diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-09 14:16:12 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-09 14:16:12 +0100 |
commit | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (patch) | |
tree | 52599cd0ab782b1768e23ad176f7618f98333cb6 /Source/WebCore/platform | |
parent | cd44dc59cdfc39534aef4d417e9f3c412e3be139 (diff) | |
download | qtwebkit-03e12282df9aa1e1fb05a8b90f1cfc2e08764cec.tar.gz |
Imported WebKit commit e09a82039aa4273ab318b71122e92d8e5f233525 (http://svn.webkit.org/repository/webkit/trunk@107223)
Diffstat (limited to 'Source/WebCore/platform')
163 files changed, 3235 insertions, 3208 deletions
diff --git a/Source/WebCore/platform/Clock.cpp b/Source/WebCore/platform/Clock.cpp index cc594e7f8..883023c3a 100644 --- a/Source/WebCore/platform/Clock.cpp +++ b/Source/WebCore/platform/Clock.cpp @@ -26,7 +26,9 @@ #include "config.h" #include "Clock.h" -#if USE(COREAUDIO) +#if USE(COREMEDIA) + #include "PlatformClockCM.h" +#elif USE(COREAUDIO) #include "PlatformClockCA.h" #else #include "ClockGeneric.h" @@ -36,7 +38,9 @@ using namespace WebCore; PassRefPtr<Clock> Clock::create() { -#if USE(COREAUDIO) +#if USE(COREMEDIA) + return adoptRef(new PlatformClockCM()); +#elif USE(COREAUDIO) return adoptRef(new PlatformClockCA()); #else return adoptRef(new ClockGeneric()); diff --git a/Source/WebCore/platform/ColorChooserClient.h b/Source/WebCore/platform/ColorChooserClient.h index e5ea2fdcf..0c5bf3623 100644 --- a/Source/WebCore/platform/ColorChooserClient.h +++ b/Source/WebCore/platform/ColorChooserClient.h @@ -13,6 +13,8 @@ class Color; class ColorChooserClient { public: + virtual ~ColorChooserClient() { } + virtual void didChooseColor(const Color&) = 0; virtual void didEndChooser() = 0; }; diff --git a/Source/WebCore/platform/Pasteboard.h b/Source/WebCore/platform/Pasteboard.h index fedfc8abd..8e5f91bb8 100644 --- a/Source/WebCore/platform/Pasteboard.h +++ b/Source/WebCore/platform/Pasteboard.h @@ -80,9 +80,8 @@ class Pasteboard { WTF_MAKE_NONCOPYABLE(Pasteboard); WTF_MAKE_FAST_ALLOCATED; public: #if PLATFORM(MAC) + // This is required to support OS X services. void writeSelectionForTypes(NSArray* pasteboardTypes, Range* selectedRange, bool canSmartCopyOrDelete, Frame*); - void writeURLForTypes(NSArray* types, const KURL&, const String& titleStr, Frame*); - Pasteboard(const String& pasteboardName); #endif @@ -91,10 +90,6 @@ public: void writePlainText(const String&); void writeURL(const KURL&, const String&, Frame* = 0); void writeImage(Node*, const KURL&, const String& title); -#if PLATFORM(MAC) - void writeFileWrapperAsRTFDAttachment(NSFileWrapper*); - String asURL(Frame*); -#endif void writeClipboard(Clipboard*); void clear(); bool canSmartReplace(); @@ -115,9 +110,6 @@ private: #if PLATFORM(MAC) RetainPtr<NSPasteboard> m_pasteboard; - PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource); - PassRefPtr<DocumentFragment> documentFragmentWithRtf(Frame* frame, NSString* pboardType); - NSURL *getBestURL(Frame *); #endif #if PLATFORM(WIN) diff --git a/Source/WebCore/platform/PlatformGestureEvent.h b/Source/WebCore/platform/PlatformGestureEvent.h index e313be50e..ed557c178 100644 --- a/Source/WebCore/platform/PlatformGestureEvent.h +++ b/Source/WebCore/platform/PlatformGestureEvent.h @@ -28,7 +28,9 @@ #if ENABLE(GESTURE_EVENTS) +#include "FloatPoint.h" #include "IntPoint.h" +#include "IntSize.h" #include "PlatformEvent.h" namespace WebCore { @@ -51,15 +53,28 @@ public: { } + PlatformGestureEvent(Type type, const IntPoint& position, const IntPoint& globalPosition, double timestamp, const IntSize& area, const FloatPoint& delta, bool shiftKey, bool ctrlKey, bool altKey, bool metaKey) + : PlatformEvent(type, shiftKey, ctrlKey, altKey, metaKey, timestamp) + , m_position(position) + , m_globalPosition(globalPosition) + , m_area(area) + , m_deltaX(delta.x()) + , m_deltaY(delta.y()) + { + } + const IntPoint& position() const { return m_position; } // PlatformWindow coordinates. const IntPoint& globalPosition() const { return m_globalPosition; } // Screen coordinates. + const IntSize& area() const { return m_area; } + float deltaX() const { return m_deltaX; } float deltaY() const { return m_deltaY; } protected: IntPoint m_position; IntPoint m_globalPosition; + IntSize m_area; float m_deltaX; float m_deltaY; }; diff --git a/Source/WebCore/platform/PlatformGestureRecognizer.h b/Source/WebCore/platform/PlatformGestureRecognizer.h deleted file mode 100644 index 0b86a9276..000000000 --- a/Source/WebCore/platform/PlatformGestureRecognizer.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2011, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef PlatformGestureRecognizer_h -#define PlatformGestureRecognizer_h - -#include "PlatformGestureEvent.h" -#include <wtf/PassOwnPtr.h> -#include <wtf/Vector.h> - -namespace WebCore { - -class EventHandler; -class PlatformTouchEvent; - -class PlatformGestureRecognizer { -protected: - PlatformGestureRecognizer(); - -public: - static PassOwnPtr<PlatformGestureRecognizer> create(); - virtual ~PlatformGestureRecognizer(); - - typedef PassOwnPtr<Vector<PlatformGestureEvent> > PassGestures; - - // Invoked for each touch event and returns 0 or more resulting gestures. - virtual PassGestures processTouchEventForGestures(const PlatformTouchEvent&, bool defaultPrevented) = 0; - - // Clears the GestureRecognizer to its initial state. - virtual void reset() = 0; -}; - -} // namespace WebCore - -#endif // PlatformGestureRecognizer_h diff --git a/Source/WebCore/platform/PlatformScreen.h b/Source/WebCore/platform/PlatformScreen.h index 827801b44..969193f1c 100644 --- a/Source/WebCore/platform/PlatformScreen.h +++ b/Source/WebCore/platform/PlatformScreen.h @@ -40,7 +40,6 @@ typedef uint32_t PlatformDisplayID; namespace WebCore { class FloatRect; - class FrameView; class Widget; int screenHorizontalDPI(Widget*); @@ -49,14 +48,14 @@ namespace WebCore { int screenDepthPerComponent(Widget*); bool screenIsMonochrome(Widget*); - FloatRect screenRect(FrameView*); - FloatRect screenAvailableRect(FrameView*); + FloatRect screenRect(Widget*); + FloatRect screenAvailableRect(Widget*); #if PLATFORM(MAC) NSScreen *screenForWindow(NSWindow *); - FloatRect toUserSpace(const NSRect&, NSWindow *destination, float deviceScaleFactor); - NSRect toDeviceSpace(const FloatRect&, NSWindow *source, float deviceScaleFactor); + FloatRect toUserSpace(const NSRect&, NSWindow *destination); + NSRect toDeviceSpace(const FloatRect&, NSWindow *source); NSPoint flipScreenPoint(const NSPoint&, NSScreen *); #endif diff --git a/Source/WebCore/platform/PlatformTouchPoint.h b/Source/WebCore/platform/PlatformTouchPoint.h index d66eb23c8..b18192d90 100644 --- a/Source/WebCore/platform/PlatformTouchPoint.h +++ b/Source/WebCore/platform/PlatformTouchPoint.h @@ -44,9 +44,11 @@ public: TouchStateEnd // Placeholder: must remain the last item. }; + // This is necessary for us to be able to build synthetic events. + PlatformTouchPoint() { }; + #if PLATFORM(QT) PlatformTouchPoint(const QTouchEvent::TouchPoint&); - PlatformTouchPoint() {}; #elif PLATFORM(EFL) PlatformTouchPoint(unsigned id, const IntPoint& windowPos, State); #endif diff --git a/Source/WebCore/platform/PopupMenuClient.h b/Source/WebCore/platform/PopupMenuClient.h index 4abe3379c..bfa24ac1b 100644 --- a/Source/WebCore/platform/PopupMenuClient.h +++ b/Source/WebCore/platform/PopupMenuClient.h @@ -22,6 +22,7 @@ #ifndef PopupMenuClient_h #define PopupMenuClient_h +#include "LayoutTypes.h" #include "PopupMenuStyle.h" #include "ScrollTypes.h" #include <wtf/Forward.h> @@ -51,8 +52,8 @@ public: virtual PopupMenuStyle menuStyle() const = 0; virtual int clientInsetLeft() const = 0; virtual int clientInsetRight() const = 0; - virtual int clientPaddingLeft() const = 0; - virtual int clientPaddingRight() const = 0; + virtual LayoutUnit clientPaddingLeft() const = 0; + virtual LayoutUnit clientPaddingRight() const = 0; virtual int listSize() const = 0; virtual int selectedIndex() const = 0; virtual void popupDidHide() = 0; diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h index ba586a4ab..cb6ab4e3d 100644 --- a/Source/WebCore/platform/ScrollView.h +++ b/Source/WebCore/platform/ScrollView.h @@ -72,8 +72,8 @@ public: // Functions for child manipulation and inspection. const HashSet<RefPtr<Widget> >* children() const { return &m_children; } - void addChild(PassRefPtr<Widget>); - void removeChild(Widget*); + virtual void addChild(PassRefPtr<Widget>); + virtual void removeChild(Widget*); // If the scroll view does not use a native widget, then it will have cross-platform Scrollbars. These functions // can be used to obtain those scrollbars. diff --git a/Source/WebCore/platform/ScrollableArea.h b/Source/WebCore/platform/ScrollableArea.h index 0b4583bbe..353b6f074 100644 --- a/Source/WebCore/platform/ScrollableArea.h +++ b/Source/WebCore/platform/ScrollableArea.h @@ -155,14 +155,15 @@ public: // Note that this only returns scrollable areas that can actually be scrolled. virtual ScrollableArea* enclosingScrollableArea() const = 0; + // Returns the bounding box of this scrollable area, in the coordinate system of the enclosing scroll view. + virtual IntRect scrollableAreaBoundingBox() const { ASSERT_NOT_REACHED(); return IntRect(); } + bool isPinnedInBothDirections(const IntSize&) const; bool isPinnedHorizontallyInDirection(int horizontalScrollDelta) const; bool isPinnedVerticallyInDirection(int verticalScrollDelta) const; virtual bool shouldRubberBandInDirection(ScrollDirection) const { return true; } - virtual void disconnectFromPage() { } - virtual bool scrollAnimatorEnabled() const { return false; } // NOTE: Only called from Internals for testing. diff --git a/Source/WebCore/platform/ScrollbarTheme.h b/Source/WebCore/platform/ScrollbarTheme.h index 9ef124276..2a83d5385 100644 --- a/Source/WebCore/platform/ScrollbarTheme.h +++ b/Source/WebCore/platform/ScrollbarTheme.h @@ -36,6 +36,10 @@ class PlatformMouseEvent; class Scrollbar; class ScrollView; +#if USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING) +class GraphicsLayer; +#endif + class ScrollbarTheme { WTF_MAKE_NONCOPYABLE(ScrollbarTheme); WTF_MAKE_FAST_ALLOCATED; public: @@ -84,6 +88,11 @@ public: virtual void paintOverhangAreas(ScrollView*, GraphicsContext*, const IntRect&, const IntRect&, const IntRect&) { } +#if USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING) + virtual void setUpOverhangAreasLayerContents(GraphicsLayer*) { } + virtual void setUpContentShadowLayer(GraphicsLayer*) { } +#endif + virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&) { return false; } virtual bool shouldSnapBackToDragOrigin(Scrollbar*, const PlatformMouseEvent&) { return false; } virtual bool shouldDragDocumentInsteadOfThumb(Scrollbar*, const PlatformMouseEvent&) { return false; } diff --git a/Source/WebCore/platform/animation/Animation.h b/Source/WebCore/platform/animation/Animation.h index 0a5f4d286..175d95a5b 100644 --- a/Source/WebCore/platform/animation/Animation.h +++ b/Source/WebCore/platform/animation/Animation.h @@ -42,7 +42,7 @@ public: static PassRefPtr<Animation> create() { return adoptRef(new Animation); } static PassRefPtr<Animation> create(const Animation* o) { return adoptRef(new Animation(*o)); } - + bool isDelaySet() const { return m_delaySet; } bool isDirectionSet() const { return m_directionSet; } bool isDurationSet() const { return m_durationSet; } @@ -96,7 +96,12 @@ public: double delay() const { return m_delay; } - enum AnimationDirection { AnimationDirectionNormal, AnimationDirectionAlternate }; + enum AnimationDirection { + AnimationDirectionNormal, + AnimationDirectionAlternate, + AnimationDirectionReverse, + AnimationDirectionAlternateReverse + }; AnimationDirection direction() const { return static_cast<AnimationDirection>(m_direction); } unsigned fillMode() const { return m_fillMode; } @@ -144,7 +149,7 @@ private: double m_delay; double m_duration; RefPtr<TimingFunction> m_timingFunction; - unsigned m_direction : 1; // AnimationDirection + unsigned m_direction : 2; // AnimationDirection unsigned m_fillMode : 2; unsigned m_playState : 2; diff --git a/Source/WebCore/platform/animation/AnimationUtilities.h b/Source/WebCore/platform/animation/AnimationUtilities.h index aebca46bb..87dabe6a6 100644 --- a/Source/WebCore/platform/animation/AnimationUtilities.h +++ b/Source/WebCore/platform/animation/AnimationUtilities.h @@ -37,7 +37,7 @@ inline int blend(int from, int to, double progress) inline unsigned blend(unsigned from, unsigned to, double progress) { - return static_cast<unsigned>(lround(static_cast<double>(from) + static_cast<double>(to - from) * progress)); + return static_cast<unsigned>(lround(to > from ? static_cast<double>(from) + static_cast<double>(to - from) * progress : static_cast<double>(from) - static_cast<double>(from - to) * progress)); } inline double blend(double from, double to, double progress) diff --git a/Source/WebCore/platform/audio/AudioBus.cpp b/Source/WebCore/platform/audio/AudioBus.cpp index eea191961..d6aa35002 100644 --- a/Source/WebCore/platform/audio/AudioBus.cpp +++ b/Source/WebCore/platform/audio/AudioBus.cpp @@ -196,21 +196,35 @@ void AudioBus::scale(float scale) // Just copies the samples from the source bus to this one. // This is just a simple copy if the number of channels match, otherwise a mixup or mixdown is done. -// For now, we just support a mixup from mono -> stereo. +// For now, we just support mixup from mono -> stereo and mixdown from stereo -> mono. void AudioBus::copyFrom(const AudioBus& sourceBus) { if (&sourceBus == this) return; - if (numberOfChannels() == sourceBus.numberOfChannels()) { - for (unsigned i = 0; i < numberOfChannels(); ++i) + unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); + unsigned numberOfDestinationChannels = numberOfChannels(); + + if (numberOfDestinationChannels == numberOfSourceChannels) { + for (unsigned i = 0; i < numberOfSourceChannels; ++i) channel(i)->copyFrom(sourceBus.channel(i)); - } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) { + } else if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) { // Handle mono -> stereo case (for now simply copy mono channel into both left and right) // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... const AudioChannel* sourceChannel = sourceBus.channel(0); channel(0)->copyFrom(sourceChannel); channel(1)->copyFrom(sourceChannel); + } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) { + // Handle stereo -> mono case. output = 0.5 * (input.L + input.R). + AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); + + const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data(); + const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data(); + + float* destination = channelByType(ChannelLeft)->mutableData(); + vadd(sourceL, 1, sourceR, 1, destination, 1, length()); + float scale = 0.5; + vsmul(destination, 1, &scale, destination, 1, length()); } else { // Case not handled ASSERT_NOT_REACHED(); @@ -219,15 +233,29 @@ void AudioBus::copyFrom(const AudioBus& sourceBus) void AudioBus::sumFrom(const AudioBus &sourceBus) { - if (numberOfChannels() == sourceBus.numberOfChannels()) { + unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); + unsigned numberOfDestinationChannels = numberOfChannels(); + + if (numberOfDestinationChannels == numberOfSourceChannels) { for (unsigned i = 0; i < numberOfChannels(); ++i) channel(i)->sumFrom(sourceBus.channel(i)); - } else if (numberOfChannels() == 2 && sourceBus.numberOfChannels() == 1) { + } else if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) { // Handle mono -> stereo case (for now simply sum mono channel into both left and right) // FIXME: Really we should apply an equal-power scaling factor here, since we're effectively panning center... const AudioChannel* sourceChannel = sourceBus.channel(0); channel(0)->sumFrom(sourceChannel); channel(1)->sumFrom(sourceChannel); + } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) { + // Handle stereo -> mono case. output += 0.5 * (input.L + input.R). + AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); + + const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data(); + const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data(); + + float* destination = channelByType(ChannelLeft)->mutableData(); + float scale = 0.5; + vsma(sourceL, 1, &scale, destination, 1, length()); + vsma(sourceR, 1, &scale, destination, 1, length()); } else { // Case not handled ASSERT_NOT_REACHED(); diff --git a/Source/WebCore/platform/audio/Biquad.cpp b/Source/WebCore/platform/audio/Biquad.cpp index 8dc1f4fb6..cfee9cfd9 100644 --- a/Source/WebCore/platform/audio/Biquad.cpp +++ b/Source/WebCore/platform/audio/Biquad.cpp @@ -188,43 +188,84 @@ void Biquad::reset() void Biquad::setLowpassParams(double cutoff, double resonance) { resonance = std::max(0.0, resonance); // can't go negative - + // Limit cutoff to 0 to 1. + cutoff = std::max(0.0, std::min(cutoff, 1.0)); + double g = pow(10.0, 0.05 * resonance); double d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); - // Compute biquad coefficients for lopass filter - double theta = piDouble * cutoff; - double sn = 0.5 * d * sin(theta); - double beta = 0.5 * (1 - sn) / (1 + sn); - double gamma = (0.5 + beta) * cos(theta); - double alpha = 0.25 * (0.5 + beta - gamma); - - m_b0 = 2 * alpha; - m_b1 = 2 * 2 * alpha; - m_b2 = 2 * alpha; - m_a1 = 2 * -gamma; - m_a2 = 2 * beta; + if (cutoff == 1) { + // When cutoff is 1, the z-transform is 1. + m_b0 = 1; + m_b1 = 0; + m_b2 = 0; + m_a1 = 0; + m_a2 = 0; + } else if (cutoff > 0) { + // Compute biquad coefficients for lowpass filter + double theta = piDouble * cutoff; + double sn = 0.5 * d * sin(theta); + double beta = 0.5 * (1 - sn) / (1 + sn); + double gamma = (0.5 + beta) * cos(theta); + double alpha = 0.25 * (0.5 + beta - gamma); + + m_b0 = 2 * alpha; + m_b1 = 2 * 2 * alpha; + m_b2 = 2 * alpha; + m_a1 = 2 * -gamma; + m_a2 = 2 * beta; + } else { + // When cutoff is zero, nothing gets through the filter, so set + // coefficients up correctly. + m_b0 = 0; + m_b1 = 0; + m_b2 = 0; + m_a1 = 0; + m_a2 = 0; + } } void Biquad::setHighpassParams(double cutoff, double resonance) { resonance = std::max(0.0, resonance); // can't go negative + // Limit cutoff to 0 to 1. + cutoff = std::max(0.0, std::min(cutoff, 1.0)); + double g = pow(10.0, 0.05 * resonance); double d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); - // Compute biquad coefficients for highpass filter - double theta = piDouble * cutoff; - double sn = 0.5 * d * sin(theta); - double beta = 0.5 * (1 - sn) / (1 + sn); - double gamma = (0.5 + beta) * cos(theta); - double alpha = 0.25 * (0.5 + beta + gamma); - - m_b0 = 2 * alpha; - m_b1 = 2 * -2 * alpha; - m_b2 = 2 * alpha; - m_a1 = 2 * -gamma; - m_a2 = 2 * beta; + if (cutoff == 1) { + // The z-transform is 0. + m_b0 = 0; + m_b1 = 0; + m_b2 = 0; + m_a1 = 0; + m_a2 = 0; + } else if (cutoff > 0) { + // Compute biquad coefficients for highpass filter + double theta = piDouble * cutoff; + double sn = 0.5 * d * sin(theta); + double beta = 0.5 * (1 - sn) / (1 + sn); + double gamma = (0.5 + beta) * cos(theta); + double alpha = 0.25 * (0.5 + beta + gamma); + + m_b0 = 2 * alpha; + m_b1 = 2 * -2 * alpha; + m_b2 = 2 * alpha; + m_a1 = 2 * -gamma; + m_a2 = 2 * beta; + } else { + // When cutoff is zero, we need to be careful because the above + // gives a quadratic divided by the same quadratic, with poles + // and zeros on the unit circle in the same place. When cutoff + // is zero, the z-transform is 1. + m_b0 = 1; + m_b1 = 0; + m_b2 = 0; + m_a1 = 0; + m_a2 = 0; + } } void Biquad::setNormalizedCoefficients(double b0, double b1, double b2, double a0, double a1, double a2) @@ -240,119 +281,222 @@ void Biquad::setNormalizedCoefficients(double b0, double b1, double b2, double a void Biquad::setLowShelfParams(double frequency, double dbGain) { - double w0 = piDouble * frequency; - + // Clip frequencies to between 0 and 1, inclusive. + frequency = std::max(0.0, std::min(frequency, 1.0)); + double A = pow(10.0, dbGain / 40); - double S = 1; // filter slope (1 is max value) - double alpha = 0.5 * sin(w0) * sqrt((A + 1 / A) * (1 / S - 1) + 2); - double k = cos(w0); - double k2 = 2 * sqrt(A) * alpha; - - double aPlusOne = A + 1; - double aMinusOne = A - 1; - - double b0 = A * (aPlusOne - aMinusOne * k + k2); - double b1 = 2 * A * (aMinusOne - aPlusOne * k); - double b2 = A * (aPlusOne - aMinusOne * k - k2); - double a0 = aPlusOne + aMinusOne * k + k2; - double a1 = -2 * (aMinusOne + aPlusOne * k); - double a2 = aPlusOne + aMinusOne * k - k2; - - setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + if (frequency == 1) { + // The z-transform is a constant gain. + setNormalizedCoefficients(A * A, 0, 0, + 1, 0, 0); + } else if (frequency > 0) { + double w0 = piDouble * frequency; + double S = 1; // filter slope (1 is max value) + double alpha = 0.5 * sin(w0) * sqrt((A + 1 / A) * (1 / S - 1) + 2); + double k = cos(w0); + double k2 = 2 * sqrt(A) * alpha; + double aPlusOne = A + 1; + double aMinusOne = A - 1; + + double b0 = A * (aPlusOne - aMinusOne * k + k2); + double b1 = 2 * A * (aMinusOne - aPlusOne * k); + double b2 = A * (aPlusOne - aMinusOne * k - k2); + double a0 = aPlusOne + aMinusOne * k + k2; + double a1 = -2 * (aMinusOne + aPlusOne * k); + double a2 = aPlusOne + aMinusOne * k - k2; + + setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + } else { + // When frequency is 0, the z-transform is 1. + setNormalizedCoefficients(1, 0, 0, + 1, 0, 0); + } } void Biquad::setHighShelfParams(double frequency, double dbGain) { - double w0 = piDouble * frequency; + // Clip frequencies to between 0 and 1, inclusive. + frequency = std::max(0.0, std::min(frequency, 1.0)); double A = pow(10.0, dbGain / 40); - double S = 1; // filter slope (1 is max value) - double alpha = 0.5 * sin(w0) * sqrt((A + 1 / A) * (1 / S - 1) + 2); - double k = cos(w0); - double k2 = 2 * sqrt(A) * alpha; - - double aPlusOne = A + 1; - double aMinusOne = A - 1; - - double b0 = A * (aPlusOne + aMinusOne * k + k2); - double b1 = -2 * A * (aMinusOne + aPlusOne * k); - double b2 = A * (aPlusOne + aMinusOne * k - k2); - double a0 = aPlusOne - aMinusOne * k + k2; - double a1 = 2 * (aMinusOne - aPlusOne * k); - double a2 = aPlusOne - aMinusOne * k - k2; - - setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + if (frequency == 1) { + // The z-transform is 1. + setNormalizedCoefficients(1, 0, 0, + 1, 0, 0); + } else if (frequency > 0) { + double w0 = piDouble * frequency; + double S = 1; // filter slope (1 is max value) + double alpha = 0.5 * sin(w0) * sqrt((A + 1 / A) * (1 / S - 1) + 2); + double k = cos(w0); + double k2 = 2 * sqrt(A) * alpha; + double aPlusOne = A + 1; + double aMinusOne = A - 1; + + double b0 = A * (aPlusOne + aMinusOne * k + k2); + double b1 = -2 * A * (aMinusOne + aPlusOne * k); + double b2 = A * (aPlusOne + aMinusOne * k - k2); + double a0 = aPlusOne - aMinusOne * k + k2; + double a1 = 2 * (aMinusOne - aPlusOne * k); + double a2 = aPlusOne - aMinusOne * k - k2; + + setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + } else { + // When frequency = 0, the filter is just a gain, A^2. + setNormalizedCoefficients(A * A, 0, 0, + 1, 0, 0); + } } void Biquad::setPeakingParams(double frequency, double Q, double dbGain) { - double w0 = piDouble * frequency; - double alpha = sin(w0) / (2 * Q); - double A = pow(10.0, dbGain / 40); + // Clip frequencies to between 0 and 1, inclusive. + frequency = std::max(0.0, std::min(frequency, 1.0)); - double k = cos(w0); + // Don't let Q go negative, which causes an unstable filter. + Q = std::max(0.0, Q); - double b0 = 1 + alpha * A; - double b1 = -2 * k; - double b2 = 1 - alpha * A; - double a0 = 1 + alpha / A; - double a1 = -2 * k; - double a2 = 1 - alpha / A; + double A = pow(10.0, dbGain / 40); - setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + if (frequency > 0 && frequency < 1) { + if (Q > 0) { + double w0 = piDouble * frequency; + double alpha = sin(w0) / (2 * Q); + double k = cos(w0); + + double b0 = 1 + alpha * A; + double b1 = -2 * k; + double b2 = 1 - alpha * A; + double a0 = 1 + alpha / A; + double a1 = -2 * k; + double a2 = 1 - alpha / A; + + setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + } else { + // When Q = 0, the above formulas have problems. If we look at + // the z-transform, we can see that the limit as Q->0 is A^2, so + // set the filter that way. + setNormalizedCoefficients(A * A, 0, 0, + 1, 0, 0); + } + } else { + // When frequency is 0 or 1, the z-transform is 1. + setNormalizedCoefficients(1, 0, 0, + 1, 0, 0); + } } void Biquad::setAllpassParams(double frequency, double Q) { - double w0 = piDouble * frequency; - double alpha = sin(w0) / (2 * Q); - - double k = cos(w0); - - double b0 = 1 - alpha; - double b1 = -2 * k; - double b2 = 1 + alpha; - double a0 = 1 + alpha; - double a1 = -2 * k; - double a2 = 1 - alpha; - - setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + // Clip frequencies to between 0 and 1, inclusive. + frequency = std::max(0.0, std::min(frequency, 1.0)); + + // Don't let Q go negative, which causes an unstable filter. + Q = std::max(0.0, Q); + + if (frequency > 0 && frequency < 1) { + if (Q > 0) { + double w0 = piDouble * frequency; + double alpha = sin(w0) / (2 * Q); + double k = cos(w0); + + double b0 = 1 - alpha; + double b1 = -2 * k; + double b2 = 1 + alpha; + double a0 = 1 + alpha; + double a1 = -2 * k; + double a2 = 1 - alpha; + + setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + } else { + // When Q = 0, the above formulas have problems. If we look at + // the z-transform, we can see that the limit as Q->0 is -1, so + // set the filter that way. + setNormalizedCoefficients(-1, 0, 0, + 1, 0, 0); + } + } else { + // When frequency is 0 or 1, the z-transform is 1. + setNormalizedCoefficients(1, 0, 0, + 1, 0, 0); + } } void Biquad::setNotchParams(double frequency, double Q) { - double w0 = piDouble * frequency; - double alpha = sin(w0) / (2 * Q); - - double k = cos(w0); - - double b0 = 1; - double b1 = -2 * k; - double b2 = 1; - double a0 = 1 + alpha; - double a1 = -2 * k; - double a2 = 1 - alpha; - - setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + // Clip frequencies to between 0 and 1, inclusive. + frequency = std::max(0.0, std::min(frequency, 1.0)); + + // Don't let Q go negative, which causes an unstable filter. + Q = std::max(0.0, Q); + + if (frequency > 0 && frequency < 1) { + if (Q > 0) { + double w0 = piDouble * frequency; + double alpha = sin(w0) / (2 * Q); + double k = cos(w0); + + double b0 = 1; + double b1 = -2 * k; + double b2 = 1; + double a0 = 1 + alpha; + double a1 = -2 * k; + double a2 = 1 - alpha; + + setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + } else { + // When Q = 0, the above formulas have problems. If we look at + // the z-transform, we can see that the limit as Q->0 is 0, so + // set the filter that way. + setNormalizedCoefficients(0, 0, 0, + 1, 0, 0); + } + } else { + // When frequency is 0 or 1, the z-transform is 1. + setNormalizedCoefficients(1, 0, 0, + 1, 0, 0); + } } void Biquad::setBandpassParams(double frequency, double Q) { - double w0 = piDouble * frequency; - double alpha = sin(w0) / (2 * Q); + // No negative frequencies allowed. + frequency = std::max(0.0, frequency); + + // Don't let Q go negative, which causes an unstable filter. + Q = std::max(0.0, Q); - double k = cos(w0); + if (frequency > 0 && frequency < 1) { + double w0 = piDouble * frequency; + if (Q > 0) { + double alpha = sin(w0) / (2 * Q); + double k = cos(w0); - double b0 = alpha; - double b1 = 0; - double b2 = -alpha; - double a0 = 1 + alpha; - double a1 = -2 * k; - double a2 = 1 - alpha; - - setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + double b0 = alpha; + double b1 = 0; + double b2 = -alpha; + double a0 = 1 + alpha; + double a1 = -2 * k; + double a2 = 1 - alpha; + + setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); + } else { + // When Q = 0, the above formulas have problems. If we look at + // the z-transform, we can see that the limit as Q->0 is 1, so + // set the filter that way. + setNormalizedCoefficients(1, 0, 0, + 1, 0, 0); + } + } else { + // When the cutoff is zero, the z-transform approaches 0, if Q + // > 0. When both Q and cutoff are zero, the z-transform is + // pretty much undefined. What should we do in this case? + // For now, just make the filter 0. When the cutoff is 1, the + // z-transform also approaches 0. + setNormalizedCoefficients(0, 0, 0, + 1, 0, 0); + } } void Biquad::setZeroPolePairs(const Complex &zero, const Complex &pole) diff --git a/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp b/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp index a7a4c1212..a322a3302 100644 --- a/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp +++ b/Source/WebCore/platform/audio/DynamicsCompressorKernel.cpp @@ -69,7 +69,7 @@ DynamicsCompressorKernel::DynamicsCompressorKernel(float sampleRate) void DynamicsCompressorKernel::setPreDelayTime(float preDelayTime) { // Re-configure look-ahead section pre-delay if delay time has changed. - unsigned preDelayFrames = preDelayTime / sampleRate(); + unsigned preDelayFrames = preDelayTime * sampleRate(); if (preDelayFrames > MaxPreDelayFrames - 1) preDelayFrames = MaxPreDelayFrames - 1; diff --git a/Source/WebCore/platform/audio/FFTFrame.h b/Source/WebCore/platform/audio/FFTFrame.h index db1d042ee..3fb3a782f 100644 --- a/Source/WebCore/platform/audio/FFTFrame.h +++ b/Source/WebCore/platform/audio/FFTFrame.h @@ -60,6 +60,10 @@ struct RDFTContext; #endif // !USE_ACCELERATE_FFT +#if USE(WEBAUDIO_IPP) +#include <ipps.h> +#endif // USE(WEBAUDIO_IPP) + #include <wtf/PassOwnPtr.h> #include <wtf/Platform.h> #include <wtf/Threading.h> @@ -161,6 +165,16 @@ private: AudioFloatArray m_imagData; #endif // USE(WEBAUDIO_GSTREAMER) +#if USE(WEBAUDIO_IPP) + Ipp8u* m_buffer; + IppsDFTSpec_R_32f* m_DFTSpec; + + float* getUpToDateComplexData(); + AudioFloatArray m_complexData; + AudioFloatArray m_realData; + AudioFloatArray m_imagData; +#endif // USE(WEBAUDIO_IPP) + #endif // !USE_ACCELERATE_FFT }; diff --git a/Source/WebCore/platform/audio/FFTFrameStub.cpp b/Source/WebCore/platform/audio/FFTFrameStub.cpp index aa26ec605..19a800d35 100644 --- a/Source/WebCore/platform/audio/FFTFrameStub.cpp +++ b/Source/WebCore/platform/audio/FFTFrameStub.cpp @@ -29,7 +29,7 @@ #if ENABLE(WEB_AUDIO) -#if !OS(DARWIN) && !USE(WEBAUDIO_MKL) && !USE(WEBAUDIO_FFMPEG) && !USE(WEBAUDIO_GSTREAMER) +#if !OS(DARWIN) && !USE(WEBAUDIO_MKL) && !USE(WEBAUDIO_FFMPEG) && !USE(WEBAUDIO_GSTREAMER) && !USE(WEBAUDIO_IPP) #include "FFTFrame.h" @@ -102,6 +102,6 @@ float* FFTFrame::imagData() const } // namespace WebCore -#endif // !OS(DARWIN) && !USE(WEBAUDIO_MKL) && !USE(WEBAUDIO_GSTREAMER) +#endif // !OS(DARWIN) && !USE(WEBAUDIO_MKL) && !USE(WEBAUDIO_FFMPEG) && !USE(WEBAUDIO_GSTREAMER) && !USE(WEBAUDIO_IPP) #endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/platform/audio/VectorMath.cpp b/Source/WebCore/platform/audio/VectorMath.cpp index 572dbf353..5693c1b89 100644 --- a/Source/WebCore/platform/audio/VectorMath.cpp +++ b/Source/WebCore/platform/audio/VectorMath.cpp @@ -418,8 +418,13 @@ void zvmul(const float* real1P, const float* imag1P, const float* real2P, const } #endif for (; i < framesToProcess; ++i) { - realDestP[i] = real1P[i] * real2P[i] - imag1P[i] * imag2P[i]; - imagDestP[i] = real1P[i] * imag2P[i] + imag1P[i] * real2P[i]; + // Read and compute result before storing them, in case the + // destination is the same as one of the sources. + float realResult = real1P[i] * real2P[i] - imag1P[i] * imag2P[i]; + float imagResult = real1P[i] * imag2P[i] + imag1P[i] * real2P[i]; + + realDestP[i] = realResult; + imagDestP[i] = imagResult; } } diff --git a/Source/WebCore/platform/audio/gstreamer/FFTFrameGStreamer.cpp b/Source/WebCore/platform/audio/gstreamer/FFTFrameGStreamer.cpp new file mode 100644 index 000000000..29374764f --- /dev/null +++ b/Source/WebCore/platform/audio/gstreamer/FFTFrameGStreamer.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2012 Igalia S.L + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// FFTFrame implementation using the GStreamer FFT library. + +#include "config.h" + +#if USE(WEBAUDIO_GSTREAMER) + +#include "FFTFrame.h" + +#include "VectorMath.h" +#include <wtf/FastAllocBase.h> + +namespace { + +size_t unpackedFFTDataSize(unsigned fftSize) +{ + return fftSize / 2 + 1; +} + +} // anonymous namespace + +namespace WebCore { + +// Normal constructor: allocates for a given fftSize. +FFTFrame::FFTFrame(unsigned fftSize) + : m_FFTSize(fftSize) + , m_log2FFTSize(static_cast<unsigned>(log2(fftSize))) + , m_realData(unpackedFFTDataSize(m_FFTSize)) + , m_imagData(unpackedFFTDataSize(m_FFTSize)) +{ + m_complexData = WTF::fastNewArray<GstFFTF32Complex>(unpackedFFTDataSize(m_FFTSize)); + + int fftLength = gst_fft_next_fast_length(m_FFTSize); + m_fft = gst_fft_f32_new(fftLength, FALSE); + m_inverseFft = gst_fft_f32_new(fftLength, TRUE); +} + +// Creates a blank/empty frame (interpolate() must later be called). +FFTFrame::FFTFrame() + : m_FFTSize(0) + , m_log2FFTSize(0) + , m_complexData(0) +{ + int fftLength = gst_fft_next_fast_length(m_FFTSize); + m_fft = gst_fft_f32_new(fftLength, FALSE); + m_inverseFft = gst_fft_f32_new(fftLength, TRUE); +} + +// Copy constructor. +FFTFrame::FFTFrame(const FFTFrame& frame) + : m_FFTSize(frame.m_FFTSize) + , m_log2FFTSize(frame.m_log2FFTSize) + , m_realData(unpackedFFTDataSize(frame.m_FFTSize)) + , m_imagData(unpackedFFTDataSize(frame.m_FFTSize)) +{ + m_complexData = WTF::fastNewArray<GstFFTF32Complex>(unpackedFFTDataSize(m_FFTSize)); + + int fftLength = gst_fft_next_fast_length(m_FFTSize); + m_fft = gst_fft_f32_new(fftLength, FALSE); + m_inverseFft = gst_fft_f32_new(fftLength, TRUE); + + // Copy/setup frame data. + memcpy(realData(), frame.realData(), sizeof(float) * unpackedFFTDataSize(m_FFTSize)); + memcpy(imagData(), frame.imagData(), sizeof(float) * unpackedFFTDataSize(m_FFTSize)); +} + +void FFTFrame::initialize() +{ +} + +void FFTFrame::cleanup() +{ +} + +FFTFrame::~FFTFrame() +{ + if (!m_fft) + return; + + gst_fft_f32_free(m_fft); + m_fft = 0; + + gst_fft_f32_free(m_inverseFft); + m_inverseFft = 0; + + WTF::fastDeleteArray(m_complexData); +} + +void FFTFrame::multiply(const FFTFrame& frame) +{ + FFTFrame& frame1 = *this; + FFTFrame& frame2 = const_cast<FFTFrame&>(frame); + + float* realP1 = frame1.realData(); + float* imagP1 = frame1.imagData(); + const float* realP2 = frame2.realData(); + const float* imagP2 = frame2.imagData(); + + size_t size = unpackedFFTDataSize(m_FFTSize); + VectorMath::zvmul(realP1, imagP1, realP2, imagP2, realP1, imagP1, size); + + // Scale accounts the peculiar scaling of vecLib on the Mac. + // This ensures the right scaling all the way back to inverse FFT. + // FIXME: if we change the scaling on the Mac then this scale + // factor will need to change too. + float scale = 0.5f; + + VectorMath::vsmul(realP1, 1, &scale, realP1, 1, size); + VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, size); +} + +void FFTFrame::doFFT(const float* data) +{ + gst_fft_f32_fft(m_fft, data, m_complexData); + + // Scale the frequency domain data to match vecLib's scale factor + // on the Mac. FIXME: if we change the definition of FFTFrame to + // eliminate this scale factor then this code will need to change. + // Also, if this loop turns out to be hot then we should use SSE + // or other intrinsics to accelerate it. + float scaleFactor = 2; + + float* imagData = m_imagData.data(); + float* realData = m_realData.data(); + for (unsigned i = 0; i < unpackedFFTDataSize(m_FFTSize); ++i) { + imagData[i] = m_complexData[i].i * scaleFactor; + realData[i] = m_complexData[i].r * scaleFactor; + } +} + +void FFTFrame::doInverseFFT(float* data) +{ + // Merge the real and imaginary vectors to complex vector. + float* realData = m_realData.data(); + float* imagData = m_imagData.data(); + + for (size_t i = 0; i < unpackedFFTDataSize(m_FFTSize); ++i) { + m_complexData[i].i = imagData[i]; + m_complexData[i].r = realData[i]; + } + + gst_fft_f32_inverse_fft(m_inverseFft, m_complexData, data); + + // Scale so that a forward then inverse FFT yields exactly the original data. + const float scaleFactor = 1.0 / (2 * m_FFTSize); + VectorMath::vsmul(data, 1, &scaleFactor, data, 1, m_FFTSize); +} + +float* FFTFrame::realData() const +{ + return const_cast<float*>(m_realData.data()); +} + +float* FFTFrame::imagData() const +{ + return const_cast<float*>(m_imagData.data()); +} + +} // namespace WebCore + +#endif // USE(WEBAUDIO_GSTREAMER) diff --git a/Source/WebCore/platform/audio/ipp/FFTFrameIPP.cpp b/Source/WebCore/platform/audio/ipp/FFTFrameIPP.cpp new file mode 100644 index 000000000..747057398 --- /dev/null +++ b/Source/WebCore/platform/audio/ipp/FFTFrameIPP.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * Copyright (C) 2012 Intel Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// FFTFrame implementation using Intel IPP's DFT algorithm, +// suitable for use on Linux. + +#include "config.h" + +#if ENABLE(WEB_AUDIO) + +#if USE(WEBAUDIO_IPP) + +#include "FFTFrame.h" + +#include "VectorMath.h" + +#include <wtf/MathExtras.h> + +namespace WebCore { + +const unsigned maximumFFTPower2Size = 24; + +// Normal constructor: allocates for a given fftSize. +FFTFrame::FFTFrame(unsigned fftSize) + : m_FFTSize(fftSize) + , m_log2FFTSize(static_cast<unsigned>(log2(fftSize))) + , m_complexData(fftSize) + , m_realData(fftSize / 2) + , m_imagData(fftSize / 2) +{ + // We only allow power of two. + ASSERT(1UL << m_log2FFTSize == m_FFTSize); + ASSERT(m_log2FFTSize <= maximumFFTPower2Size); + + ippsDFTInitAlloc_R_32f(&m_DFTSpec, m_FFTSize, IPP_FFT_NODIV_BY_ANY, ippAlgHintFast); + int bufferSize = 0; + ippsDFTGetBufSize_R_32f(m_DFTSpec, &bufferSize); + m_buffer = ippsMalloc_8u(bufferSize); +} + +// Creates a blank/empty frame (interpolate() must later be called). +FFTFrame::FFTFrame() + : m_FFTSize(0) + , m_log2FFTSize(0) +{ +} + +// Copy constructor. +FFTFrame::FFTFrame(const FFTFrame& frame) + : m_FFTSize(frame.m_FFTSize) + , m_log2FFTSize(frame.m_log2FFTSize) + , m_complexData(frame.m_FFTSize) + , m_realData(frame.m_FFTSize / 2) + , m_imagData(frame.m_FFTSize / 2) +{ + ippsDFTInitAlloc_R_32f(&m_DFTSpec, m_FFTSize, IPP_FFT_NODIV_BY_ANY, ippAlgHintFast); + int bufferSize = 0; + ippsDFTGetBufSize_R_32f(m_DFTSpec, &bufferSize); + m_buffer = ippsMalloc_8u(bufferSize); + + // Copy/setup frame data. + unsigned numberOfBytes = sizeof(float) * m_FFTSize; + memcpy(realData(), frame.realData(), numberOfBytes); + memcpy(imagData(), frame.imagData(), numberOfBytes); +} + +void FFTFrame::initialize() +{ +} + +void FFTFrame::cleanup() +{ +} + +FFTFrame::~FFTFrame() +{ + ippsFree(m_buffer); + ippsDFTFree_R_32f(m_DFTSpec); +} + +void FFTFrame::multiply(const FFTFrame& frame) +{ + FFTFrame& frame1 = *this; + FFTFrame& frame2 = const_cast<FFTFrame&>(frame); + + float* realP1 = frame1.realData(); + float* imagP1 = frame1.imagData(); + const float* realP2 = frame2.realData(); + const float* imagP2 = frame2.imagData(); + + unsigned halfSize = fftSize() / 2; + float real0 = realP1[0]; + float imag0 = imagP1[0]; + + VectorMath::zvmul(realP1, imagP1, realP2, imagP2, realP1, imagP1, halfSize); + + // Multiply the packed DC/nyquist component + realP1[0] = real0 * realP2[0]; + imagP1[0] = imag0 * imagP2[0]; + + // Scale accounts the peculiar scaling of vecLib on the Mac. + // This ensures the right scaling all the way back to inverse FFT. + // FIXME: if we change the scaling on the Mac then this scale + // factor will need to change too. + float scale = 0.5f; + + VectorMath::vsmul(realP1, 1, &scale, realP1, 1, halfSize); + VectorMath::vsmul(imagP1, 1, &scale, imagP1, 1, halfSize); +} + +void FFTFrame::doFFT(const float* data) +{ + Ipp32f* complexP = m_complexData.data(); + + // Compute Forward transform to perm format. + ippsDFTFwd_RToPerm_32f(reinterpret_cast<Ipp32f*>(const_cast<float*>(data)), complexP, m_DFTSpec, m_buffer); + + const Ipp32f scale = 2.0f; + + ippsMulC_32f_I(scale, complexP, m_FFTSize); + + Ipp32f* realP = m_realData.data(); + Ipp32f* imagP = m_imagData.data(); + ippsCplxToReal_32fc(reinterpret_cast<Ipp32fc*>(complexP), realP, imagP, m_FFTSize >> 1); +} + +void FFTFrame::doInverseFFT(float* data) +{ + Ipp32f* complexP = getUpToDateComplexData(); + + // Compute inverse transform. + ippsDFTInv_PermToR_32f(complexP, reinterpret_cast<Ipp32f*>(data), m_DFTSpec, m_buffer); + + // Scale so that a forward then inverse FFT yields exactly the original data. + const float scale = 1.0 / (2 * m_FFTSize); + + ippsMulC_32f_I(scale, reinterpret_cast<Ipp32f*>(data), m_FFTSize); +} + +float* FFTFrame::realData() const +{ + return const_cast<float*>(m_realData.data()); +} + +float* FFTFrame::imagData() const +{ + return const_cast<float*>(m_imagData.data()); +} + +float* FFTFrame::getUpToDateComplexData() +{ + int len = m_FFTSize >> 1; + // Merge the real and imagimary vectors to complex vector. + Ipp32f* realP = m_realData.data(); + Ipp32f* imagP = m_imagData.data(); + Ipp32fc* complexP = reinterpret_cast<Ipp32fc*>(m_complexData.data()); + ippsRealToCplx_32f(realP, imagP, complexP, len); + + return const_cast<float*>(m_complexData.data()); +} + +} // namespace WebCore + +#endif // USE(WEBAUDIO_IPP) + +#endif // ENABLE(WEB_AUDIO) diff --git a/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp b/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp index b2829c4e9..d26e55664 100644 --- a/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/PlatformScreenBlackBerry.cpp @@ -20,7 +20,6 @@ #include "PlatformScreen.h" #include "FloatRect.h" -#include "FrameView.h" #include "Widget.h" #include <BlackBerryPlatformScreen.h> @@ -42,12 +41,12 @@ int screenDepth(Widget*) return 24; } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { return FloatRect(FloatPoint(), FloatSize(IntSize(BlackBerry::Platform::Graphics::Screen::size()))); } -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { return FloatRect(FloatPoint(), FloatSize(IntSize(BlackBerry::Platform::Graphics::Screen::size()))); } diff --git a/Source/WebCore/platform/blackberry/SystemTimeBlackBerry.cpp b/Source/WebCore/platform/blackberry/SystemTimeBlackBerry.cpp index 930b5011c..8e794f2b4 100644 --- a/Source/WebCore/platform/blackberry/SystemTimeBlackBerry.cpp +++ b/Source/WebCore/platform/blackberry/SystemTimeBlackBerry.cpp @@ -21,13 +21,15 @@ #include "SystemTime.h" #include "NotImplemented.h" +#include <limits> namespace WebCore { float userIdleTime() { notImplemented(); - return 0; + // return an arbitrarily high userIdleTime so that releasing pages from the page cache isn't postponed. + return std::numeric_limits<float>::max(); } } // namespace WebCore diff --git a/Source/WebCore/platform/chromium/FramelessScrollView.h b/Source/WebCore/platform/chromium/FramelessScrollView.h index b0e339b64..3498475dc 100644 --- a/Source/WebCore/platform/chromium/FramelessScrollView.h +++ b/Source/WebCore/platform/chromium/FramelessScrollView.h @@ -36,7 +36,7 @@ namespace WebCore { class FramelessScrollViewClient; -#if ENABLE(GESTURE_RECOGNIZER) +#if ENABLE(GESTURE_EVENTS) class PlatformGestureEvent; #endif class PlatformKeyboardEvent; @@ -69,7 +69,7 @@ namespace WebCore { #if ENABLE(TOUCH_EVENTS) virtual bool handleTouchEvent(const PlatformTouchEvent&) = 0; #endif -#if ENABLE(GESTURE_RECOGNIZER) +#if ENABLE(GESTURE_EVENTS) virtual bool handleGestureEvent(const PlatformGestureEvent&) = 0; #endif diff --git a/Source/WebCore/platform/chromium/GestureRecognizerChromium.cpp b/Source/WebCore/platform/chromium/GestureRecognizerChromium.cpp deleted file mode 100644 index f55455d96..000000000 --- a/Source/WebCore/platform/chromium/GestureRecognizerChromium.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2011, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "GestureRecognizerChromium.h" - -namespace WebCore { - -// FIXME: Make these configurable programmatically. -static const double maximumTouchDownDurationInSecondsForClick = 0.8; -static const double minimumTouchDownDurationInSecondsForClick = 0.01; -static const double maximumSecondsBetweenDoubleClick = 0.7; -static const int maximumTouchMoveInPixelsForClick = 20; -static const float minFlickSpeedSquared = 550.f * 550.f; - -GestureRecognizerChromium::GestureRecognizerChromium() - : m_firstTouchTime(0.0) - , m_state(GestureRecognizerChromium::NoGesture) - , m_lastTouchTime(0.0) - , m_lastClickTime(0.0) - , m_lastClickPosition() - , m_lastTouchPosition() - , m_lastTouchScreenPosition() - , m_xVelocity(0.0) - , m_yVelocity(0.0) - , m_ctrlKey(false) - , m_altKey(false) - , m_shiftKey(false) - , m_metaKey(false) -{ - const unsigned FirstFinger = 0; - const PlatformTouchPoint::State Released = PlatformTouchPoint::TouchReleased; - const PlatformTouchPoint::State Pressed = PlatformTouchPoint::TouchPressed; - const PlatformTouchPoint::State Moved = PlatformTouchPoint::TouchMoved; - const PlatformTouchPoint::State Stationary = PlatformTouchPoint::TouchStationary; - const PlatformTouchPoint::State Cancelled = PlatformTouchPoint::TouchCancelled; - - addEdgeFunction(NoGesture, FirstFinger, Pressed, false, &GestureRecognizerChromium::touchDown); - addEdgeFunction(PendingSyntheticClick, FirstFinger, Cancelled, false, &GestureRecognizerChromium::noGesture); - addEdgeFunction(PendingSyntheticClick, FirstFinger, Released, false, &GestureRecognizerChromium::click); - addEdgeFunction(PendingSyntheticClick, FirstFinger, Moved, false, &GestureRecognizerChromium::isClickOrScroll); - addEdgeFunction(PendingSyntheticClick, FirstFinger, Stationary, false, &GestureRecognizerChromium::isClickOrScroll); - addEdgeFunction(Scroll, FirstFinger, Moved, false, &GestureRecognizerChromium::inScroll); - addEdgeFunction(Scroll, FirstFinger, Released, false, &GestureRecognizerChromium::scrollEnd); - addEdgeFunction(Scroll, FirstFinger, Cancelled, false, &GestureRecognizerChromium::scrollEnd); -} - -void GestureRecognizerChromium::reset() -{ - m_firstTouchTime = 0.0; - m_state = GestureRecognizerChromium::NoGesture; - m_lastTouchTime = 0.0; - m_lastTouchPosition.setX(0); - m_lastTouchPosition.setY(0); - m_lastTouchScreenPosition.setX(0); - m_lastTouchScreenPosition.setY(0); - m_xVelocity = 0.0; - m_yVelocity = 0.0; -} - -GestureRecognizerChromium::~GestureRecognizerChromium() -{ -} - -void GestureRecognizerChromium::addEdgeFunction(State state, unsigned fingerId, PlatformTouchPoint::State touchType, bool touchHandledByJavaScript, GestureTransitionFunction transitionFunction) -{ - m_edgeFunctions.add(signature(state, fingerId, touchType, touchHandledByJavaScript), transitionFunction); -} - -bool GestureRecognizerChromium::isInClickTimeWindow() -{ - double duration(m_lastTouchTime - m_firstTouchTime); - return duration >= minimumTouchDownDurationInSecondsForClick && duration < maximumTouchDownDurationInSecondsForClick; -} - -bool GestureRecognizerChromium::isInSecondClickTimeWindow() -{ - double duration(m_lastTouchTime - m_lastClickTime); - return duration < maximumSecondsBetweenDoubleClick; -} - -bool GestureRecognizerChromium::isInsideManhattanSquare(const PlatformTouchPoint& point) -{ - int manhattanDistance = abs(point.pos().x() - m_firstTouchPosition.x()) + abs(point.pos().y() - m_firstTouchPosition.y()); - return manhattanDistance < maximumTouchMoveInPixelsForClick; -} - -bool GestureRecognizerChromium::isSecondClickInsideManhattanSquare(const PlatformTouchPoint& point) -{ - int manhattanDistance = abs(point.pos().x() - m_lastClickPosition.x()) + abs(point.pos().y() - m_lastClickPosition.y()); - return manhattanDistance < maximumTouchMoveInPixelsForClick; -} - -bool GestureRecognizerChromium::isOverMinFlickSpeed() -{ - return (m_xVelocity * m_xVelocity + m_yVelocity * m_yVelocity) > minFlickSpeedSquared; -} - -void GestureRecognizerChromium::appendTapDownGestureEvent(const PlatformTouchPoint& touchPoint, Gestures gestures) -{ - gestures->append(PlatformGestureEvent(PlatformEvent::GestureTapDown, m_firstTouchPosition, m_firstTouchScreenPosition, m_lastTouchTime, 0.f, 0.f, m_shiftKey, m_ctrlKey, m_altKey, m_metaKey)); -} - -void GestureRecognizerChromium::appendClickGestureEvent(const PlatformTouchPoint& touchPoint, Gestures gestures) -{ - gestures->append(PlatformGestureEvent(PlatformEvent::GestureTap, m_firstTouchPosition, m_firstTouchScreenPosition, m_lastTouchTime, 0.f, 0.f, m_shiftKey, m_ctrlKey, m_altKey, m_metaKey)); -} - -void GestureRecognizerChromium::appendDoubleClickGestureEvent(const PlatformTouchPoint& touchPoint, Gestures gestures) -{ - gestures->append(PlatformGestureEvent(PlatformEvent::GestureDoubleTap, m_firstTouchPosition, m_firstTouchScreenPosition, m_lastTouchTime, 0.f, 0.f, m_shiftKey, m_ctrlKey, m_altKey, m_metaKey)); -} - -PlatformGestureRecognizer::PassGestures GestureRecognizerChromium::processTouchEventForGestures(const PlatformTouchEvent& event, bool defaultPrevented) -{ - m_ctrlKey = event.ctrlKey(); - m_altKey = event.altKey(); - m_shiftKey = event.shiftKey(); - m_metaKey = event.metaKey(); - - OwnPtr<Vector<PlatformGestureEvent> > gestures = adoptPtr(new Vector<PlatformGestureEvent>()); - const Vector<PlatformTouchPoint>& points = event.touchPoints(); - for (unsigned i = 0; i < points.size(); i++) { - const PlatformTouchPoint& p = points[i]; - updateValues(event.timestamp(), p); - - if (GestureTransitionFunction ef = m_edgeFunctions.get(signature(m_state, p.id(), p.state(), defaultPrevented))) - ((*this).*ef)(p, gestures.get()); - } - return gestures.release(); -} - -void GestureRecognizerChromium::appendScrollGestureBegin(const PlatformTouchPoint& touchPoint, Gestures gestures) -{ - gestures->append(PlatformGestureEvent(PlatformEvent::GestureScrollBegin, touchPoint.pos(), touchPoint.screenPos(), m_lastTouchTime, 0.f, 0.f, m_shiftKey, m_ctrlKey, m_altKey, m_metaKey)); -} - -void GestureRecognizerChromium::appendScrollGestureEnd(const PlatformTouchPoint& touchPoint, Gestures gestures, float xVelocity, float yVelocity) -{ - gestures->append(PlatformGestureEvent(PlatformEvent::GestureScrollEnd, touchPoint.pos(), touchPoint.screenPos(), m_lastTouchTime, xVelocity, yVelocity, m_shiftKey, m_ctrlKey, m_altKey, m_metaKey)); -} - -void GestureRecognizerChromium::appendScrollGestureUpdate(const PlatformTouchPoint& touchPoint, Gestures gestures) -{ - float deltaX(touchPoint.pos().x() - m_firstTouchPosition.x()); - float deltaY(touchPoint.pos().y() - m_firstTouchPosition.y()); - - gestures->append(PlatformGestureEvent(PlatformEvent::GestureScrollUpdate, touchPoint.pos(), touchPoint.screenPos(), m_lastTouchTime, deltaX, deltaY, m_shiftKey, m_ctrlKey, m_altKey, m_metaKey)); - m_firstTouchPosition = touchPoint.pos(); -} - -void GestureRecognizerChromium::updateValues(const double touchTime, const PlatformTouchPoint& touchPoint) -{ - if (m_state != NoGesture && touchPoint.state() == PlatformTouchPoint::TouchMoved) { - double interval(touchTime - m_lastTouchTime); - m_xVelocity = (touchPoint.pos().x() - m_lastTouchPosition.x()) / interval; - m_yVelocity = (touchPoint.pos().y() - m_lastTouchPosition.y()) / interval; - } - m_lastTouchTime = touchTime; - m_lastTouchPosition = touchPoint.pos(); - m_lastTouchScreenPosition = touchPoint.screenPos(); - if (state() == NoGesture) { - m_firstTouchTime = touchTime; - m_firstTouchPosition = touchPoint.pos(); - m_firstTouchScreenPosition = touchPoint.screenPos(); - m_xVelocity = 0.0; - m_yVelocity = 0.0; - } -} - -// Builds a signature. Signatures are assembled by joining together multiple bits. -// 1 LSB bit so that the computed signature is always greater than 0 -// 3 bits for the |touchType|. -// 1 bit for |handled| -// 12 bits for |id| -// 15 bits for the |gestureState|. -unsigned int GestureRecognizerChromium::signature(State gestureState, unsigned id, PlatformTouchPoint::State touchType, bool handled) -{ - ASSERT((id & 0xfff) == id); - return 1 + ((touchType & 0x7) << 1 | (handled ? 1 << 4 : 0) | ((id & 0xfff) << 5 ) | (gestureState << 17)); -} - -bool GestureRecognizerChromium::touchDown(const PlatformTouchPoint& touchPoint, Gestures gestures) -{ - appendTapDownGestureEvent(touchPoint, gestures); - setState(PendingSyntheticClick); - return false; -} - -bool GestureRecognizerChromium::scrollEnd(const PlatformTouchPoint& point, Gestures gestures) -{ - if (isOverMinFlickSpeed() && point.state() != PlatformTouchPoint::TouchCancelled) - appendScrollGestureEnd(point, gestures, m_xVelocity, m_yVelocity); - else - appendScrollGestureEnd(point, gestures, 0.f, 0.f); - setState(NoGesture); - reset(); - return false; -} - -bool GestureRecognizerChromium::noGesture(const PlatformTouchPoint&, Gestures) -{ - reset(); - return false; -} - -bool GestureRecognizerChromium::click(const PlatformTouchPoint& point, Gestures gestures) -{ - bool gestureAdded = false; - if (isInClickTimeWindow() && isInsideManhattanSquare(point)) { - gestureAdded = true; - appendClickGestureEvent(point, gestures); - if (isInSecondClickTimeWindow() && isSecondClickInsideManhattanSquare(point)) - appendDoubleClickGestureEvent(point, gestures); - m_lastClickTime = m_lastTouchTime; - m_lastClickPosition = m_lastTouchPosition; - } - reset(); - return gestureAdded; -} - -bool GestureRecognizerChromium::isClickOrScroll(const PlatformTouchPoint& point, Gestures gestures) -{ - if (isInClickTimeWindow() && isInsideManhattanSquare(point)) { - setState(GestureRecognizerChromium::PendingSyntheticClick); - return false; - } - - if (point.state() == PlatformTouchPoint::TouchMoved && !isInsideManhattanSquare(point)) { - appendScrollGestureBegin(point, gestures); - appendScrollGestureUpdate(point, gestures); - setState(Scroll); - return true; - } - return false; -} - -bool GestureRecognizerChromium::inScroll(const PlatformTouchPoint& point, Gestures gestures) -{ - appendScrollGestureUpdate(point, gestures); - return true; -} - -PassOwnPtr<PlatformGestureRecognizer> PlatformGestureRecognizer::create() -{ - GestureRecognizerChromium* gestureRecognizer = new GestureRecognizerChromium(); - return adoptPtr(gestureRecognizer); -} - -PlatformGestureRecognizer::PlatformGestureRecognizer() -{ -} - -PlatformGestureRecognizer::~PlatformGestureRecognizer() -{ -} - -} // namespace WebCore diff --git a/Source/WebCore/platform/chromium/GestureRecognizerChromium.h b/Source/WebCore/platform/chromium/GestureRecognizerChromium.h deleted file mode 100644 index 4889866f6..000000000 --- a/Source/WebCore/platform/chromium/GestureRecognizerChromium.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef GestureRecognizerChromium_h -#define GestureRecognizerChromium_h - -#include "PlatformGestureRecognizer.h" - -#include "PlatformTouchEvent.h" -#include "PlatformTouchPoint.h" -#include <wtf/HashMap.h> - -class InspectableGestureRecognizerChromium; - -namespace WebCore { - -class PlatformGestureEvent; - -class GestureRecognizerChromium : public PlatformGestureRecognizer { -public: - enum State { - NoGesture, - PendingSyntheticClick, - Scroll, - }; - - typedef Vector<PlatformGestureEvent>* Gestures; - typedef bool (GestureRecognizerChromium::*GestureTransitionFunction)(const PlatformTouchPoint&, Gestures); - - GestureRecognizerChromium(); - ~GestureRecognizerChromium(); - - virtual void reset(); - virtual PlatformGestureRecognizer::PassGestures processTouchEventForGestures(const PlatformTouchEvent&, bool defaultPrevented); - State state() { return m_state; } - -private: - friend class ::InspectableGestureRecognizerChromium; - - static unsigned int signature(State, unsigned, PlatformTouchPoint::State, bool); - void addEdgeFunction(State, unsigned finger, PlatformTouchPoint::State, bool touchHandledByJavaScript, GestureTransitionFunction); - void appendTapDownGestureEvent(const PlatformTouchPoint&, Gestures); - void appendClickGestureEvent(const PlatformTouchPoint&, Gestures); - void appendDoubleClickGestureEvent(const PlatformTouchPoint&, Gestures); - void appendScrollGestureBegin(const PlatformTouchPoint&, Gestures); - void appendScrollGestureEnd(const PlatformTouchPoint&, Gestures, float, float); - void appendScrollGestureUpdate(const PlatformTouchPoint&, Gestures); - bool isInClickTimeWindow(); - bool isInSecondClickTimeWindow(); - bool isInsideManhattanSquare(const PlatformTouchPoint&); - bool isSecondClickInsideManhattanSquare(const PlatformTouchPoint&); - bool isOverMinFlickSpeed(); - void setState(State value) { m_state = value; } - void updateValues(double touchTime, const PlatformTouchPoint&); - - bool click(const PlatformTouchPoint&, Gestures); - bool isClickOrScroll(const PlatformTouchPoint&, Gestures); - bool inScroll(const PlatformTouchPoint&, Gestures); - bool noGesture(const PlatformTouchPoint&, Gestures); - bool touchDown(const PlatformTouchPoint&, Gestures); - bool scrollEnd(const PlatformTouchPoint&, Gestures); - - WTF::HashMap<int, GestureTransitionFunction> m_edgeFunctions; - IntPoint m_firstTouchPosition; - IntPoint m_firstTouchScreenPosition; - double m_firstTouchTime; - State m_state; - double m_lastTouchTime; - double m_lastClickTime; - IntPoint m_lastClickPosition; - IntPoint m_lastTouchPosition; - IntPoint m_lastTouchScreenPosition; - float m_xVelocity; - float m_yVelocity; - - bool m_ctrlKey; - bool m_altKey; - bool m_shiftKey; - bool m_metaKey; -}; - -} // namespace WebCore - -#endif // GestureRecognizerChromium_h diff --git a/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp b/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp index e0553b930..79b9dcd3c 100644 --- a/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp +++ b/Source/WebCore/platform/chromium/PlatformScreenChromium.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "PlatformScreen.h" -#include "FrameView.h" #include "IntRect.h" #include "PlatformSupport.h" @@ -62,14 +61,14 @@ bool screenIsMonochrome(Widget* widget) return PlatformSupport::screenIsMonochrome(widget); } -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { - return PlatformSupport::screenRect(frameView); + return PlatformSupport::screenRect(widget); } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { - return PlatformSupport::screenAvailableRect(frameView); + return PlatformSupport::screenAvailableRect(widget); } } // namespace WebCore diff --git a/Source/WebCore/platform/chromium/PlatformSupport.h b/Source/WebCore/platform/chromium/PlatformSupport.h index 1f396c5d3..170177507 100644 --- a/Source/WebCore/platform/chromium/PlatformSupport.h +++ b/Source/WebCore/platform/chromium/PlatformSupport.h @@ -71,7 +71,6 @@ class Color; class Cursor; class Document; class Frame; -class FrameView; class GamepadList; class GeolocationServiceBridge; class GeolocationServiceChromium; @@ -246,8 +245,8 @@ public: static int screenDepth(Widget*); static int screenDepthPerComponent(Widget*); static bool screenIsMonochrome(Widget*); - static IntRect screenRect(FrameView*); - static IntRect screenAvailableRect(FrameView*); + static IntRect screenRect(Widget*); + static IntRect screenAvailableRect(Widget*); // SharedTimers ------------------------------------------------------- static void setSharedTimerFiredFunction(void (*func)()); diff --git a/Source/WebCore/platform/chromium/PopupContainer.cpp b/Source/WebCore/platform/chromium/PopupContainer.cpp index 59a0f60ae..e231b8506 100644 --- a/Source/WebCore/platform/chromium/PopupContainer.cpp +++ b/Source/WebCore/platform/chromium/PopupContainer.cpp @@ -292,7 +292,7 @@ bool PopupContainer::handleTouchEvent(const PlatformTouchEvent&) } #endif -#if ENABLE(GESTURE_RECOGNIZER) +#if ENABLE(GESTURE_EVENTS) // FIXME: Refactor this code to share functionality with EventHandler::handleGestureEvent. bool PopupContainer::handleGestureEvent(const PlatformGestureEvent& gestureEvent) { diff --git a/Source/WebCore/platform/chromium/PopupContainer.h b/Source/WebCore/platform/chromium/PopupContainer.h index 452e1b425..d776663f4 100644 --- a/Source/WebCore/platform/chromium/PopupContainer.h +++ b/Source/WebCore/platform/chromium/PopupContainer.h @@ -65,7 +65,7 @@ public: #if ENABLE(TOUCH_EVENTS) virtual bool handleTouchEvent(const PlatformTouchEvent&); #endif -#if ENABLE(GESTURE_RECOGNIZER) +#if ENABLE(GESTURE_EVENTS) virtual bool handleGestureEvent(const PlatformGestureEvent&); #endif diff --git a/Source/WebCore/platform/chromium/PopupListBox.cpp b/Source/WebCore/platform/chromium/PopupListBox.cpp index bc00c70ed..11164ccc3 100644 --- a/Source/WebCore/platform/chromium/PopupListBox.cpp +++ b/Source/WebCore/platform/chromium/PopupListBox.cpp @@ -186,7 +186,7 @@ bool PopupListBox::handleTouchEvent(const PlatformTouchEvent&) } #endif -#if ENABLE(GESTURE_RECOGNIZER) +#if ENABLE(GESTURE_EVENTS) bool PopupListBox::handleGestureEvent(const PlatformGestureEvent&) { return false; diff --git a/Source/WebCore/platform/chromium/PopupListBox.h b/Source/WebCore/platform/chromium/PopupListBox.h index 4cec3a41a..dd2e58ded 100644 --- a/Source/WebCore/platform/chromium/PopupListBox.h +++ b/Source/WebCore/platform/chromium/PopupListBox.h @@ -123,7 +123,7 @@ public: #if ENABLE(TOUCH_EVENTS) virtual bool handleTouchEvent(const PlatformTouchEvent&); #endif -#if ENABLE(GESTURE_RECOGNIZER) +#if ENABLE(GESTURE_EVENTS) virtual bool handleGestureEvent(const PlatformGestureEvent&); #endif diff --git a/Source/WebCore/platform/efl/LanguageEfl.cpp b/Source/WebCore/platform/efl/LanguageEfl.cpp index e6c1a7259..2b0a13dd8 100644 --- a/Source/WebCore/platform/efl/LanguageEfl.cpp +++ b/Source/WebCore/platform/efl/LanguageEfl.cpp @@ -42,13 +42,8 @@ static String platformLanguage() if (!localeDefault) return String("c"); - - char* ptr = strchr(localeDefault, '_'); - if (ptr) - *ptr = '-'; - - return String(localeDefault); + return String(localeDefault).replace('_', '-'); } Vector<String> platformUserPreferredLanguages() diff --git a/Source/WebCore/platform/efl/PlatformScreenEfl.cpp b/Source/WebCore/platform/efl/PlatformScreenEfl.cpp index f30d23da7..fac959723 100644 --- a/Source/WebCore/platform/efl/PlatformScreenEfl.cpp +++ b/Source/WebCore/platform/efl/PlatformScreenEfl.cpp @@ -34,7 +34,6 @@ #include "config.h" #include "PlatformScreen.h" -#include "FrameView.h" #include "NotImplemented.h" #include "PlatformString.h" #include "Widget.h" @@ -74,23 +73,23 @@ bool screenIsMonochrome(Widget*) return false; } -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { - if (!frameView) + if (!widget) return FloatRect(); int x, y, w, h; - Evas* e = frameView->evas(); + Evas* e = widget->evas(); ecore_evas_screen_geometry_get(ecore_evas_ecore_evas_get(e), &x, &y, &w, &h); return FloatRect(x, y, w, h); } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { notImplemented(); - return screenRect(frameView); + return screenRect(widget); } } diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.cpp b/Source/WebCore/platform/efl/RenderThemeEfl.cpp index ad662c4c2..2140fe8be 100644 --- a/Source/WebCore/platform/efl/RenderThemeEfl.cpp +++ b/Source/WebCore/platform/efl/RenderThemeEfl.cpp @@ -822,7 +822,7 @@ bool RenderThemeEfl::controlSupportsTints(const RenderObject* object) const return isEnabled(object); } -int RenderThemeEfl::baselinePosition(const RenderObject* object) const +LayoutUnit RenderThemeEfl::baselinePosition(const RenderObject* object) const { if (!object->isBox()) return 0; diff --git a/Source/WebCore/platform/efl/RenderThemeEfl.h b/Source/WebCore/platform/efl/RenderThemeEfl.h index 30a0f0d5e..cef32b85f 100644 --- a/Source/WebCore/platform/efl/RenderThemeEfl.h +++ b/Source/WebCore/platform/efl/RenderThemeEfl.h @@ -91,7 +91,7 @@ public: // A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of // controls that need to do this. - virtual int baselinePosition(const RenderObject*) const; + virtual LayoutUnit baselinePosition(const RenderObject*) const; virtual Color platformActiveSelectionBackgroundColor() const { return m_activeSelectionBackgroundColor; } virtual Color platformInactiveSelectionBackgroundColor() const { return m_inactiveSelectionBackgroundColor; } diff --git a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h index 0f4bf7d00..c638bc0fc 100644 --- a/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h +++ b/Source/WebCore/platform/graphics/ANGLEWebKitBridge.h @@ -31,7 +31,7 @@ #if PLATFORM(QT) #include "ANGLE/include/GLSLANG/ShaderLang.h" -#elif !PLATFORM(GTK) +#elif !PLATFORM(GTK) && !PLATFORM(EFL) #include "ANGLE/ShaderLang.h" #else #include "ShaderLang.h" diff --git a/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp b/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp index a8e969c20..ad1165fe4 100644 --- a/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp +++ b/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp @@ -33,19 +33,19 @@ namespace WebCore { -void GeneratorGeneratedImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp) +void GeneratorGeneratedImage::draw(GraphicsContext* destContext, const FloatRect& destRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp) { - GraphicsContextStateSaver stateSaver(*context); - context->setCompositeOperation(compositeOp); - context->clip(dstRect); - context->translate(dstRect.x(), dstRect.y()); - if (dstRect.size() != srcRect.size()) - context->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height())); - context->translate(-srcRect.x(), -srcRect.y()); - context->fillRect(FloatRect(FloatPoint(), m_size), *m_generator.get()); + GraphicsContextStateSaver stateSaver(*destContext); + destContext->setCompositeOperation(compositeOp); + destContext->clip(destRect); + destContext->translate(destRect.x(), destRect.y()); + if (destRect.size() != srcRect.size()) + destContext->scale(FloatSize(destRect.width() / srcRect.width(), destRect.height() / srcRect.height())); + destContext->translate(-srcRect.x(), -srcRect.y()); + destContext->fillRect(FloatRect(FloatPoint(), m_size), *m_generator.get()); } -void GeneratorGeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, +void GeneratorGeneratedImage::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator compositeOp, const FloatRect& destRect) { // Allow the generator to provide visually-equivalent tiling parameters for better performance. @@ -53,8 +53,16 @@ void GeneratorGeneratedImage::drawPattern(GraphicsContext* context, const FloatR FloatRect adjustedSrcRect = srcRect; m_generator->adjustParametersForTiledDrawing(adjustedSize, adjustedSrcRect); + // Factor in the destination context's scale to generate at the best resolution + AffineTransform destContextCTM = destContext->getCTM(); + double xScale = fabs(destContextCTM.xScale()); + double yScale = fabs(destContextCTM.yScale()); + AffineTransform adjustedPatternCTM = patternTransform; + adjustedPatternCTM.scale(1.0 / xScale, 1.0 / yScale); + adjustedSrcRect.scale(xScale, yScale); + // Create a BitmapImage and call drawPattern on it. - OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(adjustedSize, ColorSpaceDeviceRGB, context->isAcceleratedContext() ? Accelerated : Unaccelerated); + OwnPtr<ImageBuffer> imageBuffer = destContext->createCompatibleBuffer(adjustedSize); if (!imageBuffer) return; @@ -63,7 +71,7 @@ void GeneratorGeneratedImage::drawPattern(GraphicsContext* context, const FloatR graphicsContext->fillRect(FloatRect(FloatPoint(), adjustedSize), *m_generator.get()); // Tile the image buffer into the context. - imageBuffer->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect); + imageBuffer->drawPattern(destContext, adjustedSrcRect, adjustedPatternCTM, phase, styleColorSpace, compositeOp, destRect); } void GeneratedImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp index 475fdb3ad..f77b8a138 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.cpp +++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp @@ -754,7 +754,7 @@ PassOwnPtr<ImageBuffer> GraphicsContext::createCompatibleBuffer(const IntSize& s AffineTransform transform = getCTM(); IntSize scaledSize(static_cast<int>(ceil(size.width() * transform.xScale())), static_cast<int>(ceil(size.height() * transform.yScale()))); - OwnPtr<ImageBuffer> buffer = ImageBuffer::create(scaledSize); + OwnPtr<ImageBuffer> buffer = ImageBuffer::create(scaledSize, ColorSpaceDeviceRGB, isAcceleratedContext() ? Accelerated : Unaccelerated); if (!buffer) return nullptr; diff --git a/Source/WebCore/platform/graphics/GraphicsContext.h b/Source/WebCore/platform/graphics/GraphicsContext.h index dea950b1d..f7bef4f95 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext.h +++ b/Source/WebCore/platform/graphics/GraphicsContext.h @@ -124,6 +124,7 @@ namespace WebCore { class KURL; class GraphicsContext3D; class TextRun; + class TransformationMatrix; enum TextDrawingMode { TextModeInvisible = 0, @@ -409,6 +410,12 @@ namespace WebCore { void setCTM(const AffineTransform&); AffineTransform getCTM() const; +#if ENABLE(3D_RENDERING) && USE(TEXTURE_MAPPER) + // This is needed when using accelerated-compositing in software mode, like in TextureMapper. + void concat3DTransform(const TransformationMatrix&); + void set3DTransform(const TransformationMatrix&); + TransformationMatrix get3DTransform() const; +#endif // Create an image buffer compatible with this context, with suitable resolution // for drawing into the buffer and then into this context. PassOwnPtr<ImageBuffer> createCompatibleBuffer(const IntSize&) const; diff --git a/Source/WebCore/platform/graphics/GraphicsContext3D.h b/Source/WebCore/platform/graphics/GraphicsContext3D.h index 34c549ab4..96e66ca33 100644 --- a/Source/WebCore/platform/graphics/GraphicsContext3D.h +++ b/Source/WebCore/platform/graphics/GraphicsContext3D.h @@ -26,7 +26,6 @@ #ifndef GraphicsContext3D_h #define GraphicsContext3D_h -#include "IntSize.h" #include "GraphicsLayer.h" #include "GraphicsTypes3D.h" #include "PlatformString.h" @@ -43,7 +42,7 @@ #undef VERSION #endif -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) +#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) #include "ANGLEWebKitBridge.h" #endif @@ -57,7 +56,7 @@ QT_BEGIN_NAMESPACE class QPainter; class QRect; QT_END_NAMESPACE -#elif PLATFORM(GTK) +#elif PLATFORM(GTK) || PLATFORM(EFL) typedef unsigned int GLuint; #endif @@ -83,7 +82,7 @@ namespace WebCore { class CanvasRenderingContext; class DrawingBuffer; class Extensions3D; -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) +#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) class Extensions3DOpenGL; #endif #if PLATFORM(QT) @@ -93,6 +92,8 @@ class HostWindow; class Image; class ImageBuffer; class ImageData; +class IntRect; +class IntSize; #if USE(CAIRO) class PlatformContextCairo; #endif @@ -493,6 +494,7 @@ public: #endif #elif PLATFORM(EFL) PlatformGraphicsContext3D platformGraphicsContext3D() const; + Platform3DObject platformTexture() const { return m_texture; } #if USE(ACCELERATED_COMPOSITING) PlatformLayer* platformLayer() const; #endif @@ -505,7 +507,7 @@ public: #endif bool makeContextCurrent(); -#if PLATFORM(MAC) || PLATFORM(CHROMIUM) || PLATFORM(GTK) || PLATFORM(QT) +#if PLATFORM(MAC) || PLATFORM(CHROMIUM) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) // With multisampling on, blit from multisampleFBO to regular FBO. void prepareTexture(); #endif @@ -784,7 +786,7 @@ public: #if USE(CG) static void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef); -#elif PLATFORM(GTK) +#elif PLATFORM(GTK) || PLATFORM(EFL) void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context); #endif @@ -803,6 +805,8 @@ public: bool paintsIntoCanvasBuffer() const; #elif PLATFORM(GTK) bool paintsIntoCanvasBuffer() const { return true; } +#elif PLATFORM(EFL) + bool paintsIntoCanvasBuffer() const { return true; } #else bool paintsIntoCanvasBuffer() const { return false; } #endif @@ -893,7 +897,7 @@ public: AlphaOp alphaOp, void* destinationData); -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) +#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) // Take into account the user's requested context creation attributes, // in particular stencil and antialias, and determine which could or // could not be honored based on the capabilities of the OpenGL @@ -905,6 +909,9 @@ public: void readRenderingResults(unsigned char* pixels, int pixelsSize); #endif + bool reshapeFBOs(const IntSize&); + void resolveMultisamplingIfNecessary(const IntRect&); + int m_currentWidth, m_currentHeight; bool isResourceSafe(); @@ -913,7 +920,7 @@ public: RetainPtr<WebGLLayer> m_webGLLayer; #endif -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) +#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL) typedef struct { String source; String log; @@ -939,6 +946,10 @@ public: GC3Duint m_depthBuffer; GC3Duint m_stencilBuffer; #else +#if USE(OPENGL_ES_2) + GC3Duint m_depthBuffer; + GC3Duint m_stencilBuffer; +#endif GC3Duint m_depthStencilBuffer; #endif bool m_layerComposited; diff --git a/Source/WebCore/platform/graphics/ImageBuffer.cpp b/Source/WebCore/platform/graphics/ImageBuffer.cpp index 176de7210..5391c3815 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.cpp +++ b/Source/WebCore/platform/graphics/ImageBuffer.cpp @@ -86,7 +86,7 @@ inline void ImageBuffer::genericConvertToLuminanceMask() double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0); srcPixelArray->set(pixelOffset + 3, luma); } - putUnmultipliedImageData(srcPixelArray.get(), luminanceRect.size(), luminanceRect, IntPoint()); + putByteArray(Unmultiplied, srcPixelArray.get(), luminanceRect.size(), luminanceRect, IntPoint()); } void ImageBuffer::convertToLuminanceMask() diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h index ebc5bfa52..f97dc7939 100644 --- a/Source/WebCore/platform/graphics/ImageBuffer.h +++ b/Source/WebCore/platform/graphics/ImageBuffer.h @@ -101,8 +101,7 @@ namespace WebCore { PassRefPtr<ByteArray> getUnmultipliedImageData(const IntRect&) const; PassRefPtr<ByteArray> getPremultipliedImageData(const IntRect&) const; - void putUnmultipliedImageData(ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint); - void putPremultipliedImageData(ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint); + void putByteArray(Multiply multiplied, ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint); void convertToLuminanceMask(); diff --git a/Source/WebCore/platform/graphics/Region.cpp b/Source/WebCore/platform/graphics/Region.cpp index 5427c6c91..584a3a5fd 100644 --- a/Source/WebCore/platform/graphics/Region.cpp +++ b/Source/WebCore/platform/graphics/Region.cpp @@ -65,6 +65,18 @@ Vector<IntRect> Region::rects() const return rects; } +bool Region::contains(const Region& region) const +{ + return WebCore::intersect(region, *this) == region; +} + +bool Region::contains(const IntPoint& point) const +{ + // FIXME: This is inefficient. We should be able to iterate over the spans and find + // out if the region contains the point. + return contains(IntRect(point, IntSize(1, 1))); +} + Region::Shape::Shape() { } @@ -279,7 +291,7 @@ Region::Shape Region::Shape::shapeOperation(const Shape& shape1, const Shape& sh SegmentIterator s1 = segments1; SegmentIterator s2 = segments2; - Vector<int> segments; + Vector<int, 32> segments; // Now iterate over the segments in each span and construct a new vector of segments. while (s1 != segments1End && s2 != segments2End) { diff --git a/Source/WebCore/platform/graphics/Region.h b/Source/WebCore/platform/graphics/Region.h index b5359bbe3..8bc839578 100644 --- a/Source/WebCore/platform/graphics/Region.h +++ b/Source/WebCore/platform/graphics/Region.h @@ -47,6 +47,11 @@ public: void translate(const IntSize&); + // Returns true if the query region is a subset of this region. + bool contains(const Region&) const; + + bool contains(const IntPoint&) const; + #ifndef NDEBUG void dump() const; #endif @@ -104,13 +109,18 @@ private: bool canCoalesce(SegmentIterator begin, SegmentIterator end); - // FIXME: These vectors should have inline sizes. Figure out a good optimal value. - Vector<int> m_segments; - Vector<Span> m_spans; + Vector<int, 32> m_segments; + Vector<Span, 16> m_spans; + + friend bool operator==(const Shape&, const Shape&); }; IntRect m_bounds; Shape m_shape; + + friend bool operator==(const Region&, const Region&); + friend bool operator==(const Shape&, const Shape&); + friend bool operator==(const Span&, const Span&); }; static inline Region intersect(const Region& a, const Region& b) @@ -137,6 +147,21 @@ static inline Region translate(const Region& region, const IntSize& offset) return result; } +inline bool operator==(const Region& a, const Region& b) +{ + return a.m_bounds == b.m_bounds && a.m_shape == b.m_shape; +} + +inline bool operator==(const Region::Shape& a, const Region::Shape& b) +{ + return a.m_spans == b.m_spans && a.m_segments == b.m_segments; +} + +inline bool operator==(const Region::Span& a, const Region::Span& b) +{ + return a.y == b.y && a.segmentIndex == b.segmentIndex; +} + } // namespace WebCore #endif // Region_h diff --git a/Source/WebCore/platform/graphics/ShadowBlur.cpp b/Source/WebCore/platform/graphics/ShadowBlur.cpp index 72fdffb4e..b00231215 100644 --- a/Source/WebCore/platform/graphics/ShadowBlur.cpp +++ b/Source/WebCore/platform/graphics/ShadowBlur.cpp @@ -828,7 +828,7 @@ void ShadowBlur::blurShadowBuffer(const IntSize& templateSize) IntRect blurRect(IntPoint(), templateSize); RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect); blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4); - m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint()); + m_layerImage->putByteArray(Unmultiplied, layerData.get(), blurRect.size(), blurRect, IntPoint()); } void ShadowBlur::blurAndColorShadowBuffer(const IntSize& templateSize) diff --git a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp index 4a9a33599..47de3f871 100644 --- a/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp +++ b/Source/WebCore/platform/graphics/ca/win/PlatformCALayerWin.cpp @@ -566,6 +566,15 @@ void PlatformCALayer::setOpacity(float value) setNeedsCommit(); } +void PlatformCALayer::setFilters(const FilterOperations&) +{ +} + +bool PlatformCALayer::filtersCanBeComposited(const FilterOperations&) +{ + return false; +} + String PlatformCALayer::name() const { return CACFLayerGetName(m_layer.get()); diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp index 4c3447b72..ba886a03c 100644 --- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp @@ -1139,6 +1139,24 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const return platformContext()->imageInterpolationQuality(); } +#if ENABLE(3D_RENDERING) && USE(TEXTURE_MAPPER) +TransformationMatrix GraphicsContext::get3DTransform() const +{ + notImplemented(); + return TransformationMatrix(); +} + +void GraphicsContext::concat3DTransform(const TransformationMatrix& transform) +{ + notImplemented(); +} + +void GraphicsContext::set3DTransform(const TransformationMatrix& transform) +{ + notImplemented(); +} +#endif + } // namespace WebCore #endif // USE(CAIRO) diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp index f4d2ea22c..7ae5024a6 100644 --- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp @@ -204,12 +204,11 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect return getImageData<Premultiplied>(rect, m_data, m_size); } -template <Multiply multiplied> -void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size) +void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { - ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE); + ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE); - unsigned char* dataDst = cairo_image_surface_get_data(data.m_surface); + unsigned char* dataDst = cairo_image_surface_get_data(m_data.m_surface); ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); @@ -217,28 +216,28 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& int originx = sourceRect.x(); int destx = destPoint.x() + sourceRect.x(); ASSERT(destx >= 0); - ASSERT(destx < size.width()); + ASSERT(destx < m_size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = destPoint.x() + sourceRect.maxX(); - ASSERT(endx <= size.width()); + ASSERT(endx <= m_size.width()); int numColumns = endx - destx; int originy = sourceRect.y(); int desty = destPoint.y() + sourceRect.y(); ASSERT(desty >= 0); - ASSERT(desty < size.height()); + ASSERT(desty < m_size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = destPoint.y() + sourceRect.maxY(); - ASSERT(endy <= size.height()); + ASSERT(endy <= m_size.height()); int numRows = endy - desty; unsigned srcBytesPerRow = 4 * sourceSize.width(); - int stride = cairo_image_surface_get_stride(data.m_surface); + int stride = cairo_image_surface_get_stride(m_data.m_surface); unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; for (int y = 0; y < numRows; ++y) { @@ -257,21 +256,11 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& } srcRows += srcBytesPerRow; } - cairo_surface_mark_dirty_rectangle (data.m_surface, + cairo_surface_mark_dirty_rectangle(m_data.m_surface, destx, desty, numColumns, numRows); } -void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size); -} - -void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size); -} - #if !PLATFORM(GTK) static cairo_status_t writeFunction(void* closure, const unsigned char* data, unsigned int length) { diff --git a/Source/WebCore/platform/graphics/cairo/TextureMapperCairo.cpp b/Source/WebCore/platform/graphics/cairo/TextureMapperCairo.cpp index 61d8b205b..e72951195 100644 --- a/Source/WebCore/platform/graphics/cairo/TextureMapperCairo.cpp +++ b/Source/WebCore/platform/graphics/cairo/TextureMapperCairo.cpp @@ -115,11 +115,6 @@ void TextureMapperCairo::drawTexture(const BitmapTexture& texture, const FloatRe notImplemented(); } -PassOwnPtr<TextureMapper> TextureMapper::create(GraphicsContext* context) -{ - return adoptPtr(new TextureMapperCairo); -} - PassRefPtr<BitmapTexture> TextureMapperCairo::createTexture() { return adoptRef(new BitmapTextureCairo()); diff --git a/Source/WebCore/platform/graphics/cairo/TextureMapperGLCairo.cpp b/Source/WebCore/platform/graphics/cairo/TextureMapperGLCairo.cpp deleted file mode 100644 index 1371b6614..000000000 --- a/Source/WebCore/platform/graphics/cairo/TextureMapperGLCairo.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2011 ChangSeok Oh <shivamidow@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "TextureMapperGLCairo.h" - -#include "NotImplemented.h" - -namespace WebCore { - -BGRA32PremultimpliedBufferCairo::BGRA32PremultimpliedBufferCairo() - : m_context(0) - , m_cairoContext(0) - , m_cairoSurface(0) -{ - notImplemented(); -} - -BGRA32PremultimpliedBufferCairo::~BGRA32PremultimpliedBufferCairo() -{ - notImplemented(); -} - -PlatformGraphicsContext* BGRA32PremultimpliedBufferCairo::beginPaint(const IntRect& dirtyRect, bool opaque) -{ - notImplemented(); - return 0; -} - -void* BGRA32PremultimpliedBufferCairo::data() -{ - notImplemented(); - return 0; -} - -void BGRA32PremultimpliedBufferCairo::endPaint() -{ - notImplemented(); -} - -uint64_t uidForImage(Image* image) -{ - notImplemented(); - return 0; -} - -PassOwnPtr<BGRA32PremultimpliedBuffer> BGRA32PremultimpliedBuffer::create() -{ - notImplemented(); - return adoptPtr(new BGRA32PremultimpliedBufferCairo()); -} - -}; diff --git a/Source/WebCore/platform/graphics/cairo/TextureMapperGLCairo.h b/Source/WebCore/platform/graphics/cairo/TextureMapperGLCairo.h deleted file mode 100644 index 618806d75..000000000 --- a/Source/WebCore/platform/graphics/cairo/TextureMapperGLCairo.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 ChangSeok Oh <shivamidow@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef TextureMapperGLCairo_h -#define TextureMapperGLCairo_h - -#include "TextureMapperGL.h" - -namespace WebCore { - -class BGRA32PremultimpliedBufferCairo: public BGRA32PremultimpliedBuffer { -public: - BGRA32PremultimpliedBufferCairo(); - virtual ~BGRA32PremultimpliedBufferCairo(); - virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect, bool opaque); - virtual void endPaint(); - virtual void* data(); - -private: - PlatformContextCairo* m_context; - cairo_t* m_cairoContext; - cairo_surface_t* m_cairoSurface; -}; - -} -#endif diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp index 02ba8cffd..e9f77f301 100644 --- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp +++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp @@ -307,26 +307,38 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect return m_data.getData(rect, m_size, m_context->isAcceleratedContext(), false); } -void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) +void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { - if (m_context->isAcceleratedContext()) { - CGContextFlush(context()->platformContext()); -#if defined(BUILDING_ON_LION) - m_data.m_lastFlushTime = currentTimeMS(); -#endif + if (!m_context->isAcceleratedContext()) { + m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), multiplied == Unmultiplied); + return; } - m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), true); -} -void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - if (m_context->isAcceleratedContext()) { - CGContextFlush(context()->platformContext()); -#if defined(BUILDING_ON_LION) - m_data.m_lastFlushTime = currentTimeMS(); +#if USE(IOSURFACE_CANVAS_BACKING_STORE) + // Make a copy of the source to ensure the bits don't change before being drawn + IntSize sourceCopySize(sourceRect.width(), sourceRect.height()); + OwnPtr<ImageBuffer> sourceCopy = ImageBuffer::create(sourceCopySize, ColorSpaceDeviceRGB, Unaccelerated); + if (!sourceCopy) + return; + sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->size(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied); + + // Set up context for using drawImage as a direct bit copy + CGContextRef destContext = context()->platformContext(); + CGContextSaveGState(destContext); + CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse()); + wkCGContextResetClip(destContext); + CGContextSetInterpolationQuality(destContext, kCGInterpolationNone); + CGContextSetAlpha(destContext, 1.0); + CGContextSetBlendMode(destContext, kCGBlendModeCopy); + CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0); + + // Draw the image in CG coordinate space + IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), m_size.height() - (destPoint.y()+sourceRect.y()) - sourceRect.height()); + IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize); + RetainPtr<CGImageRef> sourceCopyImage(AdoptCF, sourceCopy->copyNativeImage()); + CGContextDrawImage(destContext, destRectInCGCoords, sourceCopyImage.get()); + CGContextRestoreGState(destContext); #endif - } - m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), false); } static inline CFStringRef jpegUTI() diff --git a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp index 0d97e52ae..00a3e463b 100644 --- a/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/BitmapCanvasLayerTextureUpdater.cpp @@ -92,7 +92,7 @@ void BitmapCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentRect borderTexels ? PlatformCanvas::Painter::GrayscaleText : PlatformCanvas::Painter::SubpixelText; PlatformCanvas::Painter canvasPainter(&m_canvas, textOption); canvasPainter.skiaContext()->setTrackOpaqueRegion(!layerIsOpaque); - paintContents(*canvasPainter.context(), contentRect, contentsScale); + paintContents(*canvasPainter.context(), *canvasPainter.skiaContext(), contentRect, contentsScale); if (!layerIsOpaque) *resultingOpaqueRect = canvasPainter.skiaContext()->opaqueRegion().asRect(); diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp index e2ab79838..4cc6bcc90 100644 --- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.cpp @@ -33,7 +33,7 @@ #include "LayerPainterChromium.h" #include "SkCanvas.h" -#include "skia/ext/platform_canvas.h" +#include "SkDevice.h" namespace WebCore { @@ -45,18 +45,21 @@ BitmapSkPictureCanvasLayerTextureUpdater::Texture::Texture(BitmapSkPictureCanvas void BitmapSkPictureCanvasLayerTextureUpdater::Texture::prepareRect(const IntRect& sourceRect) { - size_t bufferSize = TextureManager::memoryUseBytes(sourceRect.size(), texture()->format()); - m_pixelData = adoptArrayPtr(new uint8_t[bufferSize]); - OwnPtr<SkCanvas> canvas = adoptPtr(new skia::PlatformCanvas(sourceRect.width(), sourceRect.height(), false, m_pixelData.get())); + m_device = adoptPtr(new SkDevice(SkBitmap::kARGB_8888_Config, sourceRect.width(), sourceRect.height())); + OwnPtr<SkCanvas> canvas = adoptPtr(new SkCanvas(m_device.get())); textureUpdater()->paintContentsRect(canvas.get(), sourceRect); } void BitmapSkPictureCanvasLayerTextureUpdater::Texture::updateRect(GraphicsContext3D* context, TextureAllocator* allocator, const IntRect& sourceRect, const IntRect& destRect) { texture()->bindTexture(context, allocator); - ASSERT(m_pixelData.get()); - textureUpdater()->updateTextureRect(context, texture()->format(), destRect, m_pixelData.get()); - m_pixelData.clear(); + + ASSERT(m_device); + const SkBitmap* bitmap = &m_device->accessBitmap(false); + bitmap->lockPixels(); + textureUpdater()->updateTextureRect(context, texture()->format(), destRect, static_cast<uint8_t*>(bitmap->getPixels())); + bitmap->unlockPixels(); + m_device.clear(); } PassRefPtr<BitmapSkPictureCanvasLayerTextureUpdater> BitmapSkPictureCanvasLayerTextureUpdater::create(PassOwnPtr<LayerPainterChromium> painter, bool useMapTexSubImage) diff --git a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h index 1c564cdc1..8d52433d0 100644 --- a/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/BitmapSkPictureCanvasLayerTextureUpdater.h @@ -34,6 +34,8 @@ #include "PlatformColor.h" #include "SkPictureCanvasLayerTextureUpdater.h" +class SkDevice; + namespace WebCore { // This class records the contentRect into an SkPicture, then software rasterizes @@ -50,7 +52,7 @@ public: private: BitmapSkPictureCanvasLayerTextureUpdater* textureUpdater() { return m_textureUpdater; } - OwnArrayPtr<uint8_t> m_pixelData; + OwnPtr<SkDevice> m_device; BitmapSkPictureCanvasLayerTextureUpdater* m_textureUpdater; }; diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp index 6c778bf74..14fe35a58 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp @@ -41,9 +41,7 @@ #include "GraphicsContext3D.h" #include "LayerRendererChromium.h" // For the GLC() macro -#include "GrContext.h" #include "SkCanvas.h" -#include "SkDevice.h" namespace WebCore { @@ -113,33 +111,26 @@ void Canvas2DLayerChromium::paintContentsIfDirty(const Region& /* occludedScreen bool success = m_context->makeContextCurrent(); ASSERT_UNUSED(success, success); - // FIXME: Replace this block of skia code with m_canvas->flush, when that - // API becomes available. - // https://bugs.webkit.org/show_bug.cgi?id=77463 if (m_canvas) - m_canvas->getDevice()->accessRenderTarget(); // Triggers execution of pending draw operations. - - GrContext* grContext = m_context->grContext(); - if (grContext) - grContext->flush(); + m_canvas->flush(); m_context->flush(); } void Canvas2DLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) { - if (layerTreeHost() != host) - setTextureManager(host ? host->contentsTextureManager() : 0); - CanvasLayerChromium::setLayerTreeHost(host); + + if (m_useDoubleBuffering && host) + setTextureManager(host->contentsTextureManager()); } void Canvas2DLayerChromium::setTextureManager(TextureManager* textureManager) { - if (textureManager && m_useDoubleBuffering) - m_frontTexture = ManagedTexture::create(textureManager); + if (m_frontTexture) + m_frontTexture->setTextureManager(textureManager); else - m_frontTexture.clear(); + m_frontTexture = ManagedTexture::create(textureManager); } void Canvas2DLayerChromium::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater) @@ -175,12 +166,6 @@ void Canvas2DLayerChromium::unreserveContentsTexture() m_frontTexture->unreserve(); } -void Canvas2DLayerChromium::cleanupResources() -{ - if (m_useDoubleBuffering) - m_frontTexture.clear(); -} - } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h index 877224f41..11a1a9539 100644 --- a/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h @@ -61,14 +61,12 @@ public: virtual void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&); virtual void pushPropertiesTo(CCLayerImpl*); virtual void unreserveContentsTexture(); - virtual void cleanupResources(); void setCanvas(SkCanvas*); private: Canvas2DLayerChromium(GraphicsContext3D*, const IntSize&); - // Visible for testing so we can bypass setLayerTreeHost. friend class Canvas2DLayerChromiumTest; void setTextureManager(TextureManager*); diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp index 5fa67854c..ea1930365 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.cpp @@ -32,6 +32,7 @@ #include "GraphicsContext.h" #include "LayerPainterChromium.h" +#include "PlatformContextSkia.h" #include "TraceEvent.h" namespace WebCore { @@ -45,7 +46,7 @@ CanvasLayerTextureUpdater::~CanvasLayerTextureUpdater() { } -void CanvasLayerTextureUpdater::paintContents(GraphicsContext& context, const IntRect& contentRect, float contentsScale) +void CanvasLayerTextureUpdater::paintContents(GraphicsContext& context, PlatformContextSkia& platformContext, const IntRect& contentRect, float contentsScale) { context.translate(-contentRect.x(), -contentRect.y()); { @@ -62,6 +63,10 @@ void CanvasLayerTextureUpdater::paintContents(GraphicsContext& context, const In scaledContentRect = enclosingIntRect(rect); } + // Transform tracked opaque paints back to our layer's content space. + ASSERT(context.getCTM().isInvertible()); + platformContext.setOpaqueRegionTransform(context.getCTM().inverse()); + m_painter->paint(context, scaledContentRect); if (contentsScale != 1.0) diff --git a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h index 4415f6986..d491348ee 100644 --- a/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/CanvasLayerTextureUpdater.h @@ -35,6 +35,7 @@ namespace WebCore { class GraphicsContext3D; class LayerPainterChromium; +class PlatformContextSkia; // Base class for BitmapCanvasLayerTextureUpdater and // SkPictureCanvasLayerTextureUpdater that reduces code duplication between @@ -46,7 +47,7 @@ public: protected: explicit CanvasLayerTextureUpdater(PassOwnPtr<LayerPainterChromium>); - void paintContents(GraphicsContext&, const IntRect& contentRect, float contentsScale); + void paintContents(GraphicsContext&, PlatformContextSkia&, const IntRect& contentRect, float contentsScale); const IntRect& contentRect() const { return m_contentRect; } private: diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp index 34303110f..aa7fb5cf4 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp @@ -96,6 +96,7 @@ bool ContentLayerChromium::drawsContent() const void ContentLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */) { updateTileSizeAndTilingOption(); + createTextureUpdaterIfNeeded(); IntRect layerRect; @@ -122,17 +123,23 @@ void ContentLayerChromium::idlePaintContentsIfDirty() setNeedsCommit(); } -void ContentLayerChromium::createTextureUpdater(const CCLayerTreeHost* host) +void ContentLayerChromium::createTextureUpdaterIfNeeded() { + if (m_textureUpdater) + return; #if USE(SKIA) - if (host->settings().acceleratePainting) + if (layerTreeHost()->settings().acceleratePainting) m_textureUpdater = FrameBufferSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate)); - else if (host->settings().perTilePainting) - m_textureUpdater = BitmapSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate), host->layerRendererCapabilities().usingMapSub); + else if (layerTreeHost()->settings().perTilePainting) + m_textureUpdater = BitmapSkPictureCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate), layerTreeHost()->layerRendererCapabilities().usingMapSub); else #endif // USE(SKIA) - m_textureUpdater = BitmapCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate), host->layerRendererCapabilities().usingMapSub); + m_textureUpdater = BitmapCanvasLayerTextureUpdater::create(ContentLayerPainter::create(m_delegate), layerTreeHost()->layerRendererCapabilities().usingMapSub); m_textureUpdater->setOpaque(opaque()); + + GC3Denum textureFormat = layerTreeHost()->layerRendererCapabilities().bestTextureFormat; + setTextureFormat(textureFormat); + setSampledTexelFormat(textureUpdater()->sampledTexelFormat(textureFormat)); } void ContentLayerChromium::setOpaque(bool opaque) diff --git a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h index 5eff6a3d6..3e8686d0a 100644 --- a/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ContentLayerChromium.h @@ -69,8 +69,8 @@ protected: private: - virtual void createTextureUpdater(const CCLayerTreeHost*); virtual LayerTextureUpdater* textureUpdater() const { return m_textureUpdater.get(); } + virtual void createTextureUpdaterIfNeeded(); ContentLayerDelegate* m_delegate; RefPtr<LayerTextureUpdater> m_textureUpdater; diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp index 831cbe809..1e44e8702 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp @@ -160,6 +160,7 @@ void ImageLayerChromium::setContents(Image* contents) void ImageLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpace */) { + createTextureUpdaterIfNeeded(); if (m_needsDisplay) { m_textureUpdater->updateFromImage(m_contents->nativeImageForCurrentFrame()); updateTileSizeAndTilingOption(); @@ -170,6 +171,17 @@ void ImageLayerChromium::paintContentsIfDirty(const Region& /* occludedScreenSpa prepareToUpdate(visibleLayerRect()); } +void ImageLayerChromium::createTextureUpdaterIfNeeded() +{ + if (m_textureUpdater) + return; + + m_textureUpdater = ImageLayerTextureUpdater::create(layerTreeHost()->layerRendererCapabilities().usingMapSub); + GC3Denum textureFormat = layerTreeHost()->layerRendererCapabilities().bestTextureFormat; + setTextureFormat(textureFormat); + setSampledTexelFormat(textureUpdater()->sampledTexelFormat(textureFormat)); +} + LayerTextureUpdater* ImageLayerChromium::textureUpdater() const { return m_textureUpdater.get(); @@ -187,13 +199,6 @@ bool ImageLayerChromium::drawsContent() const return m_contents && TiledLayerChromium::drawsContent(); } -void ImageLayerChromium::createTextureUpdater(const CCLayerTreeHost* host) -{ - // Avoid creating a new texture updater which would not have a valid copy of the current image. - if (!m_textureUpdater) - m_textureUpdater = ImageLayerTextureUpdater::create(host->layerRendererCapabilities().usingMapSub); -} - bool ImageLayerChromium::needsContentsScale() const { // Contents scale is not need for image layer because this can be done in compositor more efficiently. diff --git a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h index ab5c1b27b..2127b857c 100644 --- a/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/ImageLayerChromium.h @@ -62,10 +62,10 @@ public: private: ImageLayerChromium(); - virtual void createTextureUpdater(const CCLayerTreeHost*); void setTilingOption(TilingOption); virtual LayerTextureUpdater* textureUpdater() const; + virtual void createTextureUpdaterIfNeeded(); virtual IntSize contentBounds() const; NativeImagePtr m_imageForCurrentFrame; diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp index b2f70141b..8d0fe03b6 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.cpp @@ -92,10 +92,6 @@ LayerChromium::~LayerChromium() removeAllChildren(); } -void LayerChromium::cleanupResources() -{ -} - void LayerChromium::setIsNonCompositedContent(bool isNonCompositedContent) { m_isNonCompositedContent = isNonCompositedContent; @@ -106,11 +102,6 @@ void LayerChromium::setLayerTreeHost(CCLayerTreeHost* host) if (m_layerTreeHost == host) return; - // If we're changing hosts then we need to free up any resources - // allocated by the old host. - if (m_layerTreeHost) - cleanupResources(); - m_layerTreeHost = host; for (size_t i = 0; i < m_children.size(); ++i) diff --git a/Source/WebCore/platform/graphics/chromium/LayerChromium.h b/Source/WebCore/platform/graphics/chromium/LayerChromium.h index 764f73015..a0758131f 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerChromium.h @@ -214,11 +214,6 @@ public: protected: LayerChromium(); - // This is called to clean up resources being held in the same context as - // layerRendererContext(). Subclasses should override this method if they - // hold context-dependent resources such as textures. - virtual void cleanupResources(); - bool isPaintedAxisAlignedInScreen() const; void setNeedsCommit(); diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp index 4f76dd9a9..1e5ee563f 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp @@ -66,7 +66,6 @@ #include "cc/CCVideoDrawQuad.h" #if USE(SKIA) #include "Extensions3D.h" -#include "GrContext.h" #include "NativeImageSkia.h" #include "PlatformContextSkia.h" #elif USE(CG) @@ -307,9 +306,9 @@ void LayerRendererChromium::viewportChanged() m_currentRenderSurface = 0; } -void LayerRendererChromium::clearSurfaceForDebug(CCRenderSurface* renderSurface, CCRenderSurface* rootRenderSurface, const FloatRect& surfaceDamageRect) +void LayerRendererChromium::clearRenderSurface(CCRenderSurface* renderSurface, CCRenderSurface* rootRenderSurface, const FloatRect& surfaceDamageRect) { - // Non-root layers should clear their entire contents to transparent. The root layer + // Non-root layers should clear their entire contents to transparent. On DEBUG builds, the root layer // is cleared to blue to easily see regions that were not drawn on the screen. If we // are using partial swap / scissor optimization, then the surface should only // clear the damaged region, so that we don't accidentally clear un-changed portions @@ -325,7 +324,11 @@ void LayerRendererChromium::clearSurfaceForDebug(CCRenderSurface* renderSurface, else GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST)); - m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); +#if defined(NDEBUG) + if (renderSurface != rootRenderSurface) +#endif + m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT); + GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST)); } @@ -375,8 +378,7 @@ void LayerRendererChromium::drawRenderPass(const CCRenderPass* renderPass) if (!useRenderSurface(renderSurface)) return; - // FIXME: eventually we should place this under a debug flag. - clearSurfaceForDebug(renderSurface, m_defaultRenderSurface, renderPass->surfaceDamageRect()); + clearRenderSurface(renderSurface, m_defaultRenderSurface, renderPass->surfaceDamageRect()); const CCQuadList& quadList = renderPass->quadList(); for (size_t i = 0; i < quadList.size(); ++i) @@ -698,10 +700,92 @@ void LayerRendererChromium::drawVideoQuad(const CCVideoDrawQuad* quad) layer->draw(this); } +struct PluginProgramBinding { + template<class Program> void set(Program* program) + { + ASSERT(program && program->initialized()); + programId = program->program(); + samplerLocation = program->fragmentShader().samplerLocation(); + matrixLocation = program->vertexShader().matrixLocation(); + alphaLocation = program->fragmentShader().alphaLocation(); + } + int programId; + int samplerLocation; + int matrixLocation; + int alphaLocation; +}; + +struct TexStretchPluginProgramBinding : PluginProgramBinding { + template<class Program> void set(Program* program) + { + PluginProgramBinding::set(program); + offsetLocation = program->vertexShader().offsetLocation(); + scaleLocation = program->vertexShader().scaleLocation(); + } + int offsetLocation; + int scaleLocation; +}; + +struct TexTransformPluginProgramBinding : PluginProgramBinding { + template<class Program> void set(Program* program) + { + PluginProgramBinding::set(program); + texTransformLocation = program->vertexShader().texTransformLocation(); + } + int texTransformLocation; +}; + void LayerRendererChromium::drawPluginQuad(const CCPluginDrawQuad* quad) { - CCLayerImpl* layer = quad->layer(); - layer->draw(this); + ASSERT(CCProxy::isImplThread()); + + if (quad->ioSurfaceTextureId()) { + TexTransformPluginProgramBinding binding; + if (quad->flipped()) + binding.set(pluginLayerTexRectProgramFlip()); + else + binding.set(pluginLayerTexRectProgram()); + + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId())); + + GLC(context(), context()->useProgram(binding.programId)); + GLC(context(), context()->uniform1i(binding.samplerLocation, 0)); + // Note: this code path ignores quad->uvRect(). + GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceWidth(), quad->ioSurfaceHeight())); + const IntSize& bounds = quad->quadRect().size(); + drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), + binding.matrixLocation, + binding.alphaLocation, + -1); + GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0)); + } else { + TexStretchPluginProgramBinding binding; + if (quad->flipped()) + binding.set(pluginLayerProgramFlip()); + else + binding.set(pluginLayerProgram()); + + GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0)); + GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId())); + + // FIXME: setting the texture parameters every time is redundant. Move this code somewhere + // where it will only happen once per texture. + GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); + GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); + GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); + GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); + + GLC(context, context()->useProgram(binding.programId)); + GLC(context, context()->uniform1i(binding.samplerLocation, 0)); + GLC(context, context()->uniform2f(binding.offsetLocation, quad->uvRect().x(), quad->uvRect().y())); + GLC(context, context()->uniform2f(binding.scaleLocation, quad->uvRect().width(), quad->uvRect().height())); + const IntSize& bounds = quad->quadRect().size(); + drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), + binding.matrixLocation, + binding.alphaLocation, + -1); + } } void LayerRendererChromium::finishDrawingFrame() diff --git a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h index c896b1df2..bea4baa41 100644 --- a/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h +++ b/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h @@ -56,10 +56,6 @@ #include <wtf/RetainPtr.h> #endif -#if USE(SKIA) -class GrContext; -#endif - namespace WebCore { class CCHeadsUpDisplay; @@ -177,7 +173,7 @@ private: void setDrawViewportRect(const IntRect&, bool flipY); bool useRenderSurface(CCRenderSurface*); - void clearSurfaceForDebug(CCRenderSurface*, CCRenderSurface* rootRenderSurface, const FloatRect& surfaceDamageRect); + void clearRenderSurface(CCRenderSurface*, CCRenderSurface* rootRenderSurface, const FloatRect& surfaceDamageRect); void releaseRenderSurfaceTextures(); diff --git a/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp b/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp index 5bb19fa87..9bc700dc9 100644 --- a/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp +++ b/Source/WebCore/platform/graphics/chromium/ManagedTexture.cpp @@ -39,6 +39,7 @@ ManagedTexture::ManagedTexture(TextureManager* manager) , m_format(0) , m_textureId(0) { + m_textureManager->registerTexture(this); } ManagedTexture::ManagedTexture(TextureManager* manager, TextureToken token, IntSize size, unsigned format, unsigned textureId) @@ -48,21 +49,41 @@ ManagedTexture::ManagedTexture(TextureManager* manager, TextureToken token, IntS , m_format(format) , m_textureId(textureId) { + m_textureManager->registerTexture(this); } ManagedTexture::~ManagedTexture() { + if (!m_textureManager) + return; + m_textureManager->unregisterTexture(this); if (m_token) m_textureManager->releaseToken(m_token); } +void ManagedTexture::setTextureManager(TextureManager* manager) +{ + if (manager == m_textureManager) + return; + + if (m_textureManager) + m_textureManager->unregisterTexture(this); + m_textureManager = manager; + clear(); + if (m_textureManager) + m_textureManager->registerTexture(this); +} + bool ManagedTexture::isValid(const IntSize& size, unsigned format) { - return m_token && size == m_size && format == m_format && m_textureManager->hasTexture(m_token); + return m_token && size == m_size && format == m_format && m_textureManager && m_textureManager->hasTexture(m_token); } bool ManagedTexture::reserve(const IntSize& size, unsigned format) { + if (!m_textureManager) + return false; + if (!m_token) m_token = m_textureManager->getToken(); @@ -71,7 +92,7 @@ bool ManagedTexture::reserve(const IntSize& size, unsigned format) m_textureManager->protectTexture(m_token); else { m_textureId = 0; - reserved = m_textureManager->requestTexture(m_token, size, format, m_textureId); + reserved = m_textureManager->requestTexture(m_token, size, format); if (reserved) { m_size = size; m_format = format; @@ -83,7 +104,7 @@ bool ManagedTexture::reserve(const IntSize& size, unsigned format) void ManagedTexture::unreserve() { - if (!m_token) + if (!m_token || !m_textureManager) return; m_textureManager->unprotectTexture(m_token); @@ -111,14 +132,18 @@ void ManagedTexture::framebufferTexture2D(GraphicsContext3D* context, TextureAll PassOwnPtr<ManagedTexture> ManagedTexture::steal() { OwnPtr<ManagedTexture> texture = adoptPtr(new ManagedTexture(m_textureManager, m_token, m_size, m_format, m_textureId)); + clear(); + return texture.release(); +} + +void ManagedTexture::clear() +{ m_token = 0; m_size = IntSize(); m_format = 0; m_textureId = 0; - return texture.release(); } - } #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/ManagedTexture.h b/Source/WebCore/platform/graphics/chromium/ManagedTexture.h index 76d62a8bb..ed4d450e9 100644 --- a/Source/WebCore/platform/graphics/chromium/ManagedTexture.h +++ b/Source/WebCore/platform/graphics/chromium/ManagedTexture.h @@ -46,13 +46,15 @@ public: } ~ManagedTexture(); + void setTextureManager(TextureManager*); + void clearManager() { m_textureManager = 0; } + bool isValid(const IntSize&, unsigned format); bool reserve(const IntSize&, unsigned format); void unreserve(); bool isReserved() { - ASSERT(m_textureManager); - return m_textureManager->isProtected(m_token); + return m_textureManager && m_textureManager->isProtected(m_token); } void allocate(TextureAllocator*); @@ -71,6 +73,8 @@ private: explicit ManagedTexture(TextureManager*); ManagedTexture(TextureManager*, TextureToken, IntSize, unsigned format, unsigned textureId); + void clear(); + TextureManager* m_textureManager; TextureToken m_token; IntSize m_size; diff --git a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h index bf4988c25..3c6f1649a 100644 --- a/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h +++ b/Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h @@ -51,7 +51,6 @@ public: bool prepareContentsTexture(); void releaseContentsTexture(); - void cleanupResources(); void draw(const IntRect& targetSurfaceRect); // Returns the rect that encloses the RenderSurface including any reflection. diff --git a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp index 0d974fa63..35cd35ad3 100644 --- a/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/SkPictureCanvasLayerTextureUpdater.cpp @@ -56,7 +56,7 @@ void SkPictureCanvasLayerTextureUpdater::prepareToUpdate(const IntRect& contentR platformContext.setDeferred(true); platformContext.setTrackOpaqueRegion(!m_layerIsOpaque); GraphicsContext graphicsContext(&platformContext); - paintContents(graphicsContext, contentRect, contentsScale); + paintContents(graphicsContext, platformContext, contentRect, contentsScale); m_picture.endRecording(); if (!m_layerIsOpaque) diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp index 516cea90a..131a9c70e 100644 --- a/Source/WebCore/platform/graphics/chromium/TextureManager.cpp +++ b/Source/WebCore/platform/graphics/chromium/TextureManager.cpp @@ -29,6 +29,7 @@ #include "TextureManager.h" #include "LayerRendererChromium.h" +#include "ManagedTexture.h" using namespace std; @@ -103,6 +104,12 @@ TextureManager::TextureManager(size_t maxMemoryLimitBytes, size_t preferredMemor { } +TextureManager::~TextureManager() +{ + for (HashSet<ManagedTexture*>::iterator it = m_registeredTextures.begin(); it != m_registeredTextures.end(); ++it) + (*it)->clearManager(); +} + void TextureManager::setMaxMemoryLimitBytes(size_t memoryLimitBytes) { reduceMemoryToLimit(memoryLimitBytes); @@ -115,6 +122,22 @@ void TextureManager::setPreferredMemoryLimitBytes(size_t memoryLimitBytes) m_preferredMemoryLimitBytes = memoryLimitBytes; } +void TextureManager::registerTexture(ManagedTexture* texture) +{ + ASSERT(texture); + ASSERT(!m_registeredTextures.contains(texture)); + + m_registeredTextures.add(texture); +} + +void TextureManager::unregisterTexture(ManagedTexture* texture) +{ + ASSERT(texture); + ASSERT(m_registeredTextures.contains(texture)); + + m_registeredTextures.remove(texture); +} + TextureToken TextureManager::getToken() { return m_nextToken++; @@ -180,30 +203,6 @@ void TextureManager::reduceMemoryToLimit(size_t limit) } } -unsigned TextureManager::replaceTexture(TextureToken newToken, TextureInfo newInfo) -{ - for (ListHashSet<TextureToken>::iterator lruIt = m_textureLRUSet.begin(); lruIt != m_textureLRUSet.end(); ++lruIt) { - TextureToken token = *lruIt; - TextureInfo info = m_textures.get(token); - if (info.isProtected) - continue; - if (!info.textureId) - continue; - if (newInfo.size != info.size || newInfo.format != info.format) - continue; - newInfo.textureId = info.textureId; -#ifndef NDEBUG - newInfo.allocator = info.allocator; -#endif - m_textures.remove(token); - m_textureLRUSet.remove(token); - m_textures.set(newToken, newInfo); - m_textureLRUSet.add(newToken); - return info.textureId; - } - return 0; -} - void TextureManager::addTexture(TextureToken token, TextureInfo info) { ASSERT(!m_textureLRUSet.contains(token)); @@ -268,10 +267,8 @@ unsigned TextureManager::allocateTexture(TextureAllocator* allocator, TextureTok return textureId; } -bool TextureManager::requestTexture(TextureToken token, IntSize size, unsigned format, unsigned& textureId) +bool TextureManager::requestTexture(TextureToken token, IntSize size, unsigned format) { - textureId = 0; - if (size.width() > m_maxTextureSize || size.height() > m_maxTextureSize) return false; @@ -297,13 +294,6 @@ bool TextureManager::requestTexture(TextureToken token, IntSize size, unsigned f #ifndef NDEBUG info.allocator = 0; #endif - // Avoid churning by reusing the texture if it is about to be reclaimed and - // it has the same size and format as the requesting texture. - if (m_memoryUseBytes + memoryRequiredBytes > m_preferredMemoryLimitBytes) { - textureId = replaceTexture(token, info); - if (textureId) - return true; - } addTexture(token, info); return true; } diff --git a/Source/WebCore/platform/graphics/chromium/TextureManager.h b/Source/WebCore/platform/graphics/chromium/TextureManager.h index a66e9d536..8259adb10 100644 --- a/Source/WebCore/platform/graphics/chromium/TextureManager.h +++ b/Source/WebCore/platform/graphics/chromium/TextureManager.h @@ -31,10 +31,13 @@ #include <wtf/FastAllocBase.h> #include <wtf/HashMap.h> +#include <wtf/HashSet.h> #include <wtf/ListHashSet.h> +#include <wtf/Vector.h> namespace WebCore { +class ManagedTexture; typedef int TextureToken; class TextureAllocator { @@ -53,6 +56,7 @@ public: { return adoptPtr(new TextureManager(maxMemoryLimitBytes, preferredMemoryLimitBytes, maxTextureSize)); } + ~TextureManager(); // Absolute maximum limit for texture allocations for this instance. static size_t highLimitBytes(const IntSize& viewportSize); @@ -68,11 +72,14 @@ public: void setPreferredMemoryLimitBytes(size_t); size_t preferredMemoryLimitBytes() { return m_preferredMemoryLimitBytes; } + void registerTexture(ManagedTexture*); + void unregisterTexture(ManagedTexture*); + TextureToken getToken(); void releaseToken(TextureToken); bool hasTexture(TextureToken); - bool requestTexture(TextureToken, IntSize, GC3Denum textureFormat, unsigned& textureId); + bool requestTexture(TextureToken, IntSize, GC3Denum textureFormat); void protectTexture(TextureToken); void unprotectTexture(TextureToken); @@ -102,7 +109,8 @@ private: void addTexture(TextureToken, TextureInfo); void removeTexture(TextureToken, TextureInfo); - unsigned replaceTexture(TextureToken, TextureInfo); + + HashSet<ManagedTexture*> m_registeredTextures; typedef HashMap<TextureToken, TextureInfo> TextureMap; TextureMap m_textures; diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp index 283aa8dd0..d9e2487d8 100644 --- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp +++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp @@ -53,7 +53,11 @@ namespace WebCore { class UpdatableTile : public CCLayerTilingData::Tile { WTF_MAKE_NONCOPYABLE(UpdatableTile); public: - explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture) : m_texture(texture) { } + explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture) + : m_partialUpdate(false) + , m_texture(texture) + { + } LayerTextureUpdater::Texture* texture() { return m_texture.get(); } ManagedTexture* managedTexture() { return m_texture->texture(); } @@ -68,6 +72,7 @@ public: IntRect m_dirtyRect; IntRect m_updateRect; IntRect m_opaqueRect; + bool m_partialUpdate; private: OwnPtr<LayerTextureUpdater::Texture> m_texture; }; @@ -92,15 +97,6 @@ PassRefPtr<CCLayerImpl> TiledLayerChromium::createCCLayerImpl() return CCTiledLayerImpl::create(id()); } -void TiledLayerChromium::cleanupResources() -{ - LayerChromium::cleanupResources(); - - m_tiler->reset(); - m_paintRect = IntRect(); - m_requestedUpdateTilesRect = IntRect(); -} - void TiledLayerChromium::updateTileSizeAndTilingOption() { const IntSize tileSize(min(defaultTileSize, contentBounds().width()), min(defaultTileSize, contentBounds().height())); @@ -174,21 +170,6 @@ IntSize TiledLayerChromium::contentBounds() const return IntSize(lroundf(bounds().width() * contentsScale()), lroundf(bounds().height() * contentsScale())); } -void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) -{ - if (host == layerTreeHost()) - return; - - LayerChromium::setLayerTreeHost(host); - - if (!host) - return; - - createTextureUpdater(host); - setTextureFormat(host->layerRendererCapabilities().bestTextureFormat); - m_sampledTexelFormat = textureUpdater()->sampledTexelFormat(m_textureFormat); -} - void TiledLayerChromium::updateCompositorResources(GraphicsContext3D*, CCTextureUpdater& updater) { // Painting could cause compositing to get turned off, which may cause the tiler to become invalidated mid-update. @@ -234,7 +215,10 @@ void TiledLayerChromium::updateCompositorResources(GraphicsContext3D*, CCTexture if (paintOffset.y() + destRect.height() > m_paintRect.height()) CRASH(); - updater.append(tile->texture(), sourceRect, destRect); + if (tile->m_partialUpdate) + updater.appendPartial(tile->texture(), sourceRect, destRect); + else + updater.append(tile->texture(), sourceRect, destRect); } } @@ -264,18 +248,23 @@ void TiledLayerChromium::pushPropertiesTo(CCLayerImpl* layer) tiledLayer->setSkipsDraw(m_skipsDraw); tiledLayer->setContentsSwizzled(m_sampledTexelFormat != LayerTextureUpdater::SampledTexelFormatRGBA); tiledLayer->setTilingData(*m_tiler); + Vector<UpdatableTile*> invalidTiles; for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { int i = iter->first.first; int j = iter->first.second; UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); - if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) + if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) { + invalidTiles.append(tile); continue; + } if (tile->isDirty()) continue; tiledLayer->pushTileProperties(i, j, tile->managedTexture()->textureId(), tile->m_opaqueRect); } + for (Vector<UpdatableTile*>::const_iterator iter = invalidTiles.begin(); iter != invalidTiles.end(); ++iter) + m_tiler->takeTile((*iter)->i(), (*iter)->j()); } TextureManager* TiledLayerChromium::textureManager() const @@ -285,6 +274,17 @@ TextureManager* TiledLayerChromium::textureManager() const return layerTreeHost()->contentsTextureManager(); } +void TiledLayerChromium::setLayerTreeHost(CCLayerTreeHost* host) +{ + if (host && host != layerTreeHost()) { + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { + UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); + tile->managedTexture()->setTextureManager(host->contentsTextureManager()); + } + } + LayerChromium::setLayerTreeHost(host); +} + UpdatableTile* TiledLayerChromium::tileAt(int i, int j) const { return static_cast<UpdatableTile*>(m_tiler->tileAt(i, j)); @@ -322,20 +322,16 @@ void TiledLayerChromium::setIsNonCompositedContent(bool isNonCompositedContent) void TiledLayerChromium::invalidateRect(const IntRect& layerRect) { + updateBounds(); if (m_tiler->isEmpty() || layerRect.isEmpty() || m_skipsDraw) return; - int left, top, right, bottom; - m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); - for (int j = top; j <= bottom; ++j) { - for (int i = left; i <= right; ++i) { - UpdatableTile* tile = tileAt(i, j); - if (!tile) - continue; - IntRect bound = m_tiler->tileRect(tile); - bound.intersect(layerRect); - tile->m_dirtyRect.unite(bound); - } + for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { + UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); + ASSERT(tile); + IntRect bound = m_tiler->tileRect(tile); + bound.intersect(layerRect); + tile->m_dirtyRect.unite(bound); } } @@ -363,14 +359,46 @@ void TiledLayerChromium::protectTileTextures(const IntRect& layerRect) } } +// Returns true if tile is dirty and only part of it needs to be updated. +bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile) +{ + if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) + return false; + + if (!tile->isDirty()) + return false; + + return !tile->m_dirtyRect.contains(m_tiler->tileRect(tile)); +} + +// Dirty tiles with valid textures needs buffered update to guarantee that +// we don't modify textures currently used for drawing by the impl thread. +bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile) +{ + // No impl thread?. + if (!CCProxy::hasImplThread()) + return false; + + if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) + return false; + + if (!tile->isDirty()) + return false; + + return true; +} + void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom) { // Reset m_updateRect for all tiles. for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) { UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get()); tile->m_updateRect = IntRect(); + tile->m_partialUpdate = false; } + createTextureUpdaterIfNeeded(); + // Create tiles as needed, expanding a dirty rect to contain all // the dirty regions currently being drawn. All dirty tiles that are to be painted // get their m_updateRect set to m_dirtyRect and m_dirtyRect cleared. This way if @@ -382,9 +410,11 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int if (!tile) tile = createTile(i, j); - // Do post commit deletion of current texture when partial texture - // updates are not used. - if (tile->isDirty() && layerTreeHost() && !layerTreeHost()->settings().partialTextureUpdates) + // FIXME: Decide if partial update should be allowed based on cost + // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 + if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost() && layerTreeHost()->requestPartialTextureUpdate()) + tile->m_partialUpdate = true; + else if (tileNeedsBufferedUpdate(tile) && layerTreeHost()) layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal()); if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat)) @@ -397,7 +427,9 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int // layer so that checkerboarded tiles will still draw. if (!backgroundCoversViewport()) m_skipsDraw = true; - cleanupResources(); + m_tiler->reset(); + m_paintRect = IntRect(); + m_requestedUpdateTilesRect = IntRect(); } return; } @@ -473,6 +505,7 @@ void TiledLayerChromium::reserveTextures() int left, top, right, bottom; m_tiler->layerRectToTileIndices(layerRect, left, top, right, bottom); + createTextureUpdaterIfNeeded(); for (int j = top; j <= bottom; ++j) { for (int i = left; i <= right; ++i) { UpdatableTile* tile = tileAt(i, j); diff --git a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h index 3cbbbcbd7..2d9995367 100644 --- a/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h +++ b/Source/WebCore/platform/graphics/chromium/TiledLayerChromium.h @@ -58,6 +58,8 @@ public: virtual void setIsNonCompositedContent(bool); + virtual void setLayerTreeHost(CCLayerTreeHost*); + // Reserves all existing and valid tile textures to protect them from being // recycled by the texture manager. void protectTileTextures(const IntRect& layerRect); @@ -69,7 +71,6 @@ public: protected: TiledLayerChromium(); - virtual void cleanupResources(); void updateTileSizeAndTilingOption(); void updateBounds(); @@ -77,9 +78,10 @@ protected: void setTileSize(const IntSize&); void setTextureFormat(GC3Denum textureFormat) { m_textureFormat = textureFormat; } void setBorderTexelOption(CCLayerTilingData::BorderTexelOption); + void setSampledTexelFormat(LayerTextureUpdater::SampledTexelFormat sampledTexelFormat) { m_sampledTexelFormat = sampledTexelFormat; } - virtual void createTextureUpdater(const CCLayerTreeHost*) = 0; virtual LayerTextureUpdater* textureUpdater() const = 0; + virtual void createTextureUpdaterIfNeeded() = 0; // Set invalidations to be potentially repainted during update(). void invalidateRect(const IntRect& layerRect); @@ -102,11 +104,12 @@ protected: private: virtual PassRefPtr<CCLayerImpl> createCCLayerImpl(); - virtual void setLayerTreeHost(CCLayerTreeHost*); - void createTilerIfNeeded(); void setTilingOption(TilingOption); + bool tileOnlyNeedsPartialUpdate(UpdatableTile*); + bool tileNeedsBufferedUpdate(UpdatableTile*); + void prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom); IntRect idlePaintRect(const IntRect& visibleLayerRect); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp index 17226aa82..2d6f43f31 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp @@ -46,6 +46,7 @@ PassOwnPtr<CCDamageTracker> CCDamageTracker::create() } CCDamageTracker::CCDamageTracker() + : m_forceFullDamageNextUpdate(false) { m_currentRectHistory = adoptPtr(new RectMap); m_nextRectHistory = adoptPtr(new RectMap); @@ -55,13 +56,13 @@ CCDamageTracker::~CCDamageTracker() { } -void CCDamageTracker::updateDamageRectForNextFrame(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer) +void CCDamageTracker::updateDamageTrackingState(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer) { // - // This function computes the "damage rect" of a target surface. The damage - // rect is the region of the surface that may have changed and needs to be redrawn. - // This can be used to scissor what is actually drawn, to save GPU computation and - // bandwidth. + // This function computes the "damage rect" of a target surface, and updates the state + // that is used to correctly track damage across frames. The damage rect is the region + // of the surface that may have changed and needs to be redrawn. This can be used to + // scissor what is actually drawn, to save GPU computation and bandwidth. // // The surface's damage rect is computed as the union of all possible changes that // have happened to the surface since the last frame was drawn. This includes: @@ -120,21 +121,27 @@ void CCDamageTracker::updateDamageRectForNextFrame(const Vector<RefPtr<CCLayerIm // damage tracker is ready for the next frame. // + // These functions cannot be bypassed with early-exits, even if we know what the + // damage will be for this frame, because we need to update the damage tracker state + // to correctly track the next frame. + FloatRect damageFromActiveLayers = trackDamageFromActiveLayers(layerList, targetSurfaceLayerID); + FloatRect damageFromSurfaceMask = trackDamageFromSurfaceMask(targetSurfaceMaskLayer); + FloatRect damageFromLeftoverRects = trackDamageFromLeftoverRects(); + // If the target surface already knows its entire region is damaged, we can return early. // FIXME: this should go away, or will be cleaner, after refactoring into RenderPass/RenderSchedule. CCLayerImpl* layer = layerList[0].get(); - if (layer->targetRenderSurface()->surfacePropertyChangedOnlyFromDescendant()) { - m_currentDamageRect = FloatRect(layer->targetRenderSurface()->contentRect()); - return; - } - - FloatRect damageFromActiveLayers = computeDamageFromActiveLayers(layerList, targetSurfaceLayerID); - FloatRect damageFromSurfaceMask = computeDamageFromSurfaceMask(targetSurfaceMaskLayer); - FloatRect damageFromLeftoverRects = computeDamageFromLeftoverRects(); + CCRenderSurface* targetSurface = layer->targetRenderSurface(); - m_currentDamageRect = damageFromActiveLayers; - m_currentDamageRect.uniteIfNonZero(damageFromSurfaceMask); - m_currentDamageRect.uniteIfNonZero(damageFromLeftoverRects); + if (m_forceFullDamageNextUpdate || targetSurface->surfacePropertyChangedOnlyFromDescendant()) { + m_currentDamageRect = FloatRect(targetSurface->contentRect()); + m_forceFullDamageNextUpdate = false; + } else { + // FIXME: can we need to clamp this damage to the surface's content rect? (affects performance, but not correctness) + m_currentDamageRect = damageFromActiveLayers; + m_currentDamageRect.uniteIfNonZero(damageFromSurfaceMask); + m_currentDamageRect.uniteIfNonZero(damageFromLeftoverRects); + } // The next history map becomes the current map for the next frame. swap(m_currentRectHistory, m_nextRectHistory); @@ -154,7 +161,7 @@ void CCDamageTracker::saveRectForNextFrame(int layerID, const FloatRect& targetS m_nextRectHistory->set(layerID, targetSpaceRect); } -FloatRect CCDamageTracker::computeDamageFromActiveLayers(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID) +FloatRect CCDamageTracker::trackDamageFromActiveLayers(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID) { FloatRect damageRect = FloatRect(); @@ -170,7 +177,7 @@ FloatRect CCDamageTracker::computeDamageFromActiveLayers(const Vector<RefPtr<CCL return damageRect; } -FloatRect CCDamageTracker::computeDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer) +FloatRect CCDamageTracker::trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer) { FloatRect damageRect = FloatRect(); @@ -186,7 +193,7 @@ FloatRect CCDamageTracker::computeDamageFromSurfaceMask(CCLayerImpl* targetSurfa return damageRect; } -FloatRect CCDamageTracker::computeDamageFromLeftoverRects() +FloatRect CCDamageTracker::trackDamageFromLeftoverRects() { // After computing damage for all active layers, any leftover items in the current // rect history correspond to layers/surfaces that no longer exist. So, these regions diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h index 42eb448c0..d428f26d1 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h @@ -43,20 +43,21 @@ public: static PassOwnPtr<CCDamageTracker> create(); ~CCDamageTracker(); - void updateDamageRectForNextFrame(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer); + void forceFullDamageNextUpdate() { m_forceFullDamageNextUpdate = true; } + void updateDamageTrackingState(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer); const FloatRect& currentDamageRect() { return m_currentDamageRect; } private: CCDamageTracker(); - FloatRect computeDamageFromActiveLayers(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID); - FloatRect computeDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer); - FloatRect computeDamageFromLeftoverRects(); + FloatRect trackDamageFromActiveLayers(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID); + FloatRect trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer); + FloatRect trackDamageFromLeftoverRects(); FloatRect removeRectFromCurrentFrame(int layerID); void saveRectForNextFrame(int layerID, const FloatRect& targetSpaceRect); - // These helper functions are used only in computeDamageFromActiveLayers(). + // These helper functions are used only in trackDamageFromActiveLayers(). void extendDamageForLayer(CCLayerImpl*, FloatRect& targetDamageRect); void extendDamageForRenderSurface(CCLayerImpl*, FloatRect& targetDamageRect); @@ -68,6 +69,7 @@ private: OwnPtr<RectMap> m_nextRectHistory; FloatRect m_currentDamageRect; + bool m_forceFullDamageNextUpdate; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h index 00e0adf8a..7bae20174 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h @@ -72,6 +72,7 @@ public: #endif PassOwnPtr<CCSharedQuadState> createSharedQuadState() const; + virtual void willDraw(LayerRendererChromium*) { } virtual void appendQuads(CCQuadList&, const CCSharedQuadState*); void appendDebugBorderQuad(CCQuadList&, const CCSharedQuadState*) const; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp index 92637fc83..27705f324 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp @@ -117,6 +117,17 @@ IntRect CCLayerTilingData::tileRect(const Tile* tile) const void CCLayerTilingData::setBounds(const IntSize& size) { m_tilingData.setTotalSize(size.width(), size.height()); + + // Any tiles completely outside our new bounds are invalid and should be dropped. + int left, top, right, bottom; + layerRectToTileIndices(IntRect(IntPoint(), size), left, top, right, bottom); + Vector<TileMapKey> invalidTileKeys; + for (TileMap::const_iterator it = m_tiles.begin(); it != m_tiles.end(); ++it) { + if (it->first.first > right || it->first.second > bottom) + invalidTileKeys.append(it->first); + } + for (size_t i = 0; i < invalidTileKeys.size(); ++i) + m_tiles.remove(invalidTileKeys[i]); } IntSize CCLayerTilingData::bounds() const diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp index 4ff8434b2..15a3074eb 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp @@ -39,6 +39,8 @@ #include "cc/CCThread.h" #include "cc/CCThreadProxy.h" +using namespace std; + namespace { static int numLayerTreeInstances; } @@ -63,6 +65,7 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings , m_animating(false) , m_client(client) , m_frameNumber(0) + , m_layerRendererInitialized(false) , m_settings(settings) , m_visible(true) , m_haveWheelEventHandlers(false) @@ -70,6 +73,7 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings , m_minPageScale(1) , m_maxPageScale(1) , m_triggerIdlePaints(true) + , m_partialTextureUpdateRequests(0) { ASSERT(CCProxy::isMainThread()); numLayerTreeInstances++; @@ -88,20 +92,10 @@ bool CCLayerTreeHost::initialize() m_proxy = CCSingleThreadProxy::create(this); m_proxy->start(); - if (!m_proxy->initializeLayerRenderer()) + if (!m_proxy->initializeContext()) return false; m_compositorIdentifier = m_proxy->compositorIdentifier(); - - // Update m_settings based on capabilities that we got back from the renderer. - m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting; - - // Update m_settings based on partial update capability. - m_settings.partialTextureUpdates = m_settings.partialTextureUpdates && m_proxy->partialTextureUpdateCapability(); - - m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()), - TextureManager::reclaimLimitBytes(viewportSize()), - m_proxy->layerRendererCapabilities().maxTextureSize); return true; } @@ -116,6 +110,29 @@ CCLayerTreeHost::~CCLayerTreeHost() numLayerTreeInstances--; } +void CCLayerTreeHost::initializeLayerRenderer() +{ + TRACE_EVENT("CCLayerTreeHost::initializeLayerRenderer", this, 0); + if (!m_proxy->initializeLayerRenderer()) { + // Uh oh, better tell the client that we can't do anything with this context. + m_client->didRecreateGraphicsContext(false); + return; + } + + // Update m_settings based on capabilities that we got back from the renderer. + m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting; + + // Update m_settings based on partial update capability. + m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates()); + + m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()), + TextureManager::reclaimLimitBytes(viewportSize()), + m_proxy->layerRendererCapabilities().maxTextureSize); + + m_layerRendererInitialized = true; +} + + void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* allocator) { ASSERT(CCProxy::isImplThread()); @@ -140,8 +157,8 @@ void CCLayerTreeHost::beginCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) ASSERT(CCProxy::isImplThread()); TRACE_EVENT("CCLayerTreeHost::commitTo", this, 0); - contentsTextureManager()->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize())); - contentsTextureManager()->deleteEvictedTextures(hostImpl->contentsTextureAllocator()); + m_contentsTextureManager->reduceMemoryToLimit(TextureManager::reclaimLimitBytes(viewportSize())); + m_contentsTextureManager->deleteEvictedTextures(hostImpl->contentsTextureAllocator()); } // This function commits the CCLayerTreeHost to an impl tree. When modifying @@ -198,6 +215,11 @@ GraphicsContext3D* CCLayerTreeHost::context() bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect) { + if (!m_layerRendererInitialized) { + initializeLayerRenderer(); + if (!m_layerRendererInitialized) + return false; + } m_triggerIdlePaints = false; bool ret = m_proxy->compositeAndReadback(pixels, rect); m_triggerIdlePaints = true; @@ -206,6 +228,8 @@ bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect) void CCLayerTreeHost::finishAllRendering() { + if (!m_layerRendererInitialized) + return; m_proxy->finishAllRendering(); } @@ -254,8 +278,10 @@ void CCLayerTreeHost::setViewportSize(const IntSize& viewportSize) if (viewportSize == m_viewportSize) return; - contentsTextureManager()->setMaxMemoryLimitBytes(TextureManager::highLimitBytes(viewportSize)); - contentsTextureManager()->setPreferredMemoryLimitBytes(TextureManager::reclaimLimitBytes(viewportSize)); + if (m_contentsTextureManager) { + m_contentsTextureManager->setMaxMemoryLimitBytes(TextureManager::highLimitBytes(viewportSize)); + m_contentsTextureManager->setPreferredMemoryLimitBytes(TextureManager::reclaimLimitBytes(viewportSize)); + } m_viewportSize = viewportSize; setNeedsCommit(); } @@ -285,6 +311,10 @@ void CCLayerTreeHost::setVisible(bool visible) return; m_visible = visible; + + if (!m_layerRendererInitialized) + return; + if (!visible) { m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes(viewportSize())); m_contentsTextureManager->unprotectAllTextures(); @@ -344,15 +374,23 @@ void CCLayerTreeHost::composite() static_cast<CCSingleThreadProxy*>(m_proxy.get())->compositeImmediately(); } -void CCLayerTreeHost::updateLayers() +bool CCLayerTreeHost::updateLayers() { + if (!m_layerRendererInitialized) { + initializeLayerRenderer(); + // If we couldn't initialize, then bail since we're returning to software mode. + if (!m_layerRendererInitialized) + return false; + } + if (!rootLayer()) - return; + return true; if (viewportSize().isEmpty()) - return; + return true; updateLayers(rootLayer()); + return true; } void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer) @@ -380,6 +418,9 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer) CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize); } + // Reset partial texture update requests. + m_partialTextureUpdateRequests = 0; + reserveTextures(); paintLayerContents(m_updateList, PaintVisible); @@ -388,8 +429,8 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer) size_t preferredLimitBytes = TextureManager::reclaimLimitBytes(m_viewportSize); size_t maxLimitBytes = TextureManager::highLimitBytes(m_viewportSize); - contentsTextureManager()->reduceMemoryToLimit(preferredLimitBytes); - if (contentsTextureManager()->currentMemoryUseBytes() >= preferredLimitBytes) + m_contentsTextureManager->reduceMemoryToLimit(preferredLimitBytes); + if (m_contentsTextureManager->currentMemoryUseBytes() >= preferredLimitBytes) return; // Idle painting should fail when we hit the preferred memory limit, @@ -461,10 +502,10 @@ static void enterTargetRenderSurface(Vector<RenderSurfaceRegion>& stack, RenderS stack.append(RenderSurfaceRegion()); stack.last().surface = newTarget; } else if (stack.last().surface != newTarget) { - const RenderSurfaceRegion& previous = stack.last(); stack.append(RenderSurfaceRegion()); stack.last().surface = newTarget; - stack.last().occludedInScreen = previous.occludedInScreen; + int lastIndex = stack.size() - 1; + stack[lastIndex].occludedInScreen = stack[lastIndex - 1].occludedInScreen; } } @@ -588,6 +629,15 @@ void CCLayerTreeHost::stopRateLimiter(GraphicsContext3D* context) } } +bool CCLayerTreeHost::requestPartialTextureUpdate() +{ + if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates) + return false; + + m_partialTextureUpdateRequests++; + return true; +} + void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture) { m_deleteTextureAfterCommitList.append(texture); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h index f58203d15..e82f29830 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h @@ -33,15 +33,12 @@ #include "cc/CCLayerTreeHostCommon.h" #include "cc/CCProxy.h" +#include <limits> #include <wtf/HashMap.h> #include <wtf/PassOwnPtr.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#if USE(SKIA) -class GrContext; -#endif - namespace WebCore { class CCLayerTreeHostImpl; @@ -78,7 +75,7 @@ struct CCSettings { , refreshRate(0) , perTilePainting(false) , partialSwapEnabled(false) - , partialTextureUpdates(true) { } + , maxPartialTextureUpdates(std::numeric_limits<size_t>::max()) { } bool acceleratePainting; bool compositeOffscreen; @@ -87,7 +84,7 @@ struct CCSettings { double refreshRate; bool perTilePainting; bool partialSwapEnabled; - bool partialTextureUpdates; + size_t maxPartialTextureUpdates; }; // Provides information on an Impl's rendering capabilities back to the CCLayerTreeHost @@ -158,7 +155,7 @@ public: const LayerRendererCapabilities& layerRendererCapabilities() const; - // Test-only hook + // Test only hook void loseCompositorContext(int numTimes); void setNeedsAnimate(); @@ -188,13 +185,15 @@ public: void setHaveWheelEventHandlers(bool); - void updateLayers(); + // Returns false if we should abort this frame due to initialization failure. + bool updateLayers(); void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&); void applyScrollAndScale(const CCScrollAndScaleSet&); void startRateLimiter(GraphicsContext3D*); void stopRateLimiter(GraphicsContext3D*); + bool requestPartialTextureUpdate(); void deleteTextureAfterCommit(PassOwnPtr<ManagedTexture>); protected: @@ -205,6 +204,8 @@ private: typedef Vector<RefPtr<LayerChromium> > LayerList; typedef Vector<OwnPtr<ManagedTexture> > TextureList; + void initializeLayerRenderer(); + enum PaintType { PaintVisible, PaintIdle }; static void paintContentsIfDirty(LayerChromium*, PaintType, const Region& occludedScreenSpace); void paintLayerContents(const LayerList&, PaintType); @@ -224,6 +225,7 @@ private: int m_frameNumber; OwnPtr<CCProxy> m_proxy; + bool m_layerRendererInitialized; RefPtr<LayerChromium> m_rootLayer; OwnPtr<TextureManager> m_contentsTextureManager; @@ -243,6 +245,7 @@ private: bool m_triggerIdlePaints; TextureList m_deleteTextureAfterCommitList; + size_t m_partialTextureUpdateRequests; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp index 1846d6c2e..088377cdd 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp @@ -148,7 +148,7 @@ void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get(); CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); ASSERT(renderSurface); - renderSurface->damageTracker()->updateDamageRectForNextFrame(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurfaceLayer->maskLayer()); + renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurfaceLayer->maskLayer()); } } @@ -231,6 +231,7 @@ void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes) continue; } + layer->willDraw(m_layerRenderer.get()); pass->appendQuadsForLayer(layer); } @@ -284,8 +285,7 @@ void CCLayerTreeHostImpl::finishAllRendering() bool CCLayerTreeHostImpl::isContextLost() { - ASSERT(m_layerRenderer); - return m_layerRenderer->isContextLost(); + return m_layerRenderer && m_layerRenderer->isContextLost(); } const LayerRendererCapabilities& CCLayerTreeHostImpl::layerRendererCapabilities() const diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h index a71adae67..569d69fa3 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h @@ -32,10 +32,6 @@ #include "cc/CCRenderPass.h" #include <wtf/RefPtr.h> -#if USE(SKIA) -class GrContext; -#endif - namespace WebCore { class CCCompletionEvent; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp index fd2ae4b86..85289141d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.cpp @@ -29,16 +29,20 @@ namespace WebCore { -PassOwnPtr<CCPluginDrawQuad> CCPluginDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer) +PassOwnPtr<CCPluginDrawQuad> CCPluginDrawQuad::create(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned ioSurfaceTextureId) { - return adoptPtr(new CCPluginDrawQuad(sharedQuadState, quadRect, layer)); + return adoptPtr(new CCPluginDrawQuad(sharedQuadState, quadRect, uvRect, textureId, flipped, ioSurfaceWidth, ioSurfaceHeight, ioSurfaceTextureId)); } -CCPluginDrawQuad::CCPluginDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, CCLayerImpl* layer) +CCPluginDrawQuad::CCPluginDrawQuad(const CCSharedQuadState* sharedQuadState, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned ioSurfaceTextureId) : CCDrawQuad(sharedQuadState, CCDrawQuad::PluginContent, quadRect) - , m_layer(layer) + , m_uvRect(uvRect) + , m_textureId(textureId) + , m_flipped(flipped) + , m_ioSurfaceWidth(ioSurfaceWidth) + , m_ioSurfaceHeight(ioSurfaceHeight) + , m_ioSurfaceTextureId(ioSurfaceTextureId) { - ASSERT(m_layer); } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h index ca52abef4..31a260d43 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginDrawQuad.h @@ -36,14 +36,25 @@ class CCLayerImpl; class CCPluginDrawQuad : public CCDrawQuad { WTF_MAKE_NONCOPYABLE(CCPluginDrawQuad); public: - static PassOwnPtr<CCPluginDrawQuad> create(const CCSharedQuadState*, const IntRect&, CCLayerImpl*); + static PassOwnPtr<CCPluginDrawQuad> create(const CCSharedQuadState*, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned m_ioSurfaceTextureId); - CCLayerImpl* layer() const { return m_layer; } + FloatRect uvRect() const { return m_uvRect; } + unsigned textureId() const { return m_textureId; } + bool flipped() const { return m_flipped; } + int ioSurfaceWidth() const { return m_ioSurfaceWidth; } + int ioSurfaceHeight() const { return m_ioSurfaceHeight; } + unsigned ioSurfaceTextureId() const { return m_ioSurfaceTextureId; } + private: - CCPluginDrawQuad(const CCSharedQuadState*, const IntRect&, CCLayerImpl*); - - CCLayerImpl* m_layer; + CCPluginDrawQuad(const CCSharedQuadState*, const IntRect& quadRect, const FloatRect& uvRect, unsigned textureId, bool flipped, int ioSurfaceWidth, int ioSurfaceHeight, unsigned ioSurfaceTextureId); + + FloatRect m_uvRect; + unsigned m_textureId; + bool m_flipped; + int m_ioSurfaceWidth; + int m_ioSurfaceHeight; + unsigned m_ioSurfaceTextureId; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp index b20a2f518..5e4aca6d9 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp @@ -36,45 +36,6 @@ #include "cc/CCProxy.h" #include <wtf/text/WTFString.h> -namespace { - -struct PluginProgramBinding { - template<class Program> void set(Program* program) - { - ASSERT(program && program->initialized()); - programId = program->program(); - samplerLocation = program->fragmentShader().samplerLocation(); - matrixLocation = program->vertexShader().matrixLocation(); - alphaLocation = program->fragmentShader().alphaLocation(); - } - int programId; - int samplerLocation; - int matrixLocation; - int alphaLocation; -}; - -struct TexStretchPluginProgramBinding : PluginProgramBinding { - template<class Program> void set(Program* program) - { - PluginProgramBinding::set(program); - offsetLocation = program->vertexShader().offsetLocation(); - scaleLocation = program->vertexShader().scaleLocation(); - } - int offsetLocation; - int scaleLocation; -}; - -struct TexTransformPluginProgramBinding : PluginProgramBinding { - template<class Program> void set(Program* program) - { - PluginProgramBinding::set(program); - texTransformLocation = program->vertexShader().texTransformLocation(); - } - int texTransformLocation; -}; - -} // anonymous namespace - namespace WebCore { CCPluginLayerImpl::CCPluginLayerImpl(int id) @@ -95,10 +56,8 @@ CCPluginLayerImpl::~CCPluginLayerImpl() cleanupResources(); } -void CCPluginLayerImpl::draw(LayerRendererChromium* layerRenderer) +void CCPluginLayerImpl::willDraw(LayerRendererChromium* layerRenderer) { - ASSERT(CCProxy::isImplThread()); - if (m_ioSurfaceChanged) { GraphicsContext3D* context = layerRenderer->context(); Extensions3DChromium* extensions = static_cast<Extensions3DChromium*>(context->getExtensions()); @@ -127,60 +86,12 @@ void CCPluginLayerImpl::draw(LayerRendererChromium* layerRenderer) // allocated. m_ioSurfaceChanged = false; } - - if (m_ioSurfaceTextureId) { - TexTransformPluginProgramBinding binding; - if (m_flipped) - binding.set(layerRenderer->pluginLayerTexRectProgramFlip()); - else - binding.set(layerRenderer->pluginLayerTexRectProgram()); - - GraphicsContext3D* context = layerRenderer->context(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, m_ioSurfaceTextureId)); - - GLC(context, context->useProgram(binding.programId)); - GLC(context, context->uniform1i(binding.samplerLocation, 0)); - // Note: this code path ignores m_uvRect. - GLC(context, context->uniform4f(binding.texTransformLocation, 0, 0, m_ioSurfaceWidth, m_ioSurfaceHeight)); - layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(), - binding.matrixLocation, - binding.alphaLocation, - -1); - GLC(context, context->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0)); - } else { - TexStretchPluginProgramBinding binding; - if (m_flipped) - binding.set(layerRenderer->pluginLayerProgramFlip()); - else - binding.set(layerRenderer->pluginLayerProgram()); - - GraphicsContext3D* context = layerRenderer->context(); - GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); - GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId)); - - // FIXME: setting the texture parameters every time is redundant. Move this code somewhere - // where it will only happen once per texture. - GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR)); - GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR)); - GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE)); - GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE)); - - GLC(context, context->useProgram(binding.programId)); - GLC(context, context->uniform1i(binding.samplerLocation, 0)); - GLC(context, context->uniform2f(binding.offsetLocation, m_uvRect.x(), m_uvRect.y())); - GLC(context, context->uniform2f(binding.scaleLocation, m_uvRect.width(), m_uvRect.height())); - layerRenderer->drawTexturedQuad(drawTransform(), bounds().width(), bounds().height(), drawOpacity(), layerRenderer->sharedGeometryQuad(), - binding.matrixLocation, - binding.alphaLocation, - -1); - } } void CCPluginLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState) { IntRect quadRect(IntPoint(), bounds()); - quadList.append(CCPluginDrawQuad::create(sharedQuadState, quadRect, this)); + quadList.append(CCPluginDrawQuad::create(sharedQuadState, quadRect, m_uvRect, m_textureId, m_flipped, m_ioSurfaceWidth, m_ioSurfaceHeight, m_ioSurfaceTextureId)); } void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h index 9b4d5a4d3..39a95951d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h @@ -41,6 +41,7 @@ public: } virtual ~CCPluginLayerImpl(); + virtual void willDraw(LayerRendererChromium*); virtual void appendQuads(CCQuadList&, const CCSharedQuadState*); typedef ProgramBinding<VertexShaderPosTexStretch, FragmentShaderRGBATexAlpha> Program; @@ -48,8 +49,6 @@ public: typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectAlpha> TexRectProgram; typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectFlipAlpha> TexRectProgramFlip; - virtual void draw(LayerRendererChromium*); - virtual void dumpLayerProperties(TextStream&, int indent) const; void setTextureId(unsigned id) { m_textureId = id; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h index 937c154ff..44aacceb0 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h @@ -31,10 +31,6 @@ #include <wtf/PassRefPtr.h> #include <wtf/Threading.h> -#if USE(SKIA) -class GrContext; -#endif - namespace WebCore { class CCThread; @@ -65,6 +61,11 @@ public: virtual bool isStarted() const = 0; + // Attempts to initialize a context to use for rendering. Returns false if the context could not be created. + // The context will not be used and no frames may be produced until initializeLayerRenderer() is called. + virtual bool initializeContext() = 0; + + // Attempts to initialize the layer renderer. Returns false if the context isn't usable for compositing. virtual bool initializeLayerRenderer() = 0; virtual int compositorIdentifier() const = 0; @@ -79,9 +80,8 @@ public: virtual void start() = 0; // Must be called before using the proxy. virtual void stop() = 0; // Must be called before deleting the proxy. - // Whether sub-regions of textures can be updated or if complete texture - // updates are required. - virtual bool partialTextureUpdateCapability() const = 0; + // Maximum number of sub-region texture updates supported for each commit. + virtual size_t maxPartialTextureUpdates() const = 0; // Debug hooks #ifndef NDEBUG diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp index 72bec2a71..2e48e10f5 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp @@ -33,6 +33,7 @@ #include "cc/CCTextureUpdater.h" #include <wtf/CurrentTime.h> +using namespace std; using namespace WTF; namespace WebCore { @@ -45,6 +46,7 @@ PassOwnPtr<CCProxy> CCSingleThreadProxy::create(CCLayerTreeHost* layerTreeHost) CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost) : m_layerTreeHost(layerTreeHost) , m_compositorIdentifier(-1) + , m_layerRendererInitialized(false) , m_numFailedRecreateAttempts(0) , m_graphicsContextLost(false) , m_timesRecreateShouldFail(0) @@ -69,12 +71,16 @@ CCSingleThreadProxy::~CCSingleThreadProxy() bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) { + TRACE_EVENT("CCSingleThreadProxy::compositeAndReadback", this, 0); ASSERT(CCProxy::isMainThread()); - if (!recreateContextIfNeeded()) + if (!recreateContextIfNeeded()) { + TRACE_EVENT("compositeAndReadback_EarlyOut_ContextLost", this, 0); return false; + } - commitIfNeeded(); + if (!commitIfNeeded()) + return false; if (!doComposite()) return false; @@ -90,6 +96,8 @@ bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect GraphicsContext3D* CCSingleThreadProxy::context() { ASSERT(CCProxy::isMainThread()); + if (m_contextBeforeInitialization) + return m_contextBeforeInitialization.get(); DebugScopedSetImplThread impl; return m_layerTreeHostImpl->context(); } @@ -109,25 +117,35 @@ bool CCSingleThreadProxy::isStarted() const return m_layerTreeHostImpl; } -bool CCSingleThreadProxy::initializeLayerRenderer() +bool CCSingleThreadProxy::initializeContext() { ASSERT(CCProxy::isMainThread()); RefPtr<GraphicsContext3D> context = m_layerTreeHost->createLayerTreeHostContext3D(); if (!context) return false; ASSERT(context->hasOneRef()); + m_contextBeforeInitialization = context; + return true; +} +bool CCSingleThreadProxy::initializeLayerRenderer() +{ + ASSERT(CCProxy::isMainThread()); + ASSERT(m_contextBeforeInitialization); { DebugScopedSetImplThread impl; - bool ok = m_layerTreeHostImpl->initializeLayerRenderer(context); - if (ok) + bool ok = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitialization.release()); + if (ok) { + m_layerRendererInitialized = true; m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities(); + } return ok; } } const LayerRendererCapabilities& CCSingleThreadProxy::layerRendererCapabilities() const { + ASSERT(m_layerRendererInitialized); // Note: this gets called during the commit by the "impl" thread return m_layerRendererCapabilitiesForMainThread; } @@ -155,7 +173,8 @@ void CCSingleThreadProxy::doCommit() m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get()); CCTextureUpdater updater(m_layerTreeHostImpl->contentsTextureAllocator()); m_layerTreeHost->updateCompositorResources(m_layerTreeHostImpl->context(), updater); - while (updater.update(m_layerTreeHostImpl->context(), 1)) { } + updater.update(m_layerTreeHostImpl->context(), numeric_limits<size_t>::max()); + ASSERT(!updater.hasMoreUpdates()); m_layerTreeHostImpl->setVisible(m_layerTreeHost->visible()); m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get()); @@ -214,7 +233,8 @@ void CCSingleThreadProxy::compositeImmediately() if (!recreateContextIfNeeded()) return; - commitIfNeeded(); + if (!commitIfNeeded()) + return; if (doComposite()) m_layerTreeHostImpl->swapBuffers(); @@ -268,13 +288,15 @@ bool CCSingleThreadProxy::recreateContextIfNeeded() return false; } -void CCSingleThreadProxy::commitIfNeeded() +bool CCSingleThreadProxy::commitIfNeeded() { ASSERT(CCProxy::isMainThread()); - m_layerTreeHost->updateLayers(); + if (!m_layerTreeHost->updateLayers()) + return false; doCommit(); + return true; } bool CCSingleThreadProxy::doComposite() diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h index 4faa22999..a94405f3d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h @@ -28,6 +28,7 @@ #include "cc/CCCompletionEvent.h" #include "cc/CCLayerTreeHostImpl.h" #include "cc/CCProxy.h" +#include <limits> #include <wtf/OwnPtr.h> namespace WebCore { @@ -44,6 +45,7 @@ public: virtual GraphicsContext3D* context(); virtual void finishAllRendering(); virtual bool isStarted() const; + virtual bool initializeContext(); virtual bool initializeLayerRenderer(); virtual int compositorIdentifier() const { return m_compositorIdentifier; } virtual const LayerRendererCapabilities& layerRendererCapabilities() const; @@ -54,7 +56,7 @@ public: virtual void setVisible(bool); virtual void start(); virtual void stop(); - virtual bool partialTextureUpdateCapability() const { return true; } + virtual size_t maxPartialTextureUpdates() const { return std::numeric_limits<size_t>::max(); } // CCLayerTreeHostImplClient implementation virtual void onSwapBuffersCompleteOnImplThread() { ASSERT_NOT_REACHED(); } @@ -67,7 +69,7 @@ public: private: explicit CCSingleThreadProxy(CCLayerTreeHost*); bool recreateContextIfNeeded(); - void commitIfNeeded(); + bool commitIfNeeded(); void doCommit(); bool doComposite(); @@ -75,8 +77,13 @@ private: CCLayerTreeHost* m_layerTreeHost; int m_compositorIdentifier; + // Holds on to the context between initializeContext() and initializeLayerRenderer() calls. Shouldn't + // be used for anything else. + RefPtr<GraphicsContext3D> m_contextBeforeInitialization; + // Used on the CCThread, but checked on main thread during initialization/shutdown. OwnPtr<CCLayerTreeHostImpl> m_layerTreeHostImpl; + bool m_layerRendererInitialized; LayerRendererCapabilities m_layerRendererCapabilitiesForMainThread; int m_numFailedRecreateAttempts; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp index 8745c4ea0..66e08c8bd 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.cpp @@ -48,7 +48,7 @@ CCTextureUpdater::~CCTextureUpdater() { } -void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect) +void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>& entries) { ASSERT(texture); @@ -56,24 +56,50 @@ void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRe entry.m_texture = texture; entry.m_sourceRect = sourceRect; entry.m_destRect = destRect; - m_entries.append(entry); + entries.append(entry); +} + +void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect) +{ + append(texture, sourceRect, destRect, m_entries); +} + +void CCTextureUpdater::appendPartial(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect) +{ + append(texture, sourceRect, destRect, m_partialEntries); } bool CCTextureUpdater::hasMoreUpdates() const { - return m_entries.size(); + return m_entries.size() || m_partialEntries.size(); } bool CCTextureUpdater::update(GraphicsContext3D* context, size_t count) { + size_t index; size_t maxIndex = min(m_entryIndex + count, m_entries.size()); - for (; m_entryIndex < maxIndex; ++m_entryIndex) { - UpdateEntry& entry = m_entries[m_entryIndex]; + for (index = m_entryIndex; index < maxIndex; ++index) { + UpdateEntry& entry = m_entries[index]; entry.m_texture->updateRect(context, m_allocator, entry.m_sourceRect, entry.m_destRect); } - if (maxIndex < m_entries.size()) + bool moreUpdates = maxIndex < m_entries.size(); + + ASSERT(m_partialEntries.size() <= count); + // Make sure the number of updates including partial updates are not more + // than |count|. + if ((count - (index - m_entryIndex)) < m_partialEntries.size()) + moreUpdates = true; + + if (moreUpdates) { + m_entryIndex = index; return true; + } + + for (index = 0; index < m_partialEntries.size(); ++index) { + UpdateEntry& entry = m_partialEntries[index]; + entry.m_texture->updateRect(context, m_allocator, entry.m_sourceRect, entry.m_destRect); + } // If no entries left to process, auto-clear. clear(); @@ -84,6 +110,7 @@ void CCTextureUpdater::clear() { m_entryIndex = 0; m_entries.clear(); + m_partialEntries.clear(); } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h index bf79ac9c2..dbb52c9ba 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTextureUpdater.h @@ -41,6 +41,7 @@ public: ~CCTextureUpdater(); void append(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect); + void appendPartial(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect); bool hasMoreUpdates() const; @@ -58,9 +59,12 @@ private: IntRect m_destRect; }; + static void append(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>&); + TextureAllocator* m_allocator; size_t m_entryIndex; Vector<UpdateEntry> m_entries; + Vector<UpdateEntry> m_partialEntries; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp index 5e6a8f862..8ca852dda 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp @@ -43,7 +43,9 @@ using namespace WTF; namespace { -static const size_t textureUpdatesPerFrame = 0; +// Number of textures to update with each call to +// scheduledActionUpdateMoreResources(). +static const size_t textureUpdatesPerFrame = 5; } // anonymous namespace @@ -59,6 +61,7 @@ CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost) , m_commitRequested(false) , m_layerTreeHost(layerTreeHost) , m_compositorIdentifier(-1) + , m_layerRendererInitialized(false) , m_started(false) , m_lastExecutedBeginFrameAndCommitSequenceNumber(-1) , m_numBeginFrameAndCommitsIssuedOnImplThread(0) @@ -85,6 +88,11 @@ bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect) ASSERT(isMainThread()); ASSERT(m_layerTreeHost); + if (!m_layerRendererInitialized) { + TRACE_EVENT("compositeAndReadback_EarlyOut_LR_Uninitialized", this, 0); + return false; + } + // If a commit is pending, perform the commit first. if (m_commitRequested) { // This bit of code is uglier than it should be because returning @@ -146,9 +154,9 @@ bool CCThreadProxy::isStarted() const return m_started; } -bool CCThreadProxy::initializeLayerRenderer() +bool CCThreadProxy::initializeContext() { - TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0); + TRACE_EVENT("CCThreadProxy::initializeContext", this, 0); RefPtr<GraphicsContext3D> context = m_layerTreeHost->createLayerTreeHostContext3D(); if (!context) return false; @@ -158,19 +166,29 @@ bool CCThreadProxy::initializeLayerRenderer() GraphicsContext3D* contextPtr = context.release().leakRef(); ASSERT(contextPtr->hasOneRef()); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeContextOnImplThread, + AllowCrossThreadAccess(contextPtr))); + return true; +} + +bool CCThreadProxy::initializeLayerRenderer() +{ + TRACE_EVENT("CCThreadProxy::initializeLayerRenderer", this, 0); // Make a blocking call to initializeLayerRendererOnImplThread. The results of that call // are pushed into the initializeSucceeded and capabilities local variables. CCCompletionEvent completion; bool initializeSucceeded = false; LayerRendererCapabilities capabilities; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeLayerRendererOnImplThread, - AllowCrossThreadAccess(contextPtr), AllowCrossThreadAccess(&completion), - AllowCrossThreadAccess(&initializeSucceeded), AllowCrossThreadAccess(&capabilities), - AllowCrossThreadAccess(&m_compositorIdentifier))); + AllowCrossThreadAccess(&completion), + AllowCrossThreadAccess(&initializeSucceeded), + AllowCrossThreadAccess(&capabilities))); completion.wait(); - if (initializeSucceeded) + if (initializeSucceeded) { + m_layerRendererInitialized = true; m_layerRendererCapabilitiesMainThreadCopy = capabilities; + } return initializeSucceeded; } @@ -182,6 +200,7 @@ int CCThreadProxy::compositorIdentifier() const const LayerRendererCapabilities& CCThreadProxy::layerRendererCapabilities() const { + ASSERT(m_layerRendererInitialized); return m_layerRendererCapabilitiesMainThreadCopy; } @@ -380,7 +399,8 @@ void CCThreadProxy::beginFrameAndCommit(int sequenceNumber, double frameBeginTim // updateLayers. m_commitRequested = false; - m_layerTreeHost->updateLayers(); + if (!m_layerTreeHost->updateLayers()) + return; // Before applying scrolls and calling animate, we set m_animateRequested to false. // If it is true now, it means setNeedAnimate was called again. Call setNeedsCommit @@ -444,7 +464,7 @@ void CCThreadProxy::scheduledActionUpdateMoreResources() { TRACE_EVENT("CCThreadProxy::scheduledActionUpdateMoreResources", this, 0); ASSERT(m_currentTextureUpdaterOnImplThread); - m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), textureUpdatesPerFrame > 0 ? textureUpdatesPerFrame : 99999); + m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), textureUpdatesPerFrame); } void CCThreadProxy::scheduledActionCommit() @@ -537,22 +557,30 @@ void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion) OwnPtr<CCFrameRateController> frameRateController = adoptPtr(new CCFrameRateController(CCDelayBasedTimeSource::create(displayRefreshIntervalMs, CCProxy::implThread()))); m_schedulerOnImplThread = CCScheduler::create(this, frameRateController.release()); m_schedulerOnImplThread->setVisible(m_layerTreeHostImpl->visible()); + + m_inputHandlerOnImplThread = CCInputHandler::create(m_layerTreeHostImpl.get()); + m_compositorIdentifier = m_inputHandlerOnImplThread->identifier(); + completion->signal(); } -void CCThreadProxy::initializeLayerRendererOnImplThread(GraphicsContext3D* contextPtr, CCCompletionEvent* completion, bool* initializeSucceeded, LayerRendererCapabilities* capabilities, int* compositorIdentifier) +void CCThreadProxy::initializeContextOnImplThread(GraphicsContext3D* context) +{ + TRACE_EVENT("CCThreadProxy::initializeContextOnImplThread", this, 0); + ASSERT(isImplThread()); + m_contextBeforeInitializationOnImplThread = adoptRef(context); +} + +void CCThreadProxy::initializeLayerRendererOnImplThread(CCCompletionEvent* completion, bool* initializeSucceeded, LayerRendererCapabilities* capabilities) { TRACE_EVENT("CCThreadProxy::initializeLayerRendererOnImplThread", this, 0); ASSERT(isImplThread()); - RefPtr<GraphicsContext3D> context(adoptRef(contextPtr)); - *initializeSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(context); + ASSERT(m_contextBeforeInitializationOnImplThread); + *initializeSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(m_contextBeforeInitializationOnImplThread.release()); if (*initializeSucceeded) { *capabilities = m_layerTreeHostImpl->layerRendererCapabilities(); if (capabilities->usingSwapCompleteCallback) m_schedulerOnImplThread->setMaxFramesPending(2); - - m_inputHandlerOnImplThread = CCInputHandler::create(m_layerTreeHostImpl.get()); - *compositorIdentifier = m_inputHandlerOnImplThread->identifier(); } completion->signal(); @@ -569,9 +597,9 @@ void CCThreadProxy::layerTreeHostClosedOnImplThread(CCCompletionEvent* completio completion->signal(); } -bool CCThreadProxy::partialTextureUpdateCapability() const +size_t CCThreadProxy::maxPartialTextureUpdates() const { - return !textureUpdatesPerFrame; + return textureUpdatesPerFrame; } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h index a11b52785..d304acd96 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h @@ -52,6 +52,7 @@ public: virtual GraphicsContext3D* context(); virtual void finishAllRendering(); virtual bool isStarted() const; + virtual bool initializeContext(); virtual bool initializeLayerRenderer(); virtual int compositorIdentifier() const; virtual const LayerRendererCapabilities& layerRendererCapabilities() const; @@ -62,7 +63,7 @@ public: virtual void setVisible(bool); virtual void start(); virtual void stop(); - virtual bool partialTextureUpdateCapability() const; + virtual size_t maxPartialTextureUpdates() const; // CCLayerTreeHostImplClient implementation virtual void onSwapBuffersCompleteOnImplThread(); @@ -98,7 +99,8 @@ private: void requestReadbackOnImplThread(ReadbackRequest*); void finishAllRenderingOnImplThread(CCCompletionEvent*); void initializeImplOnImplThread(CCCompletionEvent*); - void initializeLayerRendererOnImplThread(GraphicsContext3D*, CCCompletionEvent*, bool* initializeSucceeded, LayerRendererCapabilities*, int* compositorIdentifier); + void initializeContextOnImplThread(GraphicsContext3D*); + void initializeLayerRendererOnImplThread(CCCompletionEvent*, bool* initializeSucceeded, LayerRendererCapabilities*); void setVisibleOnImplThread(CCCompletionEvent*, bool visible); void layerTreeHostClosedOnImplThread(CCCompletionEvent*); @@ -107,6 +109,7 @@ private: bool m_commitRequested; CCLayerTreeHost* m_layerTreeHost; int m_compositorIdentifier; + bool m_layerRendererInitialized; LayerRendererCapabilities m_layerRendererCapabilitiesMainThreadCopy; bool m_started; int m_lastExecutedBeginFrameAndCommitSequenceNumber; @@ -121,6 +124,10 @@ private: RefPtr<CCScopedThreadProxy> m_mainThreadProxy; + // Holds on to the GraphicsContext3D we might use for compositing in between initializeContext() + // and initializeLayerRenderer() calls. + RefPtr<GraphicsContext3D> m_contextBeforeInitializationOnImplThread; + // Set when the main thread is waiing on a readback. ReadbackRequest* m_readbackRequestOnImplThread; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp index 09afb08d3..eef0ca3e9 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp @@ -246,10 +246,15 @@ bool CCVideoLayerImpl::reserveTextures(const VideoFrameChromium* frame, GC3Denum if (!m_textures[plane].m_texture) return false; m_textures[plane].m_visibleSize = IntSize(); + } else { + // The renderSurfaceTextureManager may have been destroyed and recreated since the last frame, so pass the new one. + // This is a no-op if the TextureManager is still around. + m_textures[plane].m_texture->setTextureManager(layerRenderer->renderSurfaceTextureManager()); } if (m_textures[plane].m_texture->size() != requiredTextureSize) m_textures[plane].m_visibleSize = computeVisibleSize(frame, plane); - m_textures[plane].m_texture->reserve(requiredTextureSize, format); + if (!m_textures[plane].m_texture->reserve(requiredTextureSize, format)) + return false; } return true; } diff --git a/Source/WebCore/platform/graphics/efl/DrawingBufferEfl.cpp b/Source/WebCore/platform/graphics/efl/DrawingBufferEfl.cpp new file mode 100644 index 000000000..babe5e42a --- /dev/null +++ b/Source/WebCore/platform/graphics/efl/DrawingBufferEfl.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if ENABLE(ACCELERATED_2D_CANVAS) || ENABLE(WEBGL) + +#include "DrawingBuffer.h" + +#include "Extensions3D.h" + +namespace WebCore { + +DrawingBuffer::DrawingBuffer(GraphicsContext3D* context, const IntSize& size, bool multisampleExtensionSupported, bool packedDepthStencilExtensionSupported, bool separateBackingTexture) + : m_separateBackingTexture(separateBackingTexture) + , m_scissorEnabled(false) + , m_texture2DBinding(0) + , m_activeTextureUnit(GraphicsContext3D::TEXTURE0) + , m_context(context) + , m_size(-1, -1) + , m_multisampleExtensionSupported(multisampleExtensionSupported) + , m_packedDepthStencilExtensionSupported(packedDepthStencilExtensionSupported) + , m_fbo(context->createFramebuffer()) + , m_colorBuffer(0) + , m_depthStencilBuffer(0) + , m_depthBuffer(0) + , m_stencilBuffer(0) + , m_multisampleFBO(0) + , m_multisampleColorBuffer(0) +{ + // Support for a separate backing texture has only been enabled for + // the chromium port. + ASSERT(!m_separateBackingTexture); + ASSERT(m_fbo); + if (!m_fbo) { + clear(); + return; + } + + // Create a texture to render into. + m_colorBuffer = context->createTexture(); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); + context->texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); + context->texParameterf(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); + context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); + context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + + createSecondaryBuffers(); + reset(size); +} + +DrawingBuffer::~DrawingBuffer() +{ + clear(); +} + +Platform3DObject DrawingBuffer::platformColorBuffer() const +{ + return m_colorBuffer; +} + +#if USE(ACCELERATED_COMPOSITING) +void DrawingBuffer::paintCompositedResultsToCanvas(CanvasRenderingContext* context) +{ +} +#endif + +} + +#endif diff --git a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp index e3e82f998..1f1eda21c 100644 --- a/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp +++ b/Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp @@ -1,850 +1,147 @@ /* - Copyright (C) 2011 Samsung Electronics - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ + * Copyright (C) 2011, 2012 Samsung Electronics + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ #include "config.h" +#include "GraphicsContext3D.h" #if ENABLE(WEBGL) - -#include "GraphicsContext3DInternal.h" - -#include "ImageData.h" -#include "NotImplemented.h" +#include "Extensions3DOpenGL.h" +#include "GraphicsContext3DPrivate.h" +#include "OpenGLShims.h" +#include "ShaderLang.h" namespace WebCore { -PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, RenderStyle renderStyle) +PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) { - bool renderDirectlyToEvasGLObject = (renderStyle == RenderDirectlyToHostWindow); + bool renderDirectlyToHostWindow = (renderStyle == RenderDirectlyToHostWindow); + // This implementation doesn't currently support rendering directly to the HostWindow. + if (renderDirectlyToHostWindow) + return 0; - OwnPtr<GraphicsContext3DInternal> internal = GraphicsContext3DInternal::create(attrs, hostWindow, renderDirectlyToEvasGLObject); - if (!internal) + OwnPtr<GraphicsContext3DPrivate> priv = GraphicsContext3DPrivate::create(); + if (!priv) return 0; - RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, renderDirectlyToEvasGLObject)); - context->m_internal = internal.release(); + RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attributes, hostWindow, renderDirectlyToHostWindow)); + context->m_private = priv.release(); return context.release(); } -GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool renderDirectlyToHostWindow) +GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attributes, HostWindow* hostWindow, bool renderDirectlyToHostWindow) : m_currentWidth(0) , m_currentHeight(0) - , m_isResourceSafe(false) -{ + , m_attrs(attributes) + , m_texture(0) + , m_fbo(0) + , m_depthStencilBuffer(0) + , m_boundFBO(0) + , m_multisampleFBO(0) + , m_multisampleDepthStencilBuffer(0) + , m_multisampleColorBuffer(0) +{ + GraphicsContext3DPrivate::addActiveGraphicsContext(this); + + validateAttributes(); + + // Create a texture to render into. + ::glGenTextures(1, &m_texture); + ::glBindTexture(GL_TEXTURE_2D, m_texture); + ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + ::glBindTexture(GL_TEXTURE_2D, 0); + + // Create an FBO. + ::glGenFramebuffersEXT(1, &m_fbo); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + + m_boundFBO = m_fbo; + if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) + ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer); + + // Create a multisample FBO. + if (m_attrs.antialias) { + ::glGenFramebuffersEXT(1, &m_multisampleFBO); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + m_boundFBO = m_multisampleFBO; + ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); + } + + // ANGLE initialization. + ShBuiltInResources ANGLEResources; + ShInitBuiltInResources(&ANGLEResources); + + getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs); + getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors); + getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors); + getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits); + getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors); + + // Always set to 1 for OpenGL ES. + ANGLEResources.MaxDrawBuffers = 1; + m_compiler.setResources(ANGLEResources); + + ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); + ::glEnable(GL_POINT_SPRITE); + ::glClearColor(0, 0, 0, 0); } GraphicsContext3D::~GraphicsContext3D() { -} + GraphicsContext3DPrivate::removeActiveGraphicsContext(this); + if (!m_private->m_context) + return; -PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() const -{ - return m_internal->platformGraphicsContext3D(); + makeContextCurrent(); + ::glDeleteTextures(1, &m_texture); + if (m_attrs.antialias) { + ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer); + if (m_attrs.stencil || m_attrs.depth) + ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); + ::glDeleteFramebuffersEXT(1, &m_multisampleFBO); + } else { + if (m_attrs.stencil || m_attrs.depth) + ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer); + } + ::glDeleteFramebuffersEXT(1, &m_fbo); } -#if USE(ACCELERATED_COMPOSITING) -PlatformLayer* GraphicsContext3D::platformLayer() const -{ - notImplemented(); - return 0; -} -#endif - bool GraphicsContext3D::makeContextCurrent() { - m_internal->makeContextCurrent(); - return true; -} - -bool GraphicsContext3D::isGLES2Compliant() const -{ - return m_internal->isGLES2Compliant(); -} - -void GraphicsContext3D::activeTexture(GC3Denum texture) -{ - m_internal->activeTexture(texture); -} - -void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader) -{ - m_internal->attachShader(program, shader); -} - -void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name) -{ - m_internal->bindAttribLocation(program, index, name); -} - -void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer) -{ - m_internal->bindBuffer(target, buffer); -} - -void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) -{ - m_internal->bindFramebuffer(target, buffer); -} - -void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer) -{ - m_internal->bindRenderbuffer(target, renderbuffer); -} - -void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture) -{ - m_internal->bindTexture(target, texture); -} - -void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - m_internal->blendColor(red, green, blue, alpha); -} - -void GraphicsContext3D::blendEquation(GC3Denum mode) -{ - m_internal->blendEquation(mode); -} - -void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) -{ - m_internal->blendEquationSeparate(modeRGB, modeAlpha); -} - -void GraphicsContext3D::blendFunc(GC3Denum srcFactor, GC3Denum dstFactor) -{ - m_internal->blendFunc(srcFactor, dstFactor); -} - -void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) -{ - m_internal->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); -} - -void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage) -{ - m_internal->bufferData(target, size, 0, usage); -} - -void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage) -{ - m_internal->bufferData(target, size, data, usage); -} - -void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data) -{ - m_internal->bufferSubData(target, offset, size, data); -} - -GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target) -{ - return m_internal->checkFramebufferStatus(target); -} - -void GraphicsContext3D::clear(GC3Dbitfield mask) -{ - m_internal->clear(mask); -} - -void GraphicsContext3D::clearColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) -{ - m_internal->clearColor(red, green, blue, alpha); -} - -void GraphicsContext3D::clearDepth(GC3Dclampf depth) -{ - m_internal->clearDepth(depth); -} - -void GraphicsContext3D::clearStencil(GC3Dint clearValue) -{ - m_internal->clearStencil(clearValue); -} - -void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) -{ - m_internal->colorMask(red, green, blue, alpha); -} - -void GraphicsContext3D::compileShader(Platform3DObject shader) -{ - m_internal->compileShader(shader); -} - -void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - m_internal->copyTexImage2D(target, level, internalformat, x, y, width, height, border); -} - -void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_internal->copyTexSubImage2D(target, level, xOffset, yOffset, x, y, width, height); -} - -void GraphicsContext3D::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data) -{ - // FIXME: Add support for compressedTexImage2D. - // m_internal->compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); -} - -void GraphicsContext3D::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data) -{ - // FIXME: Add support for compressedTexSubImage2D. - // m_internal->compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); -} - -void GraphicsContext3D::cullFace(GC3Denum mode) -{ - m_internal->cullFace(mode); -} - -void GraphicsContext3D::depthFunc(GC3Denum func) -{ - m_internal->depthFunc(func); -} - -void GraphicsContext3D::depthMask(GC3Dboolean flag) -{ - m_internal->depthMask(flag); -} - -void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) -{ - m_internal->depthRange(zNear, zFar); -} - -void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader) -{ - m_internal->detachShader(program, shader); -} - -void GraphicsContext3D::disable(GC3Denum cap) -{ - m_internal->disable(cap); -} - -void GraphicsContext3D::disableVertexAttribArray(GC3Duint index) -{ - m_internal->disableVertexAttribArray(index); -} - -void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) -{ - m_internal->drawArrays(mode, first, count); -} - -void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset) -{ - m_internal->drawElements(mode, count, type, offset); -} - -void GraphicsContext3D::enable(GC3Denum cap) -{ - m_internal->enable(cap); -} - -void GraphicsContext3D::enableVertexAttribArray(GC3Duint index) -{ - m_internal->enableVertexAttribArray(index); -} - -void GraphicsContext3D::finish() -{ - m_internal->finish(); -} - -void GraphicsContext3D::flush() -{ - m_internal->flush(); -} - -void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbufferTarget, Platform3DObject buffer) -{ - m_internal->framebufferRenderbuffer(target, attachment, renderbufferTarget, buffer); -} - -void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum texTarget, Platform3DObject texture, GC3Dint level) -{ - m_internal->framebufferTexture2D(target, attachment, texTarget, texture, level); -} - -void GraphicsContext3D::frontFace(GC3Denum mode) -{ - m_internal->frontFace(mode); -} - -void GraphicsContext3D::generateMipmap(GC3Denum target) -{ - m_internal->generateMipmap(target); -} - -bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - return m_internal->getActiveAttrib(program, index, info); -} - -bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - return m_internal->getActiveUniform(program, index, info); -} - -void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) -{ - m_internal->getAttachedShaders(program, maxCount, count, shaders); -} - -int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) -{ - return m_internal->getAttribLocation(program, name); -} - -void GraphicsContext3D::getBooleanv(GC3Denum paramName, GC3Dboolean* value) -{ - m_internal->getBooleanv(paramName, value); -} - -void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_internal->getBufferParameteriv(target, paramName, value); -} - -GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() -{ - return m_internal->getContextAttributes(); -} - -GC3Denum GraphicsContext3D::getError() -{ - return m_internal->getError(); -} - -void GraphicsContext3D::getFloatv(GC3Denum paramName, GC3Dfloat* value) -{ - m_internal->getFloatv(paramName, value); -} - -void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum paramName, GC3Dint* value) -{ - m_internal->getFramebufferAttachmentParameteriv(target, attachment, paramName, value); -} - -void GraphicsContext3D::getIntegerv(GC3Denum paramName, GC3Dint* value) -{ - m_internal->getIntegerv(paramName, value); -} - -void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum paramName, GC3Dint* value) -{ - m_internal->getProgramiv(program, paramName, value); -} - -String GraphicsContext3D::getProgramInfoLog(Platform3DObject program) -{ - return m_internal->getProgramInfoLog(program); -} - -void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_internal->getRenderbufferParameteriv(target, paramName, value); -} - -void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum paramName, GC3Dint* value) -{ - m_internal->getShaderiv(shader, paramName, value); -} - -String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) -{ - return m_internal->getShaderInfoLog(shader); -} - -String GraphicsContext3D::getShaderSource(Platform3DObject shader) -{ - return m_internal->getShaderSource(shader); -} - -String GraphicsContext3D::getString(GC3Denum name) -{ - return m_internal->getString(name); -} - -void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum paramName, GC3Dfloat* value) -{ - m_internal->getTexParameterfv(target, paramName, value); -} - -void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum paramName, GC3Dint* value) -{ - m_internal->getTexParameteriv(target, paramName, value); -} - -void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value) -{ - m_internal->getUniformfv(program, location, value); -} - -void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value) -{ - m_internal->getUniformiv(program, location, value); -} - -GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name) -{ - return m_internal->getUniformLocation(program, name); -} - -void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum paramName, GC3Dfloat* value) -{ - m_internal->getVertexAttribfv(index, paramName, value); -} - -void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum paramName, GC3Dint* value) -{ - m_internal->getVertexAttribiv(index, paramName, value); -} - -long GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum paramName) -{ - return m_internal->getVertexAttribOffset(index, paramName); -} - -void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode) -{ - m_internal->hint(target, mode); -} - -GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject obj) -{ - return m_internal->isBuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap) -{ - return m_internal->isEnabled(cap); -} - -GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject obj) -{ - return m_internal->isFramebuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject obj) -{ - return m_internal->isProgram(obj); -} - -GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject obj) -{ - return m_internal->isRenderbuffer(obj); -} - -GC3Dboolean GraphicsContext3D::isShader(Platform3DObject obj) -{ - return m_internal->isShader(obj); -} - -GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject obj) -{ - return m_internal->isTexture(obj); -} - -void GraphicsContext3D::lineWidth(GC3Dfloat width) -{ - m_internal->lineWidth(width); -} - -void GraphicsContext3D::linkProgram(Platform3DObject program) -{ - m_internal->linkProgram(program); -} - -void GraphicsContext3D::pixelStorei(GC3Denum paramName, GC3Dint param) -{ - m_internal->pixelStorei(paramName, param); -} - -void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units) -{ - m_internal->polygonOffset(factor, units); -} - -void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) -{ - m_internal->readPixels(x, y, width, height, format, type, data); -} - -void GraphicsContext3D::releaseShaderCompiler() -{ - notImplemented(); -} - -void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) -{ - m_internal->renderbufferStorage(target, internalformat, width, height); -} - -void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) -{ - m_internal->sampleCoverage(value, invert); -} - -void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_internal->scissor(x, y, width, height); -} - -void GraphicsContext3D::shaderSource(Platform3DObject program, const String& string) -{ - m_internal->shaderSource(program, string); -} - -void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - m_internal->stencilFunc(func, ref, mask); -} - -void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) -{ - m_internal->stencilFuncSeparate(face, func, ref, mask); -} - -void GraphicsContext3D::stencilMask(GC3Duint mask) -{ - m_internal->stencilMask(mask); -} - -void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask) -{ - m_internal->stencilMaskSeparate(face, mask); -} - -void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - m_internal->stencilOp(fail, zfail, zpass); -} - -void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) -{ - m_internal->stencilOpSeparate(face, fail, zfail, zpass); -} - -bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) -{ - return m_internal->texImage2D(target, level, internalformat, width, height, border, format, type, pixels); -} - -void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum paramName, GC3Dfloat param) -{ - m_internal->texParameterf(target, paramName, param); -} - -void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum paramName, GC3Dint param) -{ - m_internal->texParameteri(target, paramName, param); -} - -void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xOffset, GC3Dint yOffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels) -{ - m_internal->texSubImage2D(target, level, xOffset, yOffset, width, height, format, type, pixels); -} - -void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat x) -{ - m_internal->uniform1f(location, x); -} - -void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size) -{ - m_internal->uniform1fv(location, size, v); -} - -void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint x) -{ - m_internal->uniform1i(location, x); -} - -void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dint* v, GC3Dsizei size) -{ - m_internal->uniform1iv(location, size, v); -} - -void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat x, float y) -{ - m_internal->uniform2f(location, x, y); -} - -void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size) -{ - m_internal->uniform2fv(location, size, v); -} - -void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint x, GC3Dint y) -{ - m_internal->uniform2i(location, x, y); -} - -void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dint* v, GC3Dsizei size) -{ - m_internal->uniform2iv(location, size, v); -} - -void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - m_internal->uniform3f(location, x, y, z); -} - -void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size) -{ - m_internal->uniform3fv(location, size, v); -} - -void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z) -{ - m_internal->uniform3i(location, x, y, z); -} - -void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dint* v, GC3Dsizei size) -{ - m_internal->uniform3iv(location, size, v); -} - -void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - m_internal->uniform4f(location, x, y, z, w); -} - -void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dfloat* v, GC3Dsizei size) -{ - m_internal->uniform4fv(location, size, v); -} - -void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w) -{ - m_internal->uniform4i(location, x, y, z, w); + if (!m_private) + return false; + return m_private->makeContextCurrent(); } -void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dint* v, GC3Dsizei size) -{ - m_internal->uniform4iv(location, size, v); -} - -void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size) -{ - m_internal->uniformMatrix2fv(location, size, transpose, value); -} - -void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size) -{ - m_internal->uniformMatrix3fv(location, size, transpose, value); -} - -void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* value, GC3Dsizei size) -{ - m_internal->uniformMatrix4fv(location, size, transpose, value); -} - -void GraphicsContext3D::useProgram(Platform3DObject program) -{ - m_internal->useProgram(program); -} - -void GraphicsContext3D::validateProgram(Platform3DObject program) -{ - m_internal->validateProgram(program); -} - -void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat x) -{ - m_internal->vertexAttrib1f(index, x); -} - -void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* values) -{ - m_internal->vertexAttrib1fv(index, values); -} - -void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat x, GC3Dfloat y) -{ - m_internal->vertexAttrib2f(index, x, y); -} - -void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* values) -{ - m_internal->vertexAttrib2fv(index, values); -} - -void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z) -{ - m_internal->vertexAttrib3f(index, x, y, z); -} - -void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* values) -{ - m_internal->vertexAttrib3fv(index, values); -} - -void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w) -{ - m_internal->vertexAttrib4f(index, x, y, z, w); -} - -void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* values) -{ - m_internal->vertexAttrib4fv(index, values); -} - -void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset) -{ - m_internal->vertexAttribPointer(index, size, type, normalized, stride, offset); -} - -void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - m_internal->viewport(x, y, width, height); -} - -void GraphicsContext3D::reshape(int width, int height) -{ - notImplemented(); -} - -void GraphicsContext3D::markContextChanged() -{ - notImplemented(); -} - -void GraphicsContext3D::markLayerComposited() -{ - notImplemented(); -} - -bool GraphicsContext3D::layerComposited() const -{ - notImplemented(); - return false; -} - -void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context, DrawingBuffer* drawingBuffer) -{ - // DrawingBuffer support only implemented in Chromium ports. - ASSERT(!drawingBuffer); - notImplemented(); -} - -PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer* drawingBuffer) -{ - // DrawingBuffer support only implemented in Chromium ports. - ASSERT(!drawingBuffer); - notImplemented(); - RefPtr<ImageData> imageData = ImageData::create(IntSize(1, 1)); - return imageData.release(); -} - -Platform3DObject GraphicsContext3D::createBuffer() -{ - return m_internal->createBuffer(); -} - -Platform3DObject GraphicsContext3D::createFramebuffer() -{ - return m_internal->createFramebuffer(); -} - -Platform3DObject GraphicsContext3D::createProgram() -{ - return m_internal->createProgram(); -} - -Platform3DObject GraphicsContext3D::createRenderbuffer() -{ - return m_internal->createRenderbuffer(); -} - -Platform3DObject GraphicsContext3D::createShader(GC3Denum type) -{ - return m_internal->createShader(type); -} - -Platform3DObject GraphicsContext3D::createTexture() -{ - return m_internal->createTexture(); -} - -void GraphicsContext3D::deleteBuffer(Platform3DObject buffer) -{ - m_internal->deleteBuffer(buffer); -} - -void GraphicsContext3D::deleteFramebuffer(Platform3DObject buffer) -{ - m_internal->deleteFramebuffer(buffer); -} - -void GraphicsContext3D::deleteProgram(Platform3DObject program) -{ - m_internal->deleteProgram(program); -} - -void GraphicsContext3D::deleteRenderbuffer(Platform3DObject buffer) -{ - m_internal->deleteRenderbuffer(buffer); -} - -void GraphicsContext3D::deleteShader(Platform3DObject shader) -{ - m_internal->deleteShader(shader); -} - -void GraphicsContext3D::deleteTexture(Platform3DObject texture) -{ - m_internal->deleteTexture(texture); -} - -void GraphicsContext3D::synthesizeGLError(GC3Denum error) -{ - m_internal->synthesizeGLError(error); -} - -Extensions3D* GraphicsContext3D::getExtensions() -{ - return m_internal->getExtensions(); -} - -IntSize GraphicsContext3D::getInternalFramebufferSize() -{ - notImplemented(); - return IntSize(); -} - -void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) -{ - notImplemented(); -} - -void GraphicsContext3D::setErrorMessageCallback(PassOwnPtr<ErrorMessageCallback>) +PlatformGraphicsContext3D GraphicsContext3D::platformGraphicsContext3D() const { - notImplemented(); + return m_private->m_context; } -bool GraphicsContext3D::getImageData(Image* image, GC3Denum format, GC3Denum type, bool premultiplyAlpha, - bool ignoreGammaAndColorProfile, Vector<uint8_t>& outputVector) +bool GraphicsContext3D::isGLES2Compliant() const { - notImplemented(); return false; } diff --git a/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp index ed6cb90dc..00b600abd 100644 --- a/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp +++ b/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp @@ -187,7 +187,7 @@ void FEColorMatrix::platformApplySoftware() break; } - resultImage->putUnmultipliedImageData(pixelArray.get(), imageRect.size(), imageRect, IntPoint()); + resultImage->putByteArray(Unmultiplied, pixelArray.get(), imageRect.size(), imageRect, IntPoint()); } void FEColorMatrix::dump() diff --git a/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp index 5d807785b..5944feca5 100644 --- a/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp +++ b/Source/WebCore/platform/graphics/filters/FEDropShadow.cpp @@ -108,7 +108,7 @@ void FEDropShadow::platformApplySoftware() contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width()); - resultImage->putPremultipliedImageData(srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint()); + resultImage->putByteArray(Premultiplied, srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint()); resultContext->setCompositeOperation(CompositeSourceIn); resultContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor, ColorSpaceDeviceRGB); diff --git a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp index fbeb4bbcb..f972c98a4 100644 --- a/Source/WebCore/platform/graphics/filters/FilterEffect.cpp +++ b/Source/WebCore/platform/graphics/filters/FilterEffect.cpp @@ -130,9 +130,9 @@ ImageBuffer* FilterEffect::asImageBuffer() m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB, m_filter->renderingMode()); IntRect destinationRect(IntPoint(), m_absolutePaintRect.size()); if (m_premultipliedImageResult) - m_imageBufferResult->putPremultipliedImageData(m_premultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); + m_imageBufferResult->putByteArray(Premultiplied, m_premultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); else - m_imageBufferResult->putUnmultipliedImageData(m_unmultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); + m_imageBufferResult->putByteArray(Unmultiplied, m_unmultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint()); return m_imageBufferResult.get(); } diff --git a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp index 9dd3b9de5..d37d604cf 100644 --- a/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp +++ b/Source/WebCore/platform/graphics/gpu/DrawingBuffer.cpp @@ -49,6 +49,7 @@ static int s_maximumResourceUsePixels = 16 * 1024 * 1024; static int s_maximumResourceUsePixels = 0; #endif static int s_currentResourceUsePixels = 0; +static const float s_resourceAdjustedRatio = 0.5; PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size, bool separateBackingTexture) { @@ -236,19 +237,28 @@ bool DrawingBuffer::reset(const IntSize& newSize) } int pixelDelta = newSize.width() * newSize.height(); - if (!m_size.isEmpty()) - pixelDelta -= m_size.width() * m_size.height(); - - if (s_maximumResourceUsePixels && (s_currentResourceUsePixels + pixelDelta) > s_maximumResourceUsePixels) { - clear(); - return false; + int oldSize = 0; + if (!m_size.isEmpty()) { + oldSize = m_size.width() * m_size.height(); + pixelDelta -= oldSize; } - s_currentResourceUsePixels += pixelDelta; + + IntSize adjustedSize = newSize; + if (s_maximumResourceUsePixels) { + while ((s_currentResourceUsePixels + pixelDelta) > s_maximumResourceUsePixels) { + adjustedSize.scale(s_resourceAdjustedRatio); + if (adjustedSize.isEmpty()) { + clear(); + return false; + } + pixelDelta = adjustedSize.width() * adjustedSize.height(); + pixelDelta -= oldSize; + } + } const GraphicsContext3D::Attributes& attributes = m_context->getContextAttributes(); - if (newSize != m_size) { - m_size = newSize; + if (adjustedSize != m_size) { unsigned internalColorFormat, colorFormat, internalRenderbufferFormat; if (attributes.alpha) { @@ -262,46 +272,56 @@ bool DrawingBuffer::reset(const IntSize& newSize) } - // resize multisample FBO - if (multisample()) { - int maxSampleCount = 0; - - m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); - int sampleCount = std::min(4, maxSampleCount); + do { + m_size = adjustedSize; + // resize multisample FBO + if (multisample()) { + int maxSampleCount = 0; - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount); + int sampleCount = std::min(4, maxSampleCount); - m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); - m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height()); - m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); - resizeDepthStencil(sampleCount); - if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { - // Cleanup - clear(); - return false; + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); + + m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); + m_context->getExtensions()->renderbufferStorageMultisample(GraphicsContext3D::RENDERBUFFER, sampleCount, internalRenderbufferFormat, m_size.width(), m_size.height()); + m_context->framebufferRenderbuffer(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer); + resizeDepthStencil(sampleCount); + if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { + adjustedSize.scale(s_resourceAdjustedRatio); + continue; + } } - } - // resize regular FBO - m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); + // resize regular FBO + m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); - m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer); + m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); - m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); + m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_colorBuffer, 0); - // resize the backing color buffer - if (m_separateBackingTexture) { - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_backingColorBuffer); - m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); - } + // resize the backing color buffer + if (m_separateBackingTexture) { + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_backingColorBuffer); + m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0); + } + + m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + + if (!multisample()) + resizeDepthStencil(0); + if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE) + break; + adjustedSize.scale(s_resourceAdjustedRatio); + + } while (!adjustedSize.isEmpty()); - m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); + pixelDelta = m_size.width() * m_size.height(); + pixelDelta -= oldSize; + s_currentResourceUsePixels += pixelDelta; - if (!multisample()) - resizeDepthStencil(0); - if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) { - // Cleanup + if (!newSize.isEmpty() && adjustedSize.isEmpty()) { clear(); return false; } diff --git a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp index e96591df6..a77345caa 100644 --- a/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp +++ b/Source/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp @@ -39,6 +39,8 @@ GraphicsContext3D* SharedGraphicsContext3D::get() attributes.canRecoverFromContextLoss = false; // Canvas contexts can not handle lost contexts. attributes.shareResources = true; static GraphicsContext3D* context = GraphicsContext3D::create(attributes, 0).leakRef(); + if (context && !context->makeContextCurrent()) + context = 0; return context; } diff --git a/Source/WebCore/platform/graphics/gtk/WindowGLContext.h b/Source/WebCore/platform/graphics/gtk/WindowGLContext.h new file mode 100644 index 000000000..962356835 --- /dev/null +++ b/Source/WebCore/platform/graphics/gtk/WindowGLContext.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2012 Igalia S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef WindowGLContext_h +#define WindowGLContext_h + +#include <wtf/Noncopyable.h> +#include <wtf/PassOwnPtr.h> + +#if defined(XP_UNIX) +typedef struct __GLXcontextRec* GLXContext; +typedef struct _XDisplay Display; +#endif + +namespace WebCore { + +class WindowGLContext { + WTF_MAKE_NONCOPYABLE(WindowGLContext); +public: + static PassOwnPtr<WindowGLContext> createContextWithGdkWindow(GdkWindow*); + virtual ~WindowGLContext(); + void startDrawing(); + void finishDrawing(); + +private: + WindowGLContext(GdkWindow*); + GdkWindow* m_window; + +#if defined(XP_UNIX) + GLXContext m_context; + Display* m_display; + bool m_needToCloseDisplay; +#endif +}; + +} + +#endif // WindowGLContext_h diff --git a/Source/WebCore/platform/graphics/gtk/WindowGLContextGLX.cpp b/Source/WebCore/platform/graphics/gtk/WindowGLContextGLX.cpp new file mode 100644 index 000000000..c16a4f41b --- /dev/null +++ b/Source/WebCore/platform/graphics/gtk/WindowGLContextGLX.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2012 Igalia, S.L. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "WindowGLContext.h" + +#include <GL/glx.h> +#include <gdk/gdk.h> +#include <gdk/gdkx.h> +#include <wtf/OwnPtr.h> + +namespace WebCore { + +PassOwnPtr<WindowGLContext> WindowGLContext::createContextWithGdkWindow(GdkWindow* window) +{ + OwnPtr<WindowGLContext> context = adoptPtr(new WindowGLContext(window)); + if (!context->m_context) + return nullptr; + return context.release(); +} + +WindowGLContext::WindowGLContext(GdkWindow* window) + : m_window(window) + , m_context(0) + , m_display(0) + , m_needToCloseDisplay(0) +{ + GdkDisplay* gdkDisplay = gdk_window_get_display(m_window); + if (gdkDisplay) + m_display = GDK_DISPLAY_XDISPLAY(gdkDisplay); + else { + m_display = XOpenDisplay(0); + m_needToCloseDisplay = true; + } + + XWindowAttributes attributes; + if (!XGetWindowAttributes(m_display, GDK_WINDOW_XID(m_window), &attributes)) + return; + + XVisualInfo visualInfo; + visualInfo.visualid = XVisualIDFromVisual(attributes.visual); + + int numReturned = 0; + XVisualInfo* visualInfoList = XGetVisualInfo(m_display, VisualIDMask, &visualInfo, &numReturned); + m_context = glXCreateContext(m_display, visualInfoList, 0, True); + XFree(visualInfoList); +} + +WindowGLContext::~WindowGLContext() +{ + if (!m_context) + return; + glXMakeCurrent(m_display, None, None); + glXDestroyContext(m_display, m_context); + + if (m_needToCloseDisplay) + XCloseDisplay(m_display); +} + +void WindowGLContext::startDrawing() +{ + glXMakeCurrent(m_display, GDK_WINDOW_XID(m_window), m_context); +} + +void WindowGLContext::finishDrawing() +{ + glXSwapBuffers(m_display, GDK_WINDOW_XID(m_window)); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/mac/FontMac.mm b/Source/WebCore/platform/graphics/mac/FontMac.mm index 8e23339f7..4afb5fbdb 100644 --- a/Source/WebCore/platform/graphics/mac/FontMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontMac.mm @@ -222,7 +222,16 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons ColorSpace fillColorSpace = context->fillColorSpace(); context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); - bool hasSimpleShadow = context->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont() && (!context->shadowsIgnoreTransforms() || context->getCTM().isIdentityOrTranslationOrFlipped()) && !context->isInTransparencyLayer(); + AffineTransform contextCTM = context->getCTM(); + float syntheticBoldOffset = font->syntheticBoldOffset(); + if (syntheticBoldOffset && !contextCTM.isIdentityOrTranslationOrFlipped()) { + FloatSize horizontalUnitSizeInDevicePixels = contextCTM.mapSize(FloatSize(1, 0)); + float horizontalUnitLengthInDevicePixels = sqrtf(horizontalUnitSizeInDevicePixels.width() * horizontalUnitSizeInDevicePixels.width() + horizontalUnitSizeInDevicePixels.height() * horizontalUnitSizeInDevicePixels.height()); + if (horizontalUnitLengthInDevicePixels) + syntheticBoldOffset /= horizontalUnitLengthInDevicePixels; + }; + + bool hasSimpleShadow = context->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont() && (!context->shadowsIgnoreTransforms() || contextCTM.isIdentityOrTranslationOrFlipped()) && !context->isInTransparencyLayer(); if (hasSimpleShadow) { // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing. context->clearShadow(); @@ -233,14 +242,14 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative. float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1); showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - if (font->syntheticBoldOffset()) - showGlyphsWithAdvances(FloatPoint(shadowTextX + font->syntheticBoldOffset(), shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + if (syntheticBoldOffset) + showGlyphsWithAdvances(FloatPoint(shadowTextX + syntheticBoldOffset, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); context->setFillColor(fillColor, fillColorSpace); } showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - if (font->syntheticBoldOffset()) - showGlyphsWithAdvances(FloatPoint(point.x() + font->syntheticBoldOffset(), point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + if (syntheticBoldOffset) + showGlyphsWithAdvances(FloatPoint(point.x() + syntheticBoldOffset, point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (hasSimpleShadow) context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index 36132cd7b..8ab06eb77 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -259,7 +259,8 @@ NSMutableDictionary *MediaPlayerPrivateQTKit::commonMovieAttributes() void MediaPlayerPrivateQTKit::createQTMovie(const String& url) { - NSURL *cocoaURL = KURL(ParsedURLString, url); + KURL kURL(ParsedURLString, url); + NSURL *cocoaURL = kURL; NSMutableDictionary *movieAttributes = commonMovieAttributes(); [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute]; @@ -282,9 +283,9 @@ void MediaPlayerPrivateQTKit::createQTMovie(const String& url) willUseProxy = NO; } - if (!willUseProxy) { + if (!willUseProxy && !kURL.protocolIsData()) { // Only pass the QTMovieOpenForPlaybackAttribute flag if there are no proxy servers, due - // to rdar://problem/7531776. + // to rdar://problem/7531776, or if not loading a data:// url due to rdar://problem/8103801. [movieAttributes setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"]; } diff --git a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp index 73320d187..67d42ba86 100644 --- a/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp @@ -35,7 +35,7 @@ #if PLATFORM(MAC) #include "ANGLE/ShaderLang.h" #include <OpenGL/gl.h> -#elif PLATFORM(GTK) +#elif PLATFORM(GTK) || PLATFORM(EFL) #include "OpenGLShims.h" #elif PLATFORM(QT) #include <cairo/OpenGLShims.h> @@ -149,7 +149,7 @@ void Extensions3DOpenGL::renderbufferStorageMultisample(unsigned long target, un Platform3DObject Extensions3DOpenGL::createVertexArrayOES() { m_context->makeContextCurrent(); -#if !PLATFORM(GTK) && !PLATFORM(QT) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object +#if !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(EFL) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object GLuint array = 0; glGenVertexArraysAPPLE(1, &array); return array; @@ -164,7 +164,7 @@ void Extensions3DOpenGL::deleteVertexArrayOES(Platform3DObject array) return; m_context->makeContextCurrent(); -#if !PLATFORM(GTK) && !PLATFORM(QT) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object +#if !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(EFL) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object glDeleteVertexArraysAPPLE(1, &array); #endif } @@ -175,7 +175,7 @@ GC3Dboolean Extensions3DOpenGL::isVertexArrayOES(Platform3DObject array) return GL_FALSE; m_context->makeContextCurrent(); -#if !PLATFORM(GTK) && !PLATFORM(QT) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object +#if !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(EFL) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object return glIsVertexArrayAPPLE(array); #else return GL_FALSE; @@ -188,7 +188,7 @@ void Extensions3DOpenGL::bindVertexArrayOES(Platform3DObject array) return; m_context->makeContextCurrent(); -#if !PLATFORM(GTK) && !PLATFORM(QT) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object +#if !PLATFORM(GTK) && !PLATFORM(QT) && !PLATFORM(EFL) && defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object glBindVertexArrayAPPLE(array); #endif } diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp index 47a41c6d0..8b4d9d49a 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp @@ -30,11 +30,13 @@ #include "GraphicsContext3D.h" #include "Extensions3DOpenGL.h" +#include "IntRect.h" +#include "IntSize.h" #include "NotImplemented.h" #if PLATFORM(MAC) #include <OpenGL/gl.h> -#elif PLATFORM(GTK) +#elif PLATFORM(GTK) || PLATFORM(EFL) #include "OpenGLShims.h" #elif PLATFORM(QT) #include <QtGlobal> @@ -43,58 +45,10 @@ namespace WebCore { -void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize) +bool GraphicsContext3D::reshapeFBOs(const IntSize& size) { - if (pixelsSize < m_currentWidth * m_currentHeight * 4) - return; - - makeContextCurrent(); - - bool mustRestoreFBO = false; - if (m_attrs.antialias) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - mustRestoreFBO = true; - } else { - if (m_boundFBO != m_fbo) { - mustRestoreFBO = true; - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - } - } - - GLint packAlignment = 4; - bool mustRestorePackAlignment = false; - ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); - if (packAlignment > 4) { - ::glPixelStorei(GL_PACK_ALIGNMENT, 4); - mustRestorePackAlignment = true; - } - - ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); - - if (mustRestorePackAlignment) - ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); - - if (mustRestoreFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); -} - -void GraphicsContext3D::reshape(int width, int height) -{ - if (!platformGraphicsContext3D()) - return; - - if (width == m_currentWidth && height == m_currentHeight) - return; - - m_currentWidth = width; - m_currentHeight = height; - - makeContextCurrent(); - validateAttributes(); - + const int width = size.width(); + const int height = size.height(); GLuint colorFormat, internalDepthStencilFormat = 0; if (m_attrs.alpha) { m_internalColorFormat = GL_RGBA8; @@ -108,7 +62,7 @@ void GraphicsContext3D::reshape(int width, int height) // See GraphicsContext3D::validateAttributes. Extensions3D* extensions = getExtensions(); - // Use a 24 bit depth buffer where we know we have it + // Use a 24 bit depth buffer where we know we have it. if (extensions->supports("GL_EXT_packed_depth_stencil")) internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT; else @@ -117,7 +71,7 @@ void GraphicsContext3D::reshape(int width, int height) bool mustRestoreFBO = false; - // resize multisample FBO + // Resize multisample FBO. if (m_attrs.antialias) { GLint maxSampleCount; ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount); @@ -177,166 +131,14 @@ void GraphicsContext3D::reshape(int width, int height) mustRestoreFBO = false; } - // Initialize renderbuffers to 0. - GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0; - GLint clearStencil = 0; - GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE; - GLuint stencilMask = 0xffffffff; - GLboolean isScissorEnabled = GL_FALSE; - GLboolean isDitherEnabled = GL_FALSE; - GLbitfield clearMask = GL_COLOR_BUFFER_BIT; - ::glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); - ::glClearColor(0, 0, 0, 0); - ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); - ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - if (m_attrs.depth) { - ::glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); - ::glClearDepth(1); - ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); - ::glDepthMask(GL_TRUE); - clearMask |= GL_DEPTH_BUFFER_BIT; - } - if (m_attrs.stencil) { - ::glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil); - ::glClearStencil(0); - ::glGetIntegerv(GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&stencilMask)); - ::glStencilMaskSeparate(GL_FRONT, 0xffffffff); - clearMask |= GL_STENCIL_BUFFER_BIT; - } - isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST); - ::glDisable(GL_SCISSOR_TEST); - isDitherEnabled = ::glIsEnabled(GL_DITHER); - ::glDisable(GL_DITHER); - - ::glClear(clearMask); - - ::glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); - ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); - if (m_attrs.depth) { - ::glClearDepth(clearDepth); - ::glDepthMask(depthMask); - } - if (m_attrs.stencil) { - ::glClearStencil(clearStencil); - ::glStencilMaskSeparate(GL_FRONT, stencilMask); - } - if (isScissorEnabled) - ::glEnable(GL_SCISSOR_TEST); - else - ::glDisable(GL_SCISSOR_TEST); - if (isDitherEnabled) - ::glEnable(GL_DITHER); - else - ::glDisable(GL_DITHER); - - if (mustRestoreFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); - - ::glFlush(); -} - -void GraphicsContext3D::prepareTexture() -{ - if (m_layerComposited) - return; - makeContextCurrent(); - if (m_attrs.antialias) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR); - } - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - ::glActiveTexture(GL_TEXTURE0); - ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); - ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0); - ::glBindTexture(GL_TEXTURE_2D, m_boundTexture0); - ::glActiveTexture(m_activeTexture); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); - ::glFinish(); - m_layerComposited = true; -} - -void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) -{ - makeContextCurrent(); - GLuint fbo; - if (buffer) - fbo = buffer; - else - fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo); - if (fbo != m_boundFBO) { - ::glBindFramebufferEXT(target, fbo); - m_boundFBO = fbo; - } -} - -void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - makeContextCurrent(); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - } - ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + return mustRestoreFBO; } -void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) +void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) { - makeContextCurrent(); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - } - ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); -} - -bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - if (!program) { - synthesizeGLError(INVALID_VALUE); - return false; - } - makeContextCurrent(); - GLint maxUniformSize = 0; - ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); - GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination - GLsizei nameLength = 0; - GLint size = 0; - GLenum type = 0; - ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name); - if (!nameLength) - return false; - info.name = String(name, nameLength); - info.type = type; - info.size = size; - return true; -} - - -void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) -{ - // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., - // all previous rendering calls should be done before reading pixels. - makeContextCurrent(); - ::glFlush(); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { - ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); - ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); - ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR); - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); - ::glFlush(); - } - ::glReadPixels(x, y, width, height, format, type, data); - if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) - ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO); + ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo); + ::glBlitFramebufferEXT(rect.x(), rect.y(), rect.maxX(), rect.maxY(), rect.x(), rect.y(), rect.maxX(), rect.maxY(), GL_COLOR_BUFFER_BIT, GL_LINEAR); } void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp index e68bba7fd..cf9d8f615 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,6 +36,8 @@ #include "HTMLCanvasElement.h" #include "ImageBuffer.h" #include "ImageData.h" +#include "IntRect.h" +#include "IntSize.h" #include "NotImplemented.h" #include "WebGLObject.h" #include <cstring> @@ -48,7 +51,7 @@ #if PLATFORM(MAC) #include <OpenGL/gl.h> -#elif PLATFORM(GTK) +#elif PLATFORM(GTK) || PLATFORM(EFL) #include "OpenGLShims.h" #elif PLATFORM(QT) #include <QtGlobal> @@ -57,12 +60,33 @@ namespace WebCore { +static bool systemAllowsMultisamplingOnATICards() +{ +#if PLATFORM(MAC) +#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) + return true; +#else + ASSERT(isMainThread()); + static SInt32 version; + if (!version) { + if (Gestalt(gestaltSystemVersion, &version) != noErr) + return false; + } + // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details + return version >= 0x1072; +#endif // SNOW_LEOPARD and LION +#else + return false; +#endif // PLATFORM(MAC) +} + void GraphicsContext3D::validateAttributes() { Extensions3D* extensions = getExtensions(); if (m_attrs.stencil) { - if (extensions->supports("GL_EXT_packed_depth_stencil")) { - extensions->ensureEnabled("GL_EXT_packed_depth_stencil"); + const char* packedDepthStencilExtension = isGLES2Compliant() ? "GL_OES_packed_depth_stencil" : "GL_EXT_packed_depth_stencil"; + if (extensions->supports(packedDepthStencilExtension)) { + extensions->ensureEnabled(packedDepthStencilExtension); // Force depth if stencil is true. m_attrs.depth = true; } else @@ -70,11 +94,12 @@ void GraphicsContext3D::validateAttributes() } if (m_attrs.antialias) { bool isValidVendor = true; - // Currently in Mac we only turn on antialias if vendor is NVIDIA. + // Currently in Mac we only turn on antialias if vendor is NVIDIA, + // or if ATI and on 10.7.2 and above. const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); - if (!std::strstr(vendor, "NVIDIA")) + if (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards())) isValidVendor = false; - if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample")) + if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) m_attrs.antialias = false; else extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); @@ -103,7 +128,7 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co if (!m_attrs.premultipliedAlpha) { for (int i = 0; i < totalBytes; i += 4) { - // Premultiply alpha + // Premultiply alpha. pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); @@ -124,7 +149,7 @@ bool GraphicsContext3D::paintCompositedResultsToCanvas(CanvasRenderingContext*) PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer*) { // Reading premultiplied alpha would involve unpremultiplying, which is - // lossy + // lossy. if (m_attrs.premultipliedAlpha) return 0; @@ -134,13 +159,148 @@ PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(Drawin readRenderingResults(pixels, totalBytes); - // Convert to RGBA + // Convert to RGBA. for (int i = 0; i < totalBytes; i += 4) std::swap(pixels[i], pixels[i + 2]); return imageData.release(); } +void GraphicsContext3D::prepareTexture() +{ + if (m_layerComposited) + return; + + makeContextCurrent(); + if (m_attrs.antialias) + resolveMultisamplingIfNecessary(IntRect(0, 0, m_currentWidth, m_currentHeight)); + + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glActiveTexture(GL_TEXTURE0); + ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); + ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0); + ::glBindTexture(GL_TEXTURE_2D, m_boundTexture0); + ::glActiveTexture(m_activeTexture); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + ::glFinish(); + m_layerComposited = true; +} + +void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize) +{ + int totalBytes = m_currentWidth * m_currentHeight * 4; + if (pixelsSize < totalBytes) + return; + + makeContextCurrent(); + + bool mustRestoreFBO = false; + if (m_attrs.antialias) { + resolveMultisamplingIfNecessary(IntRect(0, 0, m_currentWidth, m_currentHeight)); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + mustRestoreFBO = true; + } else { + if (m_boundFBO != m_fbo) { + mustRestoreFBO = true; + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + } + + GLint packAlignment = 4; + bool mustRestorePackAlignment = false; + ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); + if (packAlignment > 4) { + ::glPixelStorei(GL_PACK_ALIGNMENT, 4); + mustRestorePackAlignment = true; + } + + ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels); + if (isGLES2Compliant()) { + for (int i = 0; i < totalBytes; i += 4) + std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA. + } + + if (mustRestorePackAlignment) + ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); + + if (mustRestoreFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); +} + +void GraphicsContext3D::reshape(int width, int height) +{ + if (!platformGraphicsContext3D()) + return; + + if (width == m_currentWidth && height == m_currentHeight) + return; + + m_currentWidth = width; + m_currentHeight = height; + + makeContextCurrent(); + validateAttributes(); + + bool mustRestoreFBO = reshapeFBOs(IntSize(width, height)); + + // Initialize renderbuffers to 0. + GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0; + GLint clearStencil = 0; + GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE; + GLuint stencilMask = 0xffffffff; + GLboolean isScissorEnabled = GL_FALSE; + GLboolean isDitherEnabled = GL_FALSE; + GLbitfield clearMask = GL_COLOR_BUFFER_BIT; + ::glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); + ::glClearColor(0, 0, 0, 0); + ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); + ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + if (m_attrs.depth) { + ::glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); + ::glClearDepth(1); + ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); + ::glDepthMask(GL_TRUE); + clearMask |= GL_DEPTH_BUFFER_BIT; + } + if (m_attrs.stencil) { + ::glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil); + ::glClearStencil(0); + ::glGetIntegerv(GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&stencilMask)); + ::glStencilMaskSeparate(GL_FRONT, 0xffffffff); + clearMask |= GL_STENCIL_BUFFER_BIT; + } + isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST); + ::glDisable(GL_SCISSOR_TEST); + isDitherEnabled = ::glIsEnabled(GL_DITHER); + ::glDisable(GL_DITHER); + + ::glClear(clearMask); + + ::glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); + ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); + if (m_attrs.depth) { + ::glClearDepth(clearDepth); + ::glDepthMask(depthMask); + } + if (m_attrs.stencil) { + ::glClearStencil(clearStencil); + ::glStencilMaskSeparate(GL_FRONT, stencilMask); + } + if (isScissorEnabled) + ::glEnable(GL_SCISSOR_TEST); + else + ::glDisable(GL_SCISSOR_TEST); + if (isDitherEnabled) + ::glEnable(GL_DITHER); + else + ::glDisable(GL_DITHER); + + if (mustRestoreFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO); + + ::glFlush(); +} + IntSize GraphicsContext3D::getInternalFramebufferSize() const { return IntSize(m_currentWidth, m_currentHeight); @@ -174,6 +334,20 @@ void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer) ::glBindBuffer(target, buffer); } +void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) +{ + makeContextCurrent(); + GLuint fbo; + if (buffer) + fbo = buffer; + else + fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo); + if (fbo != m_boundFBO) { + ::glBindFramebufferEXT(target, fbo); + m_boundFBO = fbo; + } +} + void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer) { makeContextCurrent(); @@ -307,7 +481,7 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) entry.isValid = isValid; if (!isValid) - return; // Shader didn't validate, don't move forward with compiling translated source + return; // Shader didn't validate, don't move forward with compiling translated source. int translatedShaderLength = translatedShaderSource.length(); @@ -322,10 +496,34 @@ void GraphicsContext3D::compileShader(Platform3DObject shader) ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess); - // ASSERT that ANGLE generated GLSL will be accepted by OpenGL + // ASSERT that ANGLE generated GLSL will be accepted by OpenGL. ASSERT(GLCompileSuccess == GL_TRUE); } +void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) +{ + makeContextCurrent(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); +} + +void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) +{ + makeContextCurrent(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); +} + void GraphicsContext3D::cullFace(GC3Denum mode) { makeContextCurrent(); @@ -439,7 +637,7 @@ bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index makeContextCurrent(); GLint maxAttributeSize = 0; ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize); - GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination + GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination. GLsizei nameLength = 0; GLint size = 0; GLenum type = 0; @@ -451,6 +649,32 @@ bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index info.size = size; return true; } + +bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) +{ + if (!program) { + synthesizeGLError(INVALID_VALUE); + return false; + } + + makeContextCurrent(); + GLint maxUniformSize = 0; + ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); + + OwnArrayPtr<GLchar> name = adoptArrayPtr(new GLchar[maxUniformSize]); // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination. + GLsizei nameLength = 0; + GLint size = 0; + GLenum type = 0; + ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get()); + if (!nameLength) + return false; + + info.name = String(name.get(), nameLength); + info.type = type; + info.size = size; + + return true; +} void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) { @@ -586,6 +810,22 @@ void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units) ::glPolygonOffset(factor, units); } +void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) +{ + // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., + // all previous rendering calls should be done before reading pixels. + makeContextCurrent(); + ::glFlush(); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { + resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + ::glFlush(); + } + ::glReadPixels(x, y, width, height, format, type, data); + if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); +} + void GraphicsContext3D::releaseShaderCompiler() { // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants. @@ -686,7 +926,7 @@ void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1) void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 2 + // FIXME: length needs to be a multiple of 2. makeContextCurrent(); ::glUniform2fv(location, size, array); } @@ -699,7 +939,7 @@ void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 3 + // FIXME: length needs to be a multiple of 3. makeContextCurrent(); ::glUniform3fv(location, size, array); } @@ -712,7 +952,7 @@ void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 4 + // FIXME: length needs to be a multiple of 4. makeContextCurrent(); ::glUniform4fv(location, size, array); } @@ -737,7 +977,7 @@ void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1) void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dint* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 2 + // FIXME: length needs to be a multiple of 2. makeContextCurrent(); ::glUniform2iv(location, size, array); } @@ -750,7 +990,7 @@ void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3D void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dint* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 3 + // FIXME: length needs to be a multiple of 3. makeContextCurrent(); ::glUniform3iv(location, size, array); } @@ -763,28 +1003,28 @@ void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3D void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dint* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 4 + // FIXME: length needs to be a multiple of 4. makeContextCurrent(); ::glUniform4iv(location, size, array); } void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 4 + // FIXME: length needs to be a multiple of 4. makeContextCurrent(); ::glUniformMatrix2fv(location, size, transpose, array); } void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 9 + // FIXME: length needs to be a multiple of 9. makeContextCurrent(); ::glUniformMatrix3fv(location, size, transpose, array); } void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size) { - // FIXME: length needs to be a multiple of 16 + // FIXME: length needs to be a multiple of 16. makeContextCurrent(); ::glUniformMatrix4fv(location, size, transpose, array); } @@ -1050,7 +1290,7 @@ void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xo { makeContextCurrent(); - // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size + // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size. ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); } diff --git a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp index 90ff5a0a3..4faa6630f 100644 --- a/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp +++ b/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLES.cpp @@ -30,6 +30,8 @@ #include "GraphicsContext3D.h" +#include "IntRect.h" +#include "IntSize.h" #include "NotImplemented.h" #if PLATFORM(GTK) @@ -38,63 +40,102 @@ namespace WebCore { -void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize) +bool GraphicsContext3D::reshapeFBOs(const IntSize& size) { - notImplemented(); -} - -void GraphicsContext3D::reshape(int width, int height) -{ - notImplemented(); -} - -void GraphicsContext3D::prepareTexture() -{ - notImplemented(); -} - -void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) -{ - notImplemented(); + const int width = size.width(); + const int height = size.height(); + GLuint colorFormat = 0, pixelDataType = 0; + if (m_attrs.alpha) { + m_internalColorFormat = GL_RGBA; + colorFormat = GL_RGBA; + pixelDataType = GL_UNSIGNED_BYTE; + } else { + m_internalColorFormat = GL_RGB; + colorFormat = GL_RGB; + pixelDataType = GL_UNSIGNED_SHORT_5_6_5; + } + + // We don't allow the logic where stencil is required and depth is not. + // See GraphicsContext3D::validateAttributes. + bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions()->supports("GL_OES_packed_depth_stencil"); + + // Resize regular FBO. + bool mustRestoreFBO = false; + if (m_boundFBO != m_fbo) { + mustRestoreFBO = true; + ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + } + + ::glBindTexture(GL_TEXTURE_2D, m_texture); + ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, pixelDataType, 0); + ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0); + + ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); + ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); + ::glBindTexture(GL_TEXTURE_2D, 0); + + // We don't support antialiasing yet. See GraphicsContext3D::validateAttributes. + ASSERT(!m_attrs.antialias); + + if (m_attrs.stencil || m_attrs.depth) { + // Use a 24 bit depth buffer where we know we have it. + if (supportPackedDepthStencilBuffer) { + ::glBindTexture(GL_TEXTURE_2D, m_depthStencilBuffr); + ::glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL_OES, width, height, 0, GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES, 0); + if (m_attrs.stencil) + ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); + if (m_attrs.depth) + ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthStencilBuffer, 0); + ::glBindTexture(GL_TEXTURE_2D, 0); + } else { + if (m_attributes.stencil) { + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_stencilBuffer); + ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8, width, height); + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencilBuffer); + } + if (m_attributes.depth) { + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); + ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, width, height); + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); + } + ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + } + } + if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) { + // FIXME: cleanup + notImplemented(); + } + + return mustRestoreFBO; } -void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) -{ - notImplemented(); -} - -void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) -{ - notImplemented(); -} - -bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) -{ - notImplemented(); -} - - -void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) +void GraphicsContext3D::resolveMultisamplingIfNecessary(IntRect& rect) { + // FIXME: We don't support antialiasing yet. notImplemented(); } void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) { - notImplemented(); + makeContextCurrent(); + ::glRenderbufferStorageEXT(target, internalformat, width, height); } void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value) { - notImplemented(); + makeContextCurrent(); + ::glGetIntegerv(pname, value); } bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) { - notImplemented(); - return false; -} - + if (width && height && !pixels) { + synthesizeGLError(INVALID_VALUE); + return false; + } + makeContextCurrent(); + ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); + return true; } #endif // ENABLE(WEBGL) diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp index ddff6051c..9e69ce698 100644 --- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp +++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.cpp @@ -18,7 +18,6 @@ */ #include "config.h" - #include "TextureMapperGL.h" #include "GraphicsContext.h" @@ -31,6 +30,12 @@ #include <wtf/RefCounted.h> #if PLATFORM(QT) +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) +#include <QPlatformPixmap> +#endif +#endif + +#if PLATFORM(QT) || USE(CAIRO) #include <cairo/OpenGLShims.h> #elif defined(TEXMAP_OPENGL_ES_2) #include <GLES2/gl2.h> @@ -51,7 +56,14 @@ #include <GL/glx.h> #endif -#if !defined(TEXMAP_OPENGL_ES_2) && !PLATFORM(QT) +#if USE(CAIRO) +#include "CairoUtilities.h" +#include "RefPtrCairo.h" +#include <cairo.h> +#include <wtf/ByteArray.h> +#endif + +#if !defined(TEXMAP_OPENGL_ES_2) && !PLATFORM(QT) && !PLATFORM(GTK) extern "C" { void glUniform1f(GLint, GLfloat); void glUniform1i(GLint, GLint); @@ -265,57 +277,6 @@ struct TextureMapperGLData { }; - struct DirectlyCompositedImageRepository { - struct Entry { - GLuint texture; - int refCount; - }; - typedef HashMap<ImageUID, Entry> ImageTextureMap; - ImageTextureMap imageToTexture; - - GLuint findOrCreate(ImageUID image, bool& found) - { - ImageTextureMap::iterator it = imageToTexture.find(image); - found = false; - if (it != imageToTexture.end()) { - it->second.refCount++; - found = true; - return it->second.texture; - } - Entry entry; - GL_CMD(glGenTextures(1, &entry.texture)); - entry.refCount = 1; - imageToTexture.add(image, entry); - return entry.texture; - } - - bool deref(ImageUID image) - { - HashMap<ImageUID, Entry>::iterator it = imageToTexture.find(image); - if (it != imageToTexture.end()) { - if (it->second.refCount < 2) { - imageToTexture.remove(it); - return false; - } - } - return true; - } - - DirectlyCompositedImageRepository() - { - } - - ~DirectlyCompositedImageRepository() - { - for (ImageTextureMap::iterator it = imageToTexture.begin(); it != imageToTexture.end(); ++it) { - GLuint texture = it->second.texture; - if (texture) - GL_CMD(glDeleteTextures(1, &texture)); - } - - } - } directlyCompositedImages; - SharedGLData& sharedGLData() const { return *(m_sharedGLData.get()); @@ -332,6 +293,7 @@ struct TextureMapperGLData { int currentProgram; GLint previousProgram; GLint previousScissorState; + GLint viewport[4]; RefPtr<SharedGLData> m_sharedGLData; }; @@ -342,56 +304,25 @@ public: virtual bool isValid() const; virtual void reset(const IntSize&, bool opaque); void bind(); - virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect); - virtual void endPaint(); - virtual void setContentsToImage(Image*); ~BitmapTextureGL() { destroy(); } virtual uint32_t id() const { return m_id; } - inline bool isOpaque() const { return m_opaque; } inline FloatSize relativeSize() const { return m_relativeSize; } void setTextureMapper(TextureMapperGL* texmap) { m_textureMapper = texmap; } - - void updateContents(PixelFormat, const IntRect&, void*); - void updateRawContents(const IntRect&, const void*); - void pack() - { - // This is currently a stub. - if (isPacked()) - return; - m_isPacked = true; - } - - void unpack() - { - // This is currently a stub. - if (!isPacked()) - return; - m_isPacked = false; - } - - bool isPacked() const - { - return m_isPacked; - } + void updateContents(Image*, const IntRect&, const IntRect&, PixelFormat); + void updateContents(const void*, const IntRect&); private: GLuint m_id; - ImageUID m_imageUID; FloatSize m_relativeSize; - bool m_opaque; IntSize m_textureSize; - OwnPtr<BGRA32PremultimpliedBuffer> m_buffer; IntRect m_dirtyRect; GLuint m_fbo; GLuint m_rbo; IntSize m_actualSize; bool m_surfaceNeedsReset; - bool m_isPacked; TextureMapperGL* m_textureMapper; BitmapTextureGL() : m_id(0) - , m_imageUID(0) - , m_opaque(false) , m_fbo(0) , m_rbo(0) , m_surfaceNeedsReset(true) @@ -544,6 +475,7 @@ void TextureMapperGL::beginPainting() #endif glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); + glGetIntegerv(GL_VIEWPORT, data().viewport); bindSurface(0); } @@ -663,7 +595,6 @@ static void texImage2DResourceSafe(size_t width, size_t height) void BitmapTextureGL::reset(const IntSize& newSize, bool opaque) { BitmapTexture::reset(newSize, opaque); - m_imageUID = 0; IntSize newTextureSize = nextPowerOfTwo(newSize); bool justCreated = false; if (!m_id) { @@ -682,28 +613,10 @@ void BitmapTextureGL::reset(const IntSize& newSize, bool opaque) } m_actualSize = newSize; m_relativeSize = FloatSize(float(newSize.width()) / m_textureSize.width(), float(newSize.height()) / m_textureSize.height()); - m_opaque = opaque; m_surfaceNeedsReset = true; } -PlatformGraphicsContext* BitmapTextureGL::beginPaint(const IntRect& dirtyRect) -{ - m_buffer = BGRA32PremultimpliedBuffer::create(); - m_dirtyRect = dirtyRect; - return m_buffer->beginPaint(dirtyRect, m_opaque); -} - -void BitmapTextureGL::endPaint() -{ - if (!m_buffer) - return; - m_buffer->endPaint(); - updateContents(BGRAFormat, m_dirtyRect, m_buffer->data()); - GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id)) - m_buffer.clear(); -} - -#ifdef TEXMAP_OPENGL_ES_2 +#if PLATFORM(QT) || (USE(CAIRO) && defined(TEXMAP_OPENGL_ES_2)) static void swizzleBGRAToRGBA(uint32_t* data, const IntSize& size) { int width = size.width(); @@ -716,77 +629,62 @@ static void swizzleBGRAToRGBA(uint32_t* data, const IntSize& size) } #endif -void BitmapTextureGL::updateContents(PixelFormat pixelFormat, const IntRect& rect, void* bits) +void BitmapTextureGL::updateContents(const void* data, const IntRect& targetRect) { GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id)) -#ifdef TEXMAP_OPENGL_ES_2 - bool shouldSwizzle = false; -#endif - - GLint glFormat = GL_RGBA; - switch (pixelFormat) { - case RGBAFormat: - glFormat = GL_RGBA; - break; - case RGBFormat: - glFormat = GL_RGB; - break; - case BGRAFormat: -#ifdef TEXMAP_OPENGL_ES_2 - shouldSwizzle = true; - glFormat = GL_RGBA; -#else - glFormat = GL_BGRA; -#endif - break; - case BGRFormat: -#ifdef TEXMAP_OPENGL_ES_2 - shouldSwizzle = true; - glFormat = GL_RGB; -#else - glFormat = GL_BGR; -#endif - break; - } - -#ifdef TEXMAP_OPENGL_ES_2 - if (shouldSwizzle) - swizzleBGRAToRGBA(static_cast<uint32_t*>(bits), rect.size()); -#endif - GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), glFormat, GL_UNSIGNED_BYTE, bits)) + GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), GL_RGBA, GL_UNSIGNED_BYTE, data)) } -void BitmapTextureGL::updateRawContents(const IntRect& rect, const void* bits) +void BitmapTextureGL::updateContents(Image* image, const IntRect& targetRect, const IntRect& sourceRect, BitmapTexture::PixelFormat format) { + if (!image) + return; GL_CMD(glBindTexture(GL_TEXTURE_2D, m_id)) GLuint glFormat = isOpaque() ? GL_RGB : GL_RGBA; - GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), glFormat, GL_UNSIGNED_BYTE, bits)) -} - -void BitmapTextureGL::setContentsToImage(Image* image) -{ - ImageUID uid = image ? uidForImage(image) : 0; - if (!image || !uid) { - if (m_imageUID) - destroy(); + NativeImagePtr frameImage = image->nativeImageForCurrentFrame(); + if (!frameImage) return; - } - if (uid == m_imageUID) - return; - bool found = false; - GLuint newTextureID = m_textureMapper->data().directlyCompositedImages.findOrCreate(uid, found); - if (newTextureID != m_id) { - m_imageUID = uid; - destroy(); - m_id = newTextureID; - reset(image->size(), false); - if (!found) { - GraphicsContext context(beginPaint(IntRect(0, 0, m_textureSize.width(), m_textureSize.height()))); - context.drawImage(image, ColorSpaceDeviceRGB, IntPoint(0, 0), CompositeCopy); - endPaint(); - } - } +#if PLATFORM(QT) + QImage qtImage; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + // With QPA, we can avoid a deep copy. + qtImage = *frameImage->handle()->buffer(); +#else + // This might be a deep copy, depending on other references to the pixmap. + qtImage = frameImage->toImage(); +#endif + + if (IntSize(qtImage.size()) != sourceRect.size()) + qtImage = qtImage.copy(sourceRect); + if (format == BGRAFormat || format == BGRFormat) + swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(qtImage.bits()), qtImage.size()); + GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(), glFormat, GL_UNSIGNED_BYTE, qtImage.constBits())) + +#elif USE(CAIRO) + +#if !CPU(BIG_ENDIAN) +#if defined(TEXMAP_OPENGL_ES_2) + swizzleBGRAToRGBA(reinterpret_cast<uint32_t*>(cairo_image_surface_get_data(frameImage)), + cairo_image_surface_get_stride(frameImage) * cairo_image_surface_get_height(frameImage)); +#else + glFormat = isOpaque() ? GL_BGR : GL_BGRA; +#endif +#endif + + glPixelStorei(GL_UNPACK_ROW_LENGTH, cairo_image_surface_get_stride(frameImage) / 4); + glPixelStorei(GL_UNPACK_SKIP_ROWS, sourceRect.y()); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, sourceRect.x()); + GL_CMD(glTexSubImage2D(GL_TEXTURE_2D, 0, + targetRect.x(), targetRect.y(), + targetRect.width(), targetRect.height(), + glFormat, GL_UNSIGNED_BYTE, + cairo_image_surface_get_data(frameImage))); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); +#endif } static inline TransformationMatrix createProjectionMatrix(const IntSize& size, bool flip) @@ -837,7 +735,7 @@ void BitmapTextureGL::bind() void BitmapTextureGL::destroy() { - if (m_id && (!m_imageUID || !m_textureMapper->data().directlyCompositedImages.deref(m_imageUID))) + if (m_id) GL_CMD(glDeleteTextures(1, &m_id)) if (m_fbo) @@ -872,12 +770,13 @@ void TextureMapperGL::bindSurface(BitmapTexture *surfacePointer) BitmapTextureGL* surface = static_cast<BitmapTextureGL*>(surfacePointer); if (!surface) { + IntSize viewportSize(data().viewport[2], data().viewport[3]); GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, 0)) - data().projectionMatrix = createProjectionMatrix(viewportSize(), true).multiply(transform()); + data().projectionMatrix = createProjectionMatrix(viewportSize, true); GL_CMD(glStencilFunc(data().sharedGLData().stencilIndex > 1 ? GL_EQUAL : GL_ALWAYS, data().sharedGLData().stencilIndex - 1, data().sharedGLData().stencilIndex - 1)) GL_CMD(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP)) - GL_CMD(glViewport(0, 0, viewportSize().width(), viewportSize().height())) - data().sharedGLData().clipStack.append(IntRect(IntPoint::zero(), viewportSize())); + GL_CMD(glViewport(0, 0, viewportSize.width(), viewportSize.height())) + data().sharedGLData().clipStack.append(IntRect(data().viewport[0], data().viewport[1], data().viewport[2], data().viewport[3])); return; } @@ -985,4 +884,9 @@ PassRefPtr<BitmapTexture> TextureMapperGL::createTexture() return adoptRef(texture); } +PassOwnPtr<TextureMapper> TextureMapper::platformCreateAccelerated() +{ + return TextureMapperGL::create(); +} + }; diff --git a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h index 1b411857c..08fa0adef 100644 --- a/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h +++ b/Source/WebCore/platform/graphics/opengl/TextureMapperGL.h @@ -43,16 +43,17 @@ public: virtual void drawTexture(uint32_t texture, bool opaque, const FloatSize&, const FloatRect&, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture, bool flip); virtual void bindSurface(BitmapTexture* surface); virtual void beginClip(const TransformationMatrix&, const FloatRect&); + virtual void beginPainting(); + virtual void endPainting(); virtual void endClip(); - virtual bool allowSurfaceForRoot() const { return false; } virtual PassRefPtr<BitmapTexture> createTexture(); virtual const char* type() const; static PassOwnPtr<TextureMapperGL> create() { return adoptPtr(new TextureMapperGL); } - void beginPainting(); - void endPainting(); void setGraphicsContext(GraphicsContext* context) { m_context = context; } GraphicsContext* graphicsContext() { return m_context; } virtual bool isOpenGLBacked() const { return true; } + void platformUpdateContents(NativeImagePtr, const IntRect&, const IntRect&, BitmapTexture::PixelFormat); + virtual AccelerationMode accelerationMode() const { return OpenGLMode; } private: bool beginScissorClip(const TransformationMatrix&, const FloatRect&); @@ -64,16 +65,6 @@ private: }; // An offscreen buffer to be rendered by software. -class BGRA32PremultimpliedBuffer { - WTF_MAKE_FAST_ALLOCATED; -public: - virtual ~BGRA32PremultimpliedBuffer() { } - virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect, bool opaque) = 0; - virtual void endPaint() = 0; - virtual void* data() = 0; - static PassOwnPtr<BGRA32PremultimpliedBuffer> create(); -}; - static inline int nextPowerOfTwo(int num) { for (int i = 0x10000000; i > 0; i >>= 1) { diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp index 495bcadd3..66bc76e81 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp @@ -146,7 +146,7 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper* textureMapper { blitMultisampleFramebufferAndRestoreContext(); - if (textureMapper->isOpenGLBacked()) { + if (textureMapper->accelerationMode() == TextureMapper::OpenGLMode) { TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper); texmapGL->drawTexture(m_context->m_texture, !m_context->m_attrs.alpha, FloatSize(1, 1), targetRect, matrix, opacity, mask, true /* flip */); return; diff --git a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp index ec73c3feb..90079ee30 100644 --- a/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp +++ b/Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp @@ -1335,6 +1335,32 @@ void GraphicsContext::setCTM(const AffineTransform& transform) m_data->p()->setWorldTransform(transform); } +#if ENABLE(3D_RENDERING) && USE(TEXTURE_MAPPER) +TransformationMatrix GraphicsContext::get3DTransform() const +{ + if (paintingDisabled()) + return TransformationMatrix(); + + return platformContext()->combinedTransform(); +} + +void GraphicsContext::concat3DTransform(const TransformationMatrix& transform) +{ + if (paintingDisabled()) + return; + + m_data->p()->setWorldTransform(transform, true); +} + +void GraphicsContext::set3DTransform(const TransformationMatrix& transform) +{ + if (paintingDisabled()) + return; + + m_data->p()->setWorldTransform(transform, false); +} +#endif + void GraphicsContext::setURLForRect(const KURL&, const IntRect&) { notImplemented(); diff --git a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp index e36ff85b1..15f89b7ae 100644 --- a/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp +++ b/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp @@ -123,8 +123,10 @@ GraphicsContext* ImageBuffer::context() const PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const { - ASSERT(copyBehavior == CopyBackingStore); - return StillImage::create(m_data.m_pixmap); + if (copyBehavior == CopyBackingStore) + return StillImage::create(m_data.m_pixmap); + + return StillImage::createForRendering(&m_data.m_pixmap); } void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, @@ -299,8 +301,7 @@ static inline unsigned int premultiplyABGRtoARGB(unsigned int x) return x; } -template <Multiply multiplied> -void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size) +void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); @@ -308,24 +309,24 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& int originx = sourceRect.x(); int destx = destPoint.x() + sourceRect.x(); ASSERT(destx >= 0); - ASSERT(destx < size.width()); + ASSERT(destx < m_size.width()); ASSERT(originx >= 0); ASSERT(originx <= sourceRect.maxX()); int endx = destPoint.x() + sourceRect.maxX(); - ASSERT(endx <= size.width()); + ASSERT(endx <= m_size.width()); int numColumns = endx - destx; int originy = sourceRect.y(); int desty = destPoint.y() + sourceRect.y(); ASSERT(desty >= 0); - ASSERT(desty < size.height()); + ASSERT(desty < m_size.height()); ASSERT(originy >= 0); ASSERT(originy <= sourceRect.maxY()); int endy = destPoint.y() + sourceRect.maxY(); - ASSERT(endy <= size.height()); + ASSERT(endy <= m_size.height()); int numRows = endy - desty; unsigned srcBytesPerRow = 4 * sourceSize.width(); @@ -359,35 +360,25 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& } } - bool isPainting = data.m_painter->isActive(); + bool isPainting = m_data.m_painter->isActive(); if (!isPainting) - data.m_painter->begin(&data.m_pixmap); + m_data.m_painter->begin(&m_data.m_pixmap); else { - data.m_painter->save(); + m_data.m_painter->save(); // putImageData() should be unaffected by painter state - data.m_painter->resetTransform(); - data.m_painter->setOpacity(1.0); - data.m_painter->setClipping(false); + m_data.m_painter->resetTransform(); + m_data.m_painter->setOpacity(1.0); + m_data.m_painter->setClipping(false); } - data.m_painter->setCompositionMode(QPainter::CompositionMode_Source); - data.m_painter->drawImage(destx, desty, image); + m_data.m_painter->setCompositionMode(QPainter::CompositionMode_Source); + m_data.m_painter->drawImage(destx, desty, image); if (!isPainting) - data.m_painter->end(); + m_data.m_painter->end(); else - data.m_painter->restore(); -} - -void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size); -} - -void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size); + m_data.m_painter->restore(); } // We get a mimeType here but QImageWriter does not support mimetypes but diff --git a/Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp b/Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp deleted file mode 100644 index 44641ce63..000000000 --- a/Source/WebCore/platform/graphics/qt/TextureMapperQt.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include "TextureMapperQt.h" - -#include <QtCore/qdebug.h> -#include <QtGui/qpaintengine.h> -#include <QtGui/qpixmap.h> - -#if USE(TEXTURE_MAPPER_GL) -# include "opengl/TextureMapperGL.h" -#endif - -namespace WebCore { - -void BitmapTextureQt::destroy() -{ - if (m_pixmap.paintingActive()) - qFatal("Destroying an active pixmap"); - m_pixmap = QPixmap(); -} - -void BitmapTextureQt::reset(const IntSize& size, bool isOpaque) -{ - BitmapTexture::reset(size, isOpaque); - - if (size.width() > m_pixmap.size().width() || size.height() > m_pixmap.size().height() || m_pixmap.isNull()) - m_pixmap = QPixmap(size.width(), size.height()); - if (!isOpaque) - m_pixmap.fill(Qt::transparent); -} - -PlatformGraphicsContext* BitmapTextureQt::beginPaint(const IntRect& dirtyRect) -{ - m_painter.begin(&m_pixmap); - TextureMapperQt::initialize(&m_painter); - m_painter.setCompositionMode(QPainter::CompositionMode_Clear); - m_painter.fillRect(QRect(dirtyRect), Qt::transparent); - m_painter.setCompositionMode(QPainter::CompositionMode_SourceOver); - return &m_painter; -} - -void BitmapTextureQt::endPaint() -{ - m_painter.end(); -} - -void BitmapTextureQt::updateContents(PixelFormat pixelFormat, const IntRect& rect, void* bits) -{ - m_painter.begin(&m_pixmap); - QImage::Format qtFormat = QImage::Format_ARGB32_Premultiplied; - if (pixelFormat == BGRFormat || pixelFormat == RGBFormat) - qtFormat = QImage::Format_RGB32; - QImage image(static_cast<uchar*>(bits), rect.width(), rect.height(), qtFormat); - if (pixelFormat == BGRFormat || pixelFormat == BGRAFormat) - image = image.rgbSwapped(); - m_painter.setCompositionMode(QPainter::CompositionMode_Source); - m_painter.drawImage(rect, image); - m_painter.end(); -} - -bool BitmapTextureQt::save(const String& path) -{ - return m_pixmap.save(path, "PNG"); -} - -void BitmapTextureQt::setContentsToImage(Image* image) -{ - if (!image) - return; - const QPixmap* pixmap = image->nativeImageForCurrentFrame(); - if (!pixmap) - return; - BitmapTexture::reset(pixmap->size(), !pixmap->hasAlphaChannel()); - m_pixmap = *pixmap; -} - -void BitmapTextureQt::pack() -{ - if (m_pixmap.isNull()) - return; - - m_image = m_pixmap.toImage(); - m_pixmap = QPixmap(); - m_isPacked = true; -} - -void BitmapTextureQt::unpack() -{ - m_isPacked = false; - if (m_image.isNull()) - return; - - m_pixmap = QPixmap::fromImage(m_image); - m_image = QImage(); -} - -void TextureMapperQt::beginClip(const TransformationMatrix& matrix, const FloatRect& rect) -{ - QPainter* painter = currentPainter(); - painter->save(); - QTransform prevTransform = painter->transform(); - painter->setTransform(matrix, false); - painter->setClipRect(rect); - painter->setTransform(prevTransform, false); -} - -void TextureMapperQt::endClip() -{ - currentPainter()->restore(); -} - -IntSize TextureMapperQt::viewportSize() const -{ - return IntSize(m_painter->device()->width(), m_painter->device()->height()); -} - - -TextureMapperQt::TextureMapperQt() - : m_currentSurface(0) -{ -} - -void TextureMapperQt::setGraphicsContext(GraphicsContext* context) -{ - m_context = context; - m_painter = context ? context->platformContext() : 0; - initialize(m_painter); -} - -GraphicsContext* TextureMapperQt::graphicsContext() -{ - return m_context; -} - -void TextureMapperQt::bindSurface(BitmapTexture* surface) -{ - if (m_currentSurface == surface) - return; - if (m_currentSurface) - m_currentSurface->m_painter.end(); - if (!surface) { - m_currentSurface = 0; - return; - } - BitmapTextureQt* surfaceQt = static_cast<BitmapTextureQt*>(surface); - if (!surfaceQt->m_painter.isActive()) - surfaceQt->m_painter.begin(&surfaceQt->m_pixmap); - m_currentSurface = surfaceQt; -} - - -void TextureMapperQt::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture) -{ - const BitmapTextureQt& textureQt = static_cast<const BitmapTextureQt&>(texture); - QPainter* painter = m_painter; - QPixmap pixmap = textureQt.m_pixmap; - if (m_currentSurface) - painter = &m_currentSurface->m_painter; - - if (maskTexture && maskTexture->isValid()) { - const BitmapTextureQt* mask = static_cast<const BitmapTextureQt*>(maskTexture); - QPixmap intermediatePixmap(pixmap.size()); - intermediatePixmap.fill(Qt::transparent); - QPainter maskPainter(&intermediatePixmap); - maskPainter.setCompositionMode(QPainter::CompositionMode_Source); - maskPainter.drawPixmap(0, 0, pixmap); - maskPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn); - maskPainter.drawPixmap(QRect(0, 0, pixmap.width(), pixmap.height()), mask->m_pixmap, mask->sourceRect()); - maskPainter.end(); - pixmap = intermediatePixmap; - } - - const qreal prevOpacity = painter->opacity(); - const QTransform prevTransform = painter->transform(); - painter->setOpacity(opacity); - painter->setTransform(matrix, true); - painter->drawPixmap(targetRect, pixmap, FloatRect(textureQt.sourceRect())); - painter->setTransform(prevTransform); - painter->setOpacity(prevOpacity); -} - -PassOwnPtr<TextureMapper> TextureMapper::create(GraphicsContext* context) -{ -#if USE(TEXTURE_MAPPER_GL) - if (context && context->platformContext()->paintEngine()->type() == QPaintEngine::OpenGL2) - return adoptPtr(new TextureMapperGL); -#endif - return adoptPtr(new TextureMapperQt); -} - -PassRefPtr<BitmapTexture> TextureMapperQt::createTexture() -{ - return adoptRef(new BitmapTextureQt()); -} - -BitmapTextureQt::BitmapTextureQt() - : m_isPacked(false) -{ - -} - -void TextureMapperQt::beginPainting() -{ - m_painter->save(); -} - -void TextureMapperQt::endPainting() -{ - m_painter->restore(); -} - -#if USE(TEXTURE_MAPPER_GL) -class BGRA32PremultimpliedBufferQt : public BGRA32PremultimpliedBuffer { -public: - virtual PlatformGraphicsContext* beginPaint(const IntRect& rect, bool opaque) - { - // m_image is only using during paint, it's safe to override it. - m_image = QImage(rect.size().width(), rect.size().height(), opaque ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied); - if (!opaque) - m_image.fill(0); - m_painter.begin(&m_image); - TextureMapperQt::initialize(&m_painter); - m_painter.translate(-rect.x(), -rect.y()); - return &m_painter; - } - - virtual void endPaint() { m_painter.end(); } - virtual void* data() { return m_image.bits(); } - -private: - QPainter m_painter; - QImage m_image; -}; - -PassOwnPtr<BGRA32PremultimpliedBuffer> BGRA32PremultimpliedBuffer::create() -{ - return adoptPtr(new BGRA32PremultimpliedBufferQt()); -} - -uint64_t uidForImage(Image* image) -{ - return image->nativeImageForCurrentFrame()->serialNumber(); -} -#endif -}; diff --git a/Source/WebCore/platform/graphics/qt/TextureMapperQt.h b/Source/WebCore/platform/graphics/qt/TextureMapperQt.h deleted file mode 100644 index 08fee03f1..000000000 --- a/Source/WebCore/platform/graphics/qt/TextureMapperQt.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. - */ - -#include "texmap/TextureMapper.h" - -#ifndef TextureMapperQt_h -#define TextureMapperQt_h - -namespace WebCore { - -class BitmapTextureQt : public BitmapTexture { - friend class TextureMapperQt; -public: - BitmapTextureQt(); - ~BitmapTextureQt() { destroy(); } - virtual void destroy(); - virtual IntSize size() const { return IntSize(m_pixmap.width(), m_pixmap.height()); } - virtual void reset(const IntSize&, bool opaque); - virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect); - virtual void endPaint(); - virtual void setContentsToImage(Image*); - virtual bool save(const String& path); - virtual bool isValid() const { return !m_pixmap.isNull() || !m_image.isNull(); } - IntRect sourceRect() const { return IntRect(0, 0, contentSize().width(), contentSize().height()); } - virtual void pack(); - virtual void unpack(); - virtual bool isPacked() const { return m_isPacked; } - virtual void updateContents(PixelFormat, const IntRect&, void* bits); - - QPainter* painter() { return &m_painter; } - -private: - QPainter m_painter; - QPixmap m_pixmap; - QImage m_image; - bool m_isPacked; -}; - -class TextureMapperQt : public TextureMapper { -public: - TextureMapperQt(); - - virtual void drawTexture(const BitmapTexture&, const FloatRect& targetRect, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture); - virtual void bindSurface(BitmapTexture* surface); - virtual void beginClip(const TransformationMatrix&, const FloatRect&); - virtual void endClip(); - virtual void setGraphicsContext(GraphicsContext*); - virtual GraphicsContext* graphicsContext(); - virtual bool allowSurfaceForRoot() const { return false; } - virtual PassRefPtr<BitmapTexture> createTexture(); - virtual IntSize viewportSize() const; - virtual void beginPainting(); - virtual void endPainting(); - - static void initialize(QPainter* painter) - { - if (painter) - painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false); - } - - static PassOwnPtr<TextureMapper> create() { return adoptPtr(new TextureMapperQt); } -private: - inline QPainter* currentPainter() { return m_currentSurface ? m_currentSurface->painter() : m_painter; } - - QPainter* m_painter; - GraphicsContext* m_context; - RefPtr<BitmapTextureQt> m_currentSurface; -}; - -} -#endif diff --git a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp index 355a6b5ef..4f79cfb0b 100644 --- a/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp @@ -721,6 +721,11 @@ void GraphicsContext::drawLineForTextChecking(const FloatPoint& pt, float width, SkScalar originX = WebCoreFloatToSkScalar(pt.x()); #if PLATFORM(CHROMIUM) && OS(DARWIN) SkScalar originY = WebCoreFloatToSkScalar(pt.y()); + // Make sure to draw only complete dots. + int rowPixels = misspellBitmap->width(); + float widthMod = fmodf(width, rowPixels); + if (rowPixels - widthMod > 1) + width -= widthMod; #else // Offset it vertically by 1 so that there's some space under the text. SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1; diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp index eaa1d77b4..e0b52a318 100644 --- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp @@ -79,11 +79,6 @@ public: m_context3D->makeContextCurrent(); } - virtual void flush() - { - m_context3D->flush(); - } - private: GraphicsContext3D* m_context3D; }; @@ -280,34 +275,33 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect return getImageData<Premultiplied>(rect, context()->platformContext()->canvas(), m_size); } -template <Multiply multiplied> -void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, - SkCanvas* canvas, const IntSize& size) +void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { + SkCanvas* canvas = context()->platformContext()->canvas(); ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originX = sourceRect.x(); int destX = destPoint.x() + sourceRect.x(); ASSERT(destX >= 0); - ASSERT(destX < size.width()); + ASSERT(destX < m_size.width()); ASSERT(originX >= 0); ASSERT(originX < sourceRect.maxX()); int endX = destPoint.x() + sourceRect.maxX(); - ASSERT(endX <= size.width()); + ASSERT(endX <= m_size.width()); int numColumns = endX - destX; int originY = sourceRect.y(); int destY = destPoint.y() + sourceRect.y(); ASSERT(destY >= 0); - ASSERT(destY < size.height()); + ASSERT(destY < m_size.height()); ASSERT(originY >= 0); ASSERT(originY < sourceRect.maxY()); int endY = destPoint.y() + sourceRect.maxY(); - ASSERT(endY <= size.height()); + ASSERT(endY <= m_size.height()); int numRows = endY - destY; unsigned srcBytesPerRow = 4 * sourceSize.width(); @@ -324,16 +318,6 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& canvas->writePixels(srcBitmap, destX, destY, config8888); } -void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas(), m_size); -} - -void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas(), m_size); -} - template <typename T> static bool encodeImage(T& source, const String& mimeType, const double* quality, Vector<char>* output) { diff --git a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp index 64a4ee4f3..30b8a3805 100644 --- a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.cpp @@ -34,6 +34,8 @@ #include "PlatformContextSkia.h" +#include "SkCanvas.h" +#include "SkColorFilter.h" #include "SkShader.h" namespace WebCore { @@ -133,10 +135,19 @@ static inline bool paintIsOpaque(const SkPaint& paint, const SkBitmap* bitmap = return false; if (bitmap && !bitmap->isOpaque()) return false; + if (paint.getLooper()) + return false; + if (paint.getImageFilter()) + return false; + if (paint.getMaskFilter()) + return false; + SkColorFilter* colorFilter = paint.getColorFilter(); + if (colorFilter && !(colorFilter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag)) + return false; return true; } -void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* bitmap) +void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const AffineTransform& transform, const SkRect& fillRect, const SkPaint& paint, const SkBitmap* bitmap) { // Any stroking may put alpha in pixels even if the filling part does not. if (paint.getStyle() != SkPaint::kFill_Style) { @@ -148,21 +159,21 @@ void OpaqueRegionSkia::didDrawRect(const PlatformContextSkia* context, const SkR else { SkRect strokeRect; strokeRect = paint.computeFastBounds(fillRect, &strokeRect); - didDraw(context, strokeRect, paint, opaque, fillsBounds); + didDraw(context, transform, strokeRect, paint, opaque, fillsBounds); } } bool checkFillOnly = true; bool opaque = paintIsOpaque(paint, bitmap, checkFillOnly); bool fillsBounds = paint.getStyle() != SkPaint::kStroke_Style; - didDraw(context, fillRect, paint, opaque, fillsBounds); + didDraw(context, transform, fillRect, paint, opaque, fillsBounds); } -void OpaqueRegionSkia::didDrawPath(const PlatformContextSkia* context, const SkPath& path, const SkPaint& paint) +void OpaqueRegionSkia::didDrawPath(const PlatformContextSkia* context, const AffineTransform& transform, const SkPath& path, const SkPaint& paint) { SkRect rect; if (path.isRect(&rect)) { - didDrawRect(context, rect, paint, 0); + didDrawRect(context, transform, rect, paint, 0); return; } @@ -173,11 +184,11 @@ void OpaqueRegionSkia::didDrawPath(const PlatformContextSkia* context, const SkP didDrawUnbounded(paint, opaque); else { rect = paint.computeFastBounds(path.getBounds(), &rect); - didDraw(context, rect, paint, opaque, fillsBounds); + didDraw(context, transform, rect, paint, opaque, fillsBounds); } } -void OpaqueRegionSkia::didDrawPoints(const PlatformContextSkia* context, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) +void OpaqueRegionSkia::didDrawPoints(const PlatformContextSkia* context, const AffineTransform& transform, SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) { if (!numPoints) return; @@ -202,11 +213,11 @@ void OpaqueRegionSkia::didDrawPoints(const PlatformContextSkia* context, SkCanva didDrawUnbounded(paint, opaque); else { rect = paint.computeFastBounds(rect, &rect); - didDraw(context, rect, paint, opaque, fillsBounds); + didDraw(context, transform, rect, paint, opaque, fillsBounds); } } -void OpaqueRegionSkia::didDrawBounded(const PlatformContextSkia* context, const SkRect& bounds, const SkPaint& paint) +void OpaqueRegionSkia::didDrawBounded(const PlatformContextSkia* context, const AffineTransform& transform, const SkRect& bounds, const SkPaint& paint) { bool opaque = paintIsOpaque(paint); bool fillsBounds = false; @@ -216,16 +227,38 @@ void OpaqueRegionSkia::didDrawBounded(const PlatformContextSkia* context, const else { SkRect rect; rect = paint.computeFastBounds(bounds, &rect); - didDraw(context, rect, paint, opaque, fillsBounds); + didDraw(context, transform, rect, paint, opaque, fillsBounds); } } -void OpaqueRegionSkia::didDraw(const PlatformContextSkia* context, const SkRect& rect, const SkPaint& paint, bool drawsOpaque, bool fillsBounds) +void OpaqueRegionSkia::didDraw(const PlatformContextSkia* context, const AffineTransform& transform, const SkRect& rect, const SkPaint& paint, bool drawsOpaque, bool fillsBounds) { + SkRect targetRect = rect; + + // Apply the current clip. + if (context->canvas()->getClipType() != SkCanvas::kRect_ClipType) + fillsBounds = false; + else { + SkIRect deviceClip; + context->canvas()->getClipDeviceBounds(&deviceClip); + if (!targetRect.intersect(SkIntToScalar(deviceClip.fLeft), SkIntToScalar(deviceClip.fTop), SkIntToScalar(deviceClip.fRight), SkIntToScalar(deviceClip.fBottom))) + return; + } + if (!context->clippedToImage().isOpaque()) + fillsBounds = false; + + // Apply the transforms. + SkMatrix canvasTransform = context->canvas()->getTotalMatrix(); + if (!canvasTransform.mapRect(&targetRect)) + fillsBounds = false; + SkMatrix canvasToTargetTransform = transform; + if (!canvasToTargetTransform.mapRect(&targetRect)) + fillsBounds = false; + if (fillsBounds && xfermodeIsOpaque(paint, drawsOpaque)) - markRectAsOpaque(context, rect); - else if (SkRect::Intersects(rect, m_opaqueRect) && !xfermodePreservesOpaque(paint, drawsOpaque)) - markRectAsNonOpaque(rect); + markRectAsOpaque(targetRect); + else if (SkRect::Intersects(targetRect, m_opaqueRect) && !xfermodePreservesOpaque(paint, drawsOpaque)) + markRectAsNonOpaque(targetRect); } void OpaqueRegionSkia::didDrawUnbounded(const SkPaint& paint, bool drawsOpaque) @@ -236,7 +269,7 @@ void OpaqueRegionSkia::didDrawUnbounded(const SkPaint& paint, bool drawsOpaque) } } -void OpaqueRegionSkia::markRectAsOpaque(const PlatformContextSkia* context, const SkRect& rect) +void OpaqueRegionSkia::markRectAsOpaque(const SkRect& rect) { // We want to keep track of an opaque region but bound its complexity at a constant size. // We keep track of the largest rectangle seen by area. If we can add the new rect to this @@ -245,8 +278,6 @@ void OpaqueRegionSkia::markRectAsOpaque(const PlatformContextSkia* context, cons if (rect.isEmpty()) return; - if (!context->clippedToImage().isOpaque()) - return; if (m_opaqueRect.contains(rect)) return; if (rect.contains(m_opaqueRect)) { diff --git a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h index 93f2c5a1b..45b069004 100644 --- a/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h +++ b/Source/WebCore/platform/graphics/skia/OpaqueRegionSkia.h @@ -40,6 +40,7 @@ #include "SkRect.h" namespace WebCore { +class AffineTransform; class PlatformContextSkia; // This class is an encapsulation of functionality for PlatformContextSkia, and its methods are mirrored @@ -52,15 +53,15 @@ public: // The resulting opaque region as a single rect. IntRect asRect() const; - void didDrawRect(const PlatformContextSkia*, const SkRect&, const SkPaint&, const SkBitmap*); - void didDrawPath(const PlatformContextSkia*, const SkPath&, const SkPaint&); - void didDrawPoints(const PlatformContextSkia*, SkCanvas::PointMode, int numPoints, const SkPoint[], const SkPaint&); - void didDrawBounded(const PlatformContextSkia*, const SkRect&, const SkPaint&); + void didDrawRect(const PlatformContextSkia*, const AffineTransform&, const SkRect&, const SkPaint&, const SkBitmap*); + void didDrawPath(const PlatformContextSkia*, const AffineTransform&, const SkPath&, const SkPaint&); + void didDrawPoints(const PlatformContextSkia*, const AffineTransform&, SkCanvas::PointMode, int numPoints, const SkPoint[], const SkPaint&); + void didDrawBounded(const PlatformContextSkia*, const AffineTransform&, const SkRect&, const SkPaint&); private: - void didDraw(const PlatformContextSkia*, const SkRect&, const SkPaint&, bool drawsOpaque, bool fillsBounds); + void didDraw(const PlatformContextSkia*, const AffineTransform&, const SkRect&, const SkPaint&, bool drawsOpaque, bool fillsBounds); void didDrawUnbounded(const SkPaint&, bool drawsOpaque); - void markRectAsOpaque(const PlatformContextSkia*, const SkRect&); + void markRectAsOpaque(const SkRect&); void markRectAsNonOpaque(const SkRect&); SkRect m_opaqueRect; diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp index 034c3319e..c323a0d7e 100644 --- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp +++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.cpp @@ -32,7 +32,6 @@ #include "PlatformContextSkia.h" -#include "AffineTransform.h" #include "Extensions3D.h" #include "GraphicsContext.h" #include "GraphicsContext3D.h" @@ -50,9 +49,6 @@ #include "SkDashPathEffect.h" #include "SkShader.h" -#include "GrContext.h" -#include "SkGpuDevice.h" - #include <wtf/MathExtras.h> #include <wtf/Vector.h> @@ -612,25 +608,25 @@ void PlatformContextSkia::setGraphicsContext3D(GraphicsContext3D* context) void PlatformContextSkia::didDrawRect(const SkRect& rect, const SkPaint& paint, const SkBitmap* bitmap) { if (m_trackOpaqueRegion) - m_opaqueRegion.didDrawRect(this, rect, paint, bitmap); + m_opaqueRegion.didDrawRect(this, m_opaqueRegionTransform, rect, paint, bitmap); } void PlatformContextSkia::didDrawPath(const SkPath& path, const SkPaint& paint) { if (m_trackOpaqueRegion) - m_opaqueRegion.didDrawPath(this, path, paint); + m_opaqueRegion.didDrawPath(this, m_opaqueRegionTransform, path, paint); } void PlatformContextSkia::didDrawPoints(SkCanvas::PointMode mode, int numPoints, const SkPoint points[], const SkPaint& paint) { if (m_trackOpaqueRegion) - m_opaqueRegion.didDrawPoints(this, mode, numPoints, points, paint); + m_opaqueRegion.didDrawPoints(this, m_opaqueRegionTransform, mode, numPoints, points, paint); } void PlatformContextSkia::didDrawBounded(const SkRect& rect, const SkPaint& paint) { if (m_trackOpaqueRegion) - m_opaqueRegion.didDrawBounded(this, rect, paint); + m_opaqueRegion.didDrawBounded(this, m_opaqueRegionTransform, rect, paint); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h index fe3abb6f5..b306450cb 100644 --- a/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h +++ b/Source/WebCore/platform/graphics/skia/PlatformContextSkia.h @@ -31,6 +31,7 @@ #ifndef PlatformContextSkia_h #define PlatformContextSkia_h +#include "AffineTransform.h" #include "GraphicsContext.h" #include "Noncopyable.h" #include "OpaqueRegionSkia.h" @@ -152,6 +153,7 @@ public: // Returns the canvas used for painting, NOT guaranteed to be non-null. SkCanvas* canvas() { return m_canvas; } + const SkCanvas* canvas() const { return m_canvas; } InterpolationQuality interpolationQuality() const; void setInterpolationQuality(InterpolationQuality interpolationQuality); @@ -191,6 +193,8 @@ public: void setDeferred(bool deferred) { m_deferred = deferred; } void setTrackOpaqueRegion(bool track) { m_trackOpaqueRegion = track; } + // A transform applied to all tracked opaque paints. This is applied at the time the painting is done. + void setOpaqueRegionTransform(const AffineTransform& transform) { m_opaqueRegionTransform = transform; } // This will be an empty region unless tracking is enabled. const OpaqueRegionSkia& opaqueRegion() const { return m_opaqueRegion; } @@ -228,6 +232,7 @@ private: // Tracks the region painted opaque via the GraphicsContext. OpaqueRegionSkia m_opaqueRegion; bool m_trackOpaqueRegion; + AffineTransform m_opaqueRegionTransform; // Stores image sizes for a hint to compute image resampling modes. // Values are used in ImageSkia.cpp diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp index dd33f0d2a..5e528d46b 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.cpp @@ -20,6 +20,8 @@ #include "config.h" #include "TextureMapper.h" +#include "TextureMapperImageBuffer.h" + #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) namespace WebCore { @@ -71,5 +73,13 @@ PassRefPtr<BitmapTexture> TextureMapper::acquireTextureFromPool(const IntSize& s return selectedTexture; } + +PassOwnPtr<TextureMapper> TextureMapper::create(AccelerationMode mode) +{ + if (mode == SoftwareMode) + return TextureMapperImageBuffer::create(); + return platformCreateAccelerated(); +} + } #endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapper.h b/Source/WebCore/platform/graphics/texmap/TextureMapper.h index d66fe2fb4..f25ce0bc1 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapper.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapper.h @@ -47,46 +47,31 @@ class TextureMapper; class BitmapTexture : public RefCounted<BitmapTexture> { public: enum PixelFormat { BGRAFormat, RGBAFormat, BGRFormat, RGBFormat }; - BitmapTexture() : m_lockCount(0) {} + BitmapTexture() + : m_isOpaque(true) + { + } + virtual ~BitmapTexture() { } virtual void destroy() { } - virtual bool allowOfflineTextureUpload() const { return false; } virtual IntSize size() const = 0; - virtual int bpp() const { return 32; } + virtual void updateContents(Image*, const IntRect&, const IntRect&, BitmapTexture::PixelFormat) = 0; + virtual void updateContents(const void*, const IntRect&) = 0; virtual bool isValid() const = 0; + + virtual int bpp() const { return 32; } virtual void reset(const IntSize& size, bool opaque = false) { m_isOpaque = opaque; m_contentSize = size; } - virtual void pack() { } - virtual void unpack() { } - virtual bool isPacked() const { return false; } - - virtual PlatformGraphicsContext* beginPaint(const IntRect& dirtyRect) = 0; - virtual void endPaint() = 0; - - // For performance reasons, BitmapTexture might modify the bits directly (swizzle). - // Thus, this method is only recommended for buffer update, such as used by WebKit2. - virtual void updateContents(PixelFormat, const IntRect&, void* bits) = 0; - virtual void updateRawContents(const IntRect&, const void* bits) { } - virtual PlatformGraphicsContext* beginPaintMedia() - { - return beginPaint(IntRect(0, 0, size().width(), size().height())); - } - virtual void setContentsToImage(Image*) = 0; - virtual bool save(const String&) { return false; } - - inline void lock() { ++m_lockCount; } - inline void unlock() { --m_lockCount; } - inline bool isLocked() { return m_lockCount; } inline IntSize contentSize() const { return m_contentSize; } inline int numberOfBytes() const { return size().width() * size().height() * bpp() >> 3; } + inline bool isOpaque() const { return m_isOpaque; } protected: - int m_lockCount; IntSize m_contentSize; bool m_isOpaque; }; @@ -97,32 +82,26 @@ class TextureMapper { friend class BitmapTexture; public: - static PassOwnPtr<TextureMapper> create(GraphicsContext* graphicsContext = 0); + enum AccelerationMode { SoftwareMode, OpenGLMode }; + static PassOwnPtr<TextureMapper> create(AccelerationMode newMode = SoftwareMode); virtual ~TextureMapper() { } virtual void drawTexture(const BitmapTexture&, const FloatRect& target, const TransformationMatrix& modelViewMatrix = TransformationMatrix(), float opacity = 1.0f, const BitmapTexture* maskTexture = 0) = 0; // makes a surface the target for the following drawTexture calls. virtual void bindSurface(BitmapTexture* surface) = 0; - virtual void setGraphicsContext(GraphicsContext*) = 0; - virtual GraphicsContext* graphicsContext() = 0; + virtual void setGraphicsContext(GraphicsContext* context) { m_context = context; } + virtual GraphicsContext* graphicsContext() { return m_context; } virtual void beginClip(const TransformationMatrix&, const FloatRect&) = 0; virtual void endClip() = 0; - virtual bool allowSurfaceForRoot() const = 0; virtual PassRefPtr<BitmapTexture> createTexture() = 0; - IntSize viewportSize() const { return m_viewportSize; } - void setViewportSize(const IntSize& s) { m_viewportSize = s; } void setImageInterpolationQuality(InterpolationQuality quality) { m_interpolationQuality = quality; } void setTextDrawingMode(TextDrawingModeFlags mode) { m_textDrawingMode = mode; } InterpolationQuality imageInterpolationQuality() const { return m_interpolationQuality; } TextDrawingModeFlags textDrawingMode() const { return m_textDrawingMode; } - virtual bool allowPartialUpdates() const { return false; } - virtual bool isOpenGLBacked() const { return false; } - - void setTransform(const TransformationMatrix& matrix) { m_transform = matrix; } - TransformationMatrix transform() const { return m_transform; } + virtual AccelerationMode accelerationMode() const = 0; virtual void beginPainting() { } virtual void endPainting() { } @@ -130,7 +109,6 @@ public: // A surface is released implicitly when dereferenced. virtual PassRefPtr<BitmapTexture> acquireTextureFromPool(const IntSize&); - protected: TextureMapper() : m_interpolationQuality(InterpolationDefault) @@ -138,14 +116,21 @@ protected: {} private: +#if USE(TEXTURE_MAPPER_GL) + static PassOwnPtr<TextureMapper> platformCreateAccelerated(); +#else + static PassOwnPtr<TextureMapper> platformCreateAccelerated() + { + return PassOwnPtr<TextureMapper>(); + } +#endif InterpolationQuality m_interpolationQuality; TextDrawingModeFlags m_textDrawingMode; - TransformationMatrix m_transform; - IntSize m_viewportSize; Vector<RefPtr<BitmapTexture> > m_texturePool; + GraphicsContext* m_context; }; -}; +} #endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp index 09714d909..6be518a8b 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperAnimation.cpp @@ -26,7 +26,17 @@ #if USE(TEXTURE_MAPPER) namespace WebCore { -static double normalizedAnimationValue(double runningTime, double duration, bool alternate) + +static bool shouldReverseAnimationValue(Animation::AnimationDirection direction, int loopCount) +{ + if (((direction == Animation::AnimationDirectionAlternate) && (loopCount & 1)) + || ((direction == Animation::AnimationDirectionAlternateReverse) && !(loopCount & 1)) + || direction == Animation::AnimationDirectionReverse) + return true; + return false; +} + +static double normalizedAnimationValue(double runningTime, double duration, Animation::AnimationDirection direction) { if (!duration) return 0; @@ -35,7 +45,8 @@ static double normalizedAnimationValue(double runningTime, double duration, bool const double lastFullLoop = duration * double(loopCount); const double remainder = runningTime - lastFullLoop; const double normalized = remainder / duration; - return (loopCount % 2 && alternate) ? (1 - normalized) : normalized; + + return shouldReverseAnimationValue(direction, loopCount) ? 1 - normalized : normalized; } static float applyOpacityAnimation(float fromOpacity, float toOpacity, double progress) diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp new file mode 100644 index 000000000..783b03bf7 --- /dev/null +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.cpp @@ -0,0 +1,105 @@ +/* + Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "TextureMapperImageBuffer.h" + +#if USE(TEXTURE_MAPPER) +namespace WebCore { + +void BitmapTextureImageBuffer::updateContents(const void* data, const IntRect& targetRect) +{ +#if PLATFORM(QT) + QImage image(reinterpret_cast<const uchar*>(data), targetRect.width(), targetRect.height(), targetRect.width() * 4, QImage::Format_ARGB32_Premultiplied); + QPainter* painter = m_image->context()->platformContext(); + painter->save(); + painter->setCompositionMode(QPainter::CompositionMode_Source); + painter->drawImage(targetRect, image); + painter->restore(); +#endif +} + +void BitmapTextureImageBuffer::updateContents(Image* image, const IntRect& targetRect, const IntRect& sourceRect, PixelFormat) +{ + m_image->context()->drawImage(image, ColorSpaceDeviceRGB, targetRect, sourceRect, CompositeCopy); +} + +void TextureMapperImageBuffer::beginClip(const TransformationMatrix& matrix, const FloatRect& rect) +{ + GraphicsContext* context = currentContext(); + if (!context) + return; +#if ENABLE(3D_RENDERING) + TransformationMatrix previousTransform = context->get3DTransform(); +#else + AffineTransform previousTransform = context->getCTM(); +#endif + context->save(); + +#if ENABLE(3D_RENDERING) + context->concat3DTransform(matrix); +#else + context->concatCTM(matrix.toAffineTransform()); +#endif + + context->clip(rect); + +#if ENABLE(3D_RENDERING) + context->set3DTransform(previousTransform); +#else + context->setCTM(previousTransform); +#endif +} + +void TextureMapperImageBuffer::drawTexture(const BitmapTexture& texture, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, const BitmapTexture* maskTexture) +{ + GraphicsContext* context = currentContext(); + if (!context) + return; + + const BitmapTextureImageBuffer& textureImageBuffer = static_cast<const BitmapTextureImageBuffer&>(texture); + ImageBuffer* image = textureImageBuffer.m_image.get(); + OwnPtr<ImageBuffer> maskedImage; + + if (maskTexture && maskTexture->isValid()) { + const BitmapTextureImageBuffer* mask = static_cast<const BitmapTextureImageBuffer*>(maskTexture); + maskedImage = ImageBuffer::create(maskTexture->contentSize()); + GraphicsContext* maskContext = maskedImage->context(); + maskContext->drawImageBuffer(image, ColorSpaceDeviceRGB, IntPoint::zero(), CompositeCopy); + if (opacity < 1) { + maskContext->setAlpha(opacity); + opacity = 1; + } + maskContext->drawImageBuffer(mask->m_image.get(), ColorSpaceDeviceRGB, IntPoint::zero(), CompositeDestinationIn); + image = maskedImage.get(); + } + + context->save(); + context->setAlpha(opacity); +#if ENABLE(3D_RENDERING) + context->concat3DTransform(matrix); +#else + context->concatCTM(matrix.toAffineTransform()); +#endif + context->drawImageBuffer(image, ColorSpaceDeviceRGB, targetRect); + context->restore(); +} + +} +#endif diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h new file mode 100644 index 000000000..8411206cf --- /dev/null +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperImageBuffer.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#ifndef TextureMapperImageBuffer_h +#define TextureMapperImageBuffer_h + +#include "ImageBuffer.h" +#include "TextureMapper.h" + +#if USE(TEXTURE_MAPPER) +namespace WebCore { + +class BitmapTextureImageBuffer : public BitmapTexture { + friend class TextureMapperImageBuffer; +public: + static PassRefPtr<BitmapTexture> create() { return adoptRef(new BitmapTextureImageBuffer); } + ~BitmapTextureImageBuffer() { destroy(); } + virtual void destroy() { m_image.clear(); } + virtual IntSize size() const { return m_image->size(); } + virtual void reset(const IntSize& size, bool opaque) + { + BitmapTexture::reset(size, opaque); + m_image = ImageBuffer::create(size); + } + + virtual bool isValid() const { return m_image; } + inline GraphicsContext* graphicsContext() { return m_image ? m_image->context() : 0; } + virtual void updateContents(Image*, const IntRect&, const IntRect&, PixelFormat); + void updateContents(const void* data, const IntRect& targetRect); +private: + BitmapTextureImageBuffer() { } + OwnPtr<ImageBuffer> m_image; +}; + + +class TextureMapperImageBuffer : public TextureMapper { +public: + virtual void drawTexture(const BitmapTexture&, const FloatRect& targetRect, const TransformationMatrix&, float opacity, const BitmapTexture* maskTexture); + virtual void beginClip(const TransformationMatrix&, const FloatRect&); + virtual void bindSurface(BitmapTexture* surface) { m_currentSurface = surface;} + virtual void endClip() { graphicsContext()->restore(); } + static PassOwnPtr<TextureMapper> create() { return adoptPtr(new TextureMapperImageBuffer); } + PassRefPtr<BitmapTexture> createTexture() { return BitmapTextureImageBuffer::create(); } + inline GraphicsContext* currentContext() + { + return m_currentSurface ? static_cast<BitmapTextureImageBuffer*>(m_currentSurface.get())->graphicsContext() : graphicsContext(); + } + + virtual AccelerationMode accelerationMode() const { return SoftwareMode; } + +private: + RefPtr<BitmapTexture> m_currentSurface; +}; + +} +#endif // USE(TEXTURE_MAPPER) + +#endif // TextureMapperImageBuffer_h diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp index ccf49bc98..45b94bd91 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.cpp @@ -23,6 +23,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "GraphicsLayerTextureMapper.h" +#include "ImageBuffer.h" #include "MathExtras.h" namespace { @@ -156,12 +157,10 @@ void TextureMapperNode::renderContent(TextureMapper* textureMapper, GraphicsLaye if (!textureMapper) return; - // FIXME: Add directly composited images. - FloatRect dirtyRect = m_currentContent.needsDisplay ? entireRect() : m_currentContent.needsDisplayRect; + IntRect dirtyRect = enclosingIntRect(m_currentContent.needsDisplay ? entireRect() : m_currentContent.needsDisplayRect); for (size_t tileIndex = 0; tileIndex < m_ownedTiles.size(); ++tileIndex) { OwnedTile& tile = m_ownedTiles[tileIndex]; - FloatRect rect = dirtyRect; if (!tile.texture) tile.texture = textureMapper->createTexture(); RefPtr<BitmapTexture>& texture = tile.texture; @@ -169,31 +168,48 @@ void TextureMapperNode::renderContent(TextureMapper* textureMapper, GraphicsLaye if (tile.needsReset || texture->contentSize() != tileSize || !texture->isValid()) { tile.needsReset = false; - texture->reset(tileSize, m_currentContent.contentType == DirectImageContentType ? false : m_state.contentsOpaque); - rect = tile.rect; + texture->reset(tileSize, m_state.contentsOpaque); + dirtyRect.unite(enclosingIntRect(tile.rect)); } + } + + if (dirtyRect.isEmpty()) + return; + + // Paint the entire dirty rect into an image buffer. This ensures we only paint once. + OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(dirtyRect.size()); + GraphicsContext* context = imageBuffer->context(); + context->setImageInterpolationQuality(textureMapper->imageInterpolationQuality()); + context->setTextDrawingMode(textureMapper->textDrawingMode()); + context->translate(-dirtyRect.x(), -dirtyRect.y()); + layer->paintGraphicsLayerContents(*context, dirtyRect); + if (m_currentContent.contentType == DirectImageContentType) + context->drawImage(m_currentContent.image.get(), ColorSpaceDeviceRGB, m_state.contentsRect); + + RefPtr<Image> image; + +#if PLATFORM(QT) + image = imageBuffer->copyImage(DontCopyBackingStore); +#else + // FIXME: support DontCopyBackingStore in non-Qt ports that use TextureMapper. + image = imageBuffer->copyImage(CopyBackingStore); +#endif - IntRect contentRect = enclosingIntRect(tile.rect); - contentRect.intersect(enclosingIntRect(rect)); - if (contentRect.isEmpty()) + // Divide the image to tiles. + for (size_t tileIndex = 0; tileIndex < m_ownedTiles.size(); ++tileIndex) { + OwnedTile& tile = m_ownedTiles[tileIndex]; + IntRect targetRect = enclosingIntRect(tile.rect); + targetRect.intersect(dirtyRect); + if (targetRect.isEmpty()) continue; + IntRect sourceRect = targetRect; - FloatRect contentRectInTileCoordinates = contentRect; - FloatPoint offset(-tile.rect.x(), -tile.rect.y()); - contentRectInTileCoordinates.move(offset.x(), offset.y()); - - { - GraphicsContext context(texture->beginPaint(enclosingIntRect(contentRectInTileCoordinates))); - context.setImageInterpolationQuality(textureMapper->imageInterpolationQuality()); - context.setTextDrawingMode(textureMapper->textDrawingMode()); - context.translate(offset.x(), offset.y()); - FloatRect scaledContentRect(contentRect); - if (m_currentContent.contentType == DirectImageContentType) - context.drawImage(m_currentContent.image.get(), ColorSpaceDeviceRGB, IntPoint(0, 0)); - else - layer->paintGraphicsLayerContents(context, enclosingIntRect(scaledContentRect)); - texture->endPaint(); - } + // Normalize sourceRect to the buffer's coordinates. + sourceRect.move(-dirtyRect.x(), -dirtyRect.y()); + + // Normalize targetRect to the texture's coordinqates. + targetRect.move(-tile.rect.x(), -tile.rect.y()); + tile.texture->updateContents(image.get(), targetRect, sourceRect, BitmapTexture::RGBAFormat); } m_currentContent.needsDisplay = false; @@ -481,7 +497,7 @@ void TextureMapperNode::clearAllDirectlyCompositedImageTiles() } } -void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, const void* bits) +void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, const void* data) { ASSERT(m_textureMapper); @@ -498,7 +514,7 @@ void TextureMapperNode::setContentsTileBackBuffer(int id, const IntRect& sourceR if (!tile.backBuffer.texture) tile.backBuffer.texture = m_textureMapper->createTexture(); tile.backBuffer.texture->reset(sourceRect.size(), false); - tile.backBuffer.texture->updateRawContents(sourceRect, bits); + tile.backBuffer.texture->updateContents(data, sourceRect); tile.isBackBufferUpdated = true; } diff --git a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h index fe4b14c73..230c9e0e0 100644 --- a/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h +++ b/Source/WebCore/platform/graphics/texmap/TextureMapperNode.h @@ -148,7 +148,7 @@ public: void setTileOwnership(TileOwnership ownership) { m_state.tileOwnership = ownership; } int createContentsTile(float scale); void removeContentsTile(int id); - void setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, const void* bits); + void setContentsTileBackBuffer(int id, const IntRect& sourceRect, const IntRect& targetRect, const void*); void setTileBackBufferTextureForDirectlyCompositedImage(int id, const IntRect& sourceRect, const FloatRect& targetRect, BitmapTexture*); void clearAllDirectlyCompositedImageTiles(); void purgeNodeTexturesRecursive(); diff --git a/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp b/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp index 39ef15503..0d4e0ba60 100644 --- a/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp +++ b/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp @@ -183,9 +183,9 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect return getImageData<true>(rect, m_data.m_bitmap.get()); } -template <bool premultiplied> -static void putImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, SharedBitmap* bitmap) +void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { + SharedBitmap* bitmap = m_data.m_bitmap.get(); unsigned char* dst = (unsigned char*)bitmap->bytes(); if (!dst) return; @@ -211,7 +211,7 @@ static void putImageData(ByteArray* source, const IntSize& sourceSize, const Int int green = *src++; int blue = *src++; int alpha = *src++; - if (premultiplied) { + if (multiplied == Premultiplied) { *dst++ = static_cast<unsigned char>(blue * 255 / alpha); *dst++ = static_cast<unsigned char>(green * 255 / alpha); *dst++ = static_cast<unsigned char>(red * 255 / alpha); @@ -228,16 +228,6 @@ static void putImageData(ByteArray* source, const IntSize& sourceSize, const Int } } -void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<false>(source, sourceSize, sourceRect, destPoint, m_data.m_bitmap.get()); -} - -void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - putImageData<true>(source, sourceSize, sourceRect, destPoint, m_data.m_bitmap.get()); -} - void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) { UNUSED_PARAM(lookUpTable); diff --git a/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp index 7c909b54d..2dbb1961d 100644 --- a/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp +++ b/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp @@ -72,12 +72,7 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect return 0; } -void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) -{ - notImplemented(); -} - -void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) +void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint) { notImplemented(); } diff --git a/Source/WebCore/platform/gtk/GtkUtilities.cpp b/Source/WebCore/platform/gtk/GtkUtilities.cpp index 246687958..c98b5ba36 100644 --- a/Source/WebCore/platform/gtk/GtkUtilities.cpp +++ b/Source/WebCore/platform/gtk/GtkUtilities.cpp @@ -34,10 +34,15 @@ IntPoint convertWidgetPointToScreenPoint(GtkWidget* widget, const IntPoint& poin if (!toplevelWidget || !gtk_widget_is_toplevel(toplevelWidget) || !GTK_IS_WINDOW(toplevelWidget)) return point; + GdkWindow* gdkWindow = gtk_widget_get_window(toplevelWidget); + if (!gdkWindow) + return point; + int xInWindow, yInWindow; gtk_widget_translate_coordinates(widget, toplevelWidget, point.x(), point.y(), &xInWindow, &yInWindow); + int windowOriginX, windowOriginY; - gdk_window_get_origin(gtk_widget_get_window(toplevelWidget), &windowOriginX, &windowOriginY); + gdk_window_get_origin(gdkWindow, &windowOriginX, &windowOriginY); return IntPoint(windowOriginX + xInWindow, windowOriginY + yInWindow); } diff --git a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp index 74e4f18ca..0a3b486dc 100644 --- a/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp +++ b/Source/WebCore/platform/gtk/PlatformScreenGtk.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "PlatformScreen.h" -#include "FrameView.h" #include "GtkVersioning.h" #include "HostWindow.h" #include "NotImplemented.h" @@ -101,9 +100,9 @@ static GdkScreen* getScreen(GtkWidget* widget) return gtk_widget_has_screen(widget) ? gtk_widget_get_screen(widget) : gdk_screen_get_default(); } -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { - GtkWidget* container = frameView ? GTK_WIDGET(frameView->root()->hostWindow()->platformPageClient()) : 0; + GtkWidget* container = widget ? GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()) : 0; if (container) container = getToplevel(container); @@ -119,11 +118,11 @@ FloatRect screenRect(FrameView* frameView) return FloatRect(geometry.x, geometry.y, geometry.width, geometry.height); } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { - GtkWidget* container = frameView ? GTK_WIDGET(frameView->root()->hostWindow()->platformPageClient()) : 0; + GtkWidget* container = widget ? GTK_WIDGET(widget->root()->hostWindow()->platformPageClient()) : 0; if (container && !gtk_widget_get_realized(container)) - return screenRect(frameView); + return screenRect(widget); GdkScreen* screen = container ? getScreen(container) : gdk_screen_get_default(); if (!screen) diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp index ca34e14c3..f1620a794 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk.cpp +++ b/Source/WebCore/platform/gtk/RenderThemeGtk.cpp @@ -161,7 +161,7 @@ bool RenderThemeGtk::controlSupportsTints(const RenderObject* o) const return isEnabled(o); } -int RenderThemeGtk::baselinePosition(const RenderObject* o) const +LayoutUnit RenderThemeGtk::baselinePosition(const RenderObject* o) const { if (!o->isBox()) return 0; diff --git a/Source/WebCore/platform/gtk/RenderThemeGtk.h b/Source/WebCore/platform/gtk/RenderThemeGtk.h index ea61674f4..ad7990ed2 100644 --- a/Source/WebCore/platform/gtk/RenderThemeGtk.h +++ b/Source/WebCore/platform/gtk/RenderThemeGtk.h @@ -60,7 +60,7 @@ public: // A method to obtain the baseline position for a "leaf" control. This will only be used if a baseline // position cannot be determined by examining child content. Checkboxes and radio buttons are examples of // controls that need to do this. - virtual int baselinePosition(const RenderObject*) const; + virtual LayoutUnit baselinePosition(const RenderObject*) const; // The platform selection color. virtual Color platformActiveSelectionBackgroundColor() const; diff --git a/Source/WebCore/platform/mac/ClipboardMac.mm b/Source/WebCore/platform/mac/ClipboardMac.mm index 2806fc625..d37c5f3f3 100644 --- a/Source/WebCore/platform/mac/ClipboardMac.mm +++ b/Source/WebCore/platform/mac/ClipboardMac.mm @@ -368,7 +368,7 @@ void ClipboardMac::writeRange(Range* range, Frame* frame) ASSERT(range); ASSERT(frame); Pasteboard pasteboard([m_pasteboard.get() name]); - pasteboard.writeSelectionForTypes(nil, range, frame->editor()->smartInsertDeleteEnabled() && frame->selection()->granularity() == WordGranularity, frame); + pasteboard.writeSelection(range, frame->editor()->smartInsertDeleteEnabled() && frame->selection()->granularity() == WordGranularity, frame); } void ClipboardMac::writePlainText(const String& text) @@ -382,7 +382,7 @@ void ClipboardMac::writeURL(const KURL& url, const String& title, Frame* frame) ASSERT(frame); ASSERT(m_pasteboard); Pasteboard pasteboard([m_pasteboard.get() name]); - pasteboard.writeURLForTypes(nil, url, title, frame); + pasteboard.writeURL(url, title, frame); } #if ENABLE(DRAG_SUPPORT) diff --git a/Source/WebCore/platform/mac/DragDataMac.mm b/Source/WebCore/platform/mac/DragDataMac.mm index d6f4155c5..bec007bd4 100644 --- a/Source/WebCore/platform/mac/DragDataMac.mm +++ b/Source/WebCore/platform/mac/DragDataMac.mm @@ -31,6 +31,9 @@ #import "DocumentFragment.h" #import "DOMDocumentFragment.h" #import "DOMDocumentFragmentInternal.h" +#import "Editor.h" +#import "EditorClient.h" +#import "Frame.h" #import "MIMETypeRegistry.h" #import "Pasteboard.h" #import "Range.h" @@ -147,7 +150,7 @@ bool DragData::containsURL(Frame* frame, FilenameConversionPolicy filenamePolicy { return !asURL(frame, filenamePolicy).isEmpty(); } - + String DragData::asURL(Frame* frame, FilenameConversionPolicy filenamePolicy, String* title) const { // FIXME: Use filenamePolicy. @@ -157,8 +160,40 @@ String DragData::asURL(Frame* frame, FilenameConversionPolicy filenamePolicy, St if (NSString *URLTitleString = [m_pasteboard.get() stringForType:WebURLNamePboardType]) *title = URLTitleString; } - Pasteboard pasteboard([m_pasteboard.get() name]); - return pasteboard.asURL(frame); + + NSArray *types = [m_pasteboard.get() types]; + + // FIXME: using the editorClient to call into WebKit, for now, since + // calling webkit_canonicalize from WebCore involves migrating a sizable amount of + // helper code that should either be done in a separate patch or figured out in another way. + + if ([types containsObject:NSURLPboardType]) { + NSURL *URLFromPasteboard = [NSURL URLFromPasteboard:m_pasteboard.get()]; + NSString *scheme = [URLFromPasteboard scheme]; + if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) { + return [frame->editor()->client()->canonicalizeURL(URLFromPasteboard) absoluteString]; + } + } + + if ([types containsObject:NSStringPboardType]) { + NSString *URLString = [m_pasteboard.get() stringForType:NSStringPboardType]; + NSURL *URL = frame->editor()->client()->canonicalizeURLString(URLString); + if (URL) + return [URL absoluteString]; + } + + if ([types containsObject:NSFilenamesPboardType]) { + NSArray *files = [m_pasteboard.get() propertyListForType:NSFilenamesPboardType]; + if ([files count] == 1) { + NSString *file = [files objectAtIndex:0]; + BOOL isDirectory; + if ([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && isDirectory) + return String(); + return [frame->editor()->client()->canonicalizeURL([NSURL fileURLWithPath:file]) absoluteString]; + } + } + + return String(); } PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range> range, bool allowPlainText, bool& chosePlainText) const diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm index cb501e512..877e0a6f7 100644 --- a/Source/WebCore/platform/mac/PasteboardMac.mm +++ b/Source/WebCore/platform/mac/PasteboardMac.mm @@ -210,15 +210,9 @@ void Pasteboard::writeSelection(Range* selectedRange, bool canSmartCopyOrDelete, writeSelectionForTypes(nil, selectedRange, canSmartCopyOrDelete, frame); } -void Pasteboard::writeURLForTypes(NSArray* types, const KURL& url, const String& titleStr, Frame* frame) +static void writeURLForTypes(NSArray* types, NSPasteboard* pasteboard, const KURL& url, const String& titleStr, Frame* frame) { - if (!WebArchivePboardType) - Pasteboard::generalPasteboard(); // Initializes pasteboard types. - - if (!types) { - types = writableTypesForURL(); - [m_pasteboard.get() declareTypes:types owner:nil]; - } + [pasteboard declareTypes:types owner:nil]; ASSERT(!url.isEmpty()); @@ -233,23 +227,23 @@ void Pasteboard::writeURLForTypes(NSArray* types, const KURL& url, const String& } if ([types containsObject:WebURLsWithTitlesPboardType]) - [m_pasteboard.get() setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString], + [pasteboard setPropertyList:[NSArray arrayWithObjects:[NSArray arrayWithObject:userVisibleString], [NSArray arrayWithObject:(NSString*)titleStr.stripWhiteSpace()], nil] forType:WebURLsWithTitlesPboardType]; if ([types containsObject:NSURLPboardType]) - [cocoaURL writeToPasteboard:m_pasteboard.get()]; + [cocoaURL writeToPasteboard:pasteboard]; if ([types containsObject:WebURLPboardType]) - [m_pasteboard.get() setString:userVisibleString forType:WebURLPboardType]; + [pasteboard setString:userVisibleString forType:WebURLPboardType]; if ([types containsObject:WebURLNamePboardType]) - [m_pasteboard.get() setString:title forType:WebURLNamePboardType]; + [pasteboard setString:title forType:WebURLNamePboardType]; if ([types containsObject:NSStringPboardType]) - [m_pasteboard.get() setString:userVisibleString forType:NSStringPboardType]; + [pasteboard setString:userVisibleString forType:NSStringPboardType]; } void Pasteboard::writeURL(const KURL& url, const String& titleStr, Frame* frame) { - writeURLForTypes(nil, url, titleStr, frame); + writeURLForTypes(writableTypesForURL(), m_pasteboard.get(), url, titleStr, frame); } static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url) @@ -265,7 +259,7 @@ static NSFileWrapper* fileWrapperForImage(CachedResource* resource, NSURL *url) return wrapper; } -void Pasteboard::writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper) +static void writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper, NSPasteboard* pasteboard) { NSTextAttachment *attachment = [[NSTextAttachment alloc] initWithFileWrapper:wrapper]; @@ -273,7 +267,7 @@ void Pasteboard::writeFileWrapperAsRTFDAttachment(NSFileWrapper* wrapper) [attachment release]; NSData *RTFDData = [string RTFDFromRange:NSMakeRange(0, [string length]) documentAttributes:nil]; - [m_pasteboard.get() setData:RTFDData forType:NSRTFDPboardType]; + [pasteboard setData:RTFDData forType:NSRTFDPboardType]; } void Pasteboard::writeImage(Node* node, const KURL& url, const String& title) @@ -293,9 +287,7 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title) if (!cachedImage || cachedImage->errorOccurred()) return; - NSArray* types = writableTypesForImage(); - [m_pasteboard.get() declareTypes:types owner:nil]; - writeURLForTypes(types, cocoaURL, nsStringNilIfEmpty(title), frame); + writeURLForTypes(writableTypesForImage(), m_pasteboard.get(), cocoaURL, nsStringNilIfEmpty(title), frame); Image* image = cachedImage->imageForRenderer(renderer); ASSERT(image); @@ -305,7 +297,7 @@ void Pasteboard::writeImage(Node* node, const KURL& url, const String& title) String MIMEType = cachedImage->response().mimeType(); ASSERT(MIMETypeRegistry::isSupportedImageResourceMIMEType(MIMEType)); - writeFileWrapperAsRTFDAttachment(fileWrapperForImage(cachedImage, cocoaURL)); + writeFileWrapperAsRTFDAttachment(fileWrapperForImage(cachedImage, cocoaURL), m_pasteboard.get()); } void Pasteboard::writeClipboard(Clipboard* clipboard) @@ -365,7 +357,7 @@ String Pasteboard::plainText(Frame* frame) return String(); } -PassRefPtr<DocumentFragment> Pasteboard::documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource) +static PassRefPtr<DocumentFragment> documentFragmentWithImageResource(Frame* frame, PassRefPtr<ArchiveResource> resource) { if (DocumentLoader* loader = frame->loader()->documentLoader()) loader->addArchiveResource(resource.get()); @@ -385,16 +377,16 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragmentWithImageResource(Frame return 0; } -PassRefPtr<DocumentFragment> Pasteboard::documentFragmentWithRtf(Frame* frame, NSString* pboardType) +static PassRefPtr<DocumentFragment> documentFragmentWithRTF(Frame* frame, NSString *pasteboardType, NSPasteboard *pasteboard) { if (!frame || !frame->document() || !frame->document()->isHTMLDocument()) return 0; NSAttributedString *string = nil; - if (pboardType == NSRTFDPboardType) - string = [[NSAttributedString alloc] initWithRTFD:[m_pasteboard.get() dataForType:NSRTFDPboardType] documentAttributes:NULL]; + if (pasteboardType == NSRTFDPboardType) + string = [[NSAttributedString alloc] initWithRTFD:[pasteboard dataForType:NSRTFDPboardType] documentAttributes:NULL]; if (string == nil) - string = [[NSAttributedString alloc] initWithRTF:[m_pasteboard.get() dataForType:NSRTFPboardType] documentAttributes:NULL]; + string = [[NSAttributedString alloc] initWithRTF:[pasteboard dataForType:NSRTFPboardType] documentAttributes:NULL]; if (string == nil) return nil; @@ -432,49 +424,6 @@ static NSURL* uniqueURLWithRelativePart(NSString *relativePart) return URL; } -NSURL *Pasteboard::getBestURL(Frame* frame) -{ - NSArray *types = [m_pasteboard.get() types]; - - // FIXME: using the editorClient to call into webkit, for now, since - // calling webkit_canonicalize from WebCore involves migrating a sizable amount of - // helper code that should either be done in a separate patch or figured out in another way. - - if ([types containsObject:NSURLPboardType]) { - NSURL *URLFromPasteboard = [NSURL URLFromPasteboard:m_pasteboard.get()]; - NSString *scheme = [URLFromPasteboard scheme]; - if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) { - return frame->editor()->client()->canonicalizeURL(URLFromPasteboard); - } - } - - if ([types containsObject:NSStringPboardType]) { - NSString *URLString = [m_pasteboard.get() stringForType:NSStringPboardType]; - NSURL *URL = frame->editor()->client()->canonicalizeURLString(URLString); - if (URL) - return URL; - } - - if ([types containsObject:NSFilenamesPboardType]) { - NSArray *files = [m_pasteboard.get() propertyListForType:NSFilenamesPboardType]; - // FIXME: Maybe it makes more sense to allow multiple files and only use the first one? - if ([files count] == 1) { - NSString *file = [files objectAtIndex:0]; - BOOL isDirectory; - if ([[NSFileManager defaultManager] fileExistsAtPath:file isDirectory:&isDirectory] && isDirectory) - return nil; - return frame->editor()->client()->canonicalizeURL([NSURL fileURLWithPath:file]); - } - } - - return nil; -} - -String Pasteboard::asURL(Frame* frame) -{ - return [getBestURL(frame) absoluteString]; -} - PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefPtr<Range> context, bool allowPlainText, bool& chosePlainText) { NSArray *types = [m_pasteboard.get() types]; @@ -540,11 +489,11 @@ PassRefPtr<DocumentFragment> Pasteboard::documentFragment(Frame* frame, PassRefP } if ([types containsObject:NSRTFDPboardType] && - (fragment = documentFragmentWithRtf(frame, NSRTFDPboardType))) + (fragment = documentFragmentWithRTF(frame, NSRTFDPboardType, m_pasteboard.get()))) return fragment.release(); if ([types containsObject:NSRTFPboardType] && - (fragment = documentFragmentWithRtf(frame, NSRTFPboardType))) + (fragment = documentFragmentWithRTF(frame, NSRTFPboardType, m_pasteboard.get()))) return fragment.release(); if ([types containsObject:NSTIFFPboardType] && diff --git a/Source/WebCore/platform/mac/PlatformClockCM.h b/Source/WebCore/platform/mac/PlatformClockCM.h new file mode 100644 index 000000000..e03491530 --- /dev/null +++ b/Source/WebCore/platform/mac/PlatformClockCM.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PlatformClockCM_h +#define PlatformClockCM_h + +#if USE(COREMEDIA) + +#include "Clock.h" +#include <wtf/RetainPtr.h> + +typedef struct OpaqueCMTimebase* CMTimebaseRef; +typedef struct OpaqueCMClock* CMClockRef; + +namespace WebCore { + +class PlatformClockCM : public Clock { +public: + PlatformClockCM(); + PlatformClockCM(CMClockRef); + +private: + void initializeWithTimingSource(CMClockRef); + + virtual void setCurrentTime(float); + virtual float currentTime() const; + + virtual void setPlayRate(float); + virtual float playRate() const { return m_rate; } + + virtual void start(); + virtual void stop(); + virtual bool isRunning() const { return m_running; } + + RetainPtr<CMTimebaseRef> m_timebase; + float m_rate; + bool m_running; +}; + +} + +#endif + +#endif diff --git a/Source/WebCore/platform/mac/PlatformClockCM.mm b/Source/WebCore/platform/mac/PlatformClockCM.mm new file mode 100644 index 000000000..adc4d68f8 --- /dev/null +++ b/Source/WebCore/platform/mac/PlatformClockCM.mm @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" + +#if USE(COREMEDIA) + +#import "PlatformClockCM.h" + +#import "FloatConversion.h" +#import "SoftLinking.h" +#import <CoreMedia/CMAudioDeviceClock.h> + +SOFT_LINK_FRAMEWORK_OPTIONAL(CoreMedia) + +SOFT_LINK(CoreMedia, CMAudioDeviceClockCreate, OSStatus, (CFAllocatorRef allocator, CFStringRef deviceUID, CMClockRef *clockOut), (allocator, deviceUID, clockOut)) +SOFT_LINK(CoreMedia, CMTimebaseCreateWithMasterClock, OSStatus, (CFAllocatorRef allocator, CMClockRef masterClock, CMTimebaseRef *timebaseOut), (allocator, masterClock, timebaseOut)) +SOFT_LINK(CoreMedia, CMTimebaseSetTime, OSStatus, (CMTimebaseRef timebase, CMTime time), (timebase, time)) +SOFT_LINK(CoreMedia, CMTimebaseGetTime, CMTime, (CMTimebaseRef timebase), (timebase)) +SOFT_LINK(CoreMedia, CMTimebaseSetRate, OSStatus, (CMTimebaseRef timebase, Float64 rate), (timebase, rate)) +SOFT_LINK(CoreMedia, CMTimeMakeWithSeconds, CMTime, (Float64 seconds, int32_t preferredTimeScale), (seconds, preferredTimeScale)) +SOFT_LINK(CoreMedia, CMTimeGetSeconds, Float64, (CMTime time), (time)) + +using namespace WebCore; + +// A default time scale of 1000 allows milli-second CMTime precision without scaling the timebase. +static const int32_t DefaultTimeScale = 1000; + +PlatformClockCM::PlatformClockCM() + : m_timebase(0) + , m_running(false) +{ + CMClockRef rawClockPtr = 0; + CMAudioDeviceClockCreate(kCFAllocatorDefault, NULL, &rawClockPtr); + RetainPtr<CMClockRef> clock(AdoptCF, rawClockPtr); + initializeWithTimingSource(clock.get()); +} + +PlatformClockCM::PlatformClockCM(CMClockRef clock) + : m_timebase(0) + , m_running(false) +{ + initializeWithTimingSource(clock); +} + +void PlatformClockCM::initializeWithTimingSource(CMClockRef clock) +{ + CMTimebaseRef rawTimebasePtr = 0; + CMTimebaseCreateWithMasterClock(kCFAllocatorDefault, clock, &rawTimebasePtr); + m_timebase.adoptCF(rawTimebasePtr); +} + +void PlatformClockCM::setCurrentTime(float time) +{ + CMTime cmTime = CMTimeMakeWithSeconds(time, DefaultTimeScale); + CMTimebaseSetTime(m_timebase.get(), cmTime); +} + +float PlatformClockCM::currentTime() const +{ + CMTime cmTime = CMTimebaseGetTime(m_timebase.get()); + return narrowPrecisionToFloat(CMTimeGetSeconds(cmTime)); +} + +void PlatformClockCM::setPlayRate(float rate) +{ + if (m_rate == rate) + return; + + m_rate = rate; + if (m_running) + CMTimebaseSetRate(m_timebase.get(), rate); +} + +void PlatformClockCM::start() +{ + if (m_running) + return; + m_running = true; + CMTimebaseSetRate(m_timebase.get(), m_rate); +} + +void PlatformClockCM::stop() +{ + if (!m_running) + return; + m_running = false; + CMTimebaseSetRate(m_timebase.get(), 0); +} + +#endif diff --git a/Source/WebCore/platform/mac/PlatformScreenMac.mm b/Source/WebCore/platform/mac/PlatformScreenMac.mm index f14f1e2e3..71e3cb137 100644 --- a/Source/WebCore/platform/mac/PlatformScreenMac.mm +++ b/Source/WebCore/platform/mac/PlatformScreenMac.mm @@ -28,8 +28,8 @@ #import "FloatRect.h" #import "Frame.h" -#import "FrameView.h" #import "Page.h" +#import "Widget.h" #import "NotImplemented.h" namespace WebCore { @@ -64,16 +64,16 @@ bool screenIsMonochrome(Widget*) // These functions scale between screen and page coordinates because JavaScript/DOM operations // assume that the screen and the page share the same coordinate system. -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { - NSWindow *window = frameView ? [frameView->platformWidget() window] : nil; - return toUserSpace([screenForWindow(window) frame], window, WebCore::deviceScaleFactor(frameView->frame())); + NSWindow *window = widget ? [widget->platformWidget() window] : nil; + return toUserSpace([screenForWindow(window) frame], window); } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { - NSWindow *window = frameView ? [frameView->platformWidget() window] : nil; - return toUserSpace([screenForWindow(window) visibleFrame], window, WebCore::deviceScaleFactor(frameView->frame())); + NSWindow *window = widget ? [widget->platformWidget() window] : nil; + return toUserSpace([screenForWindow(window) visibleFrame], window); } NSScreen *screenForWindow(NSWindow *window) @@ -89,18 +89,16 @@ NSScreen *screenForWindow(NSWindow *window) return nil; } -FloatRect toUserSpace(const NSRect& rect, NSWindow *destination, float deviceScaleFactor) +FloatRect toUserSpace(const NSRect& rect, NSWindow *destination) { FloatRect userRect = rect; userRect.setY(NSMaxY([screenForWindow(destination) frame]) - (userRect.y() + userRect.height())); // flip - userRect.scale(1 / deviceScaleFactor); // scale down return userRect; } -NSRect toDeviceSpace(const FloatRect& rect, NSWindow *source, float deviceScaleFactor) +NSRect toDeviceSpace(const FloatRect& rect, NSWindow *source) { FloatRect deviceRect = rect; - deviceRect.scale(deviceScaleFactor); // scale up deviceRect.setY(NSMaxY([screenForWindow(source) frame]) - (deviceRect.y() + deviceRect.height())); // flip return deviceRect; } diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm index 7bed38f1b..63c247770 100644 --- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm +++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm @@ -253,6 +253,14 @@ static NSSize abs(NSSize size) { UNUSED_PARAM(scrollerImpPair); UNUSED_PARAM(rect); + + if (!_scrollableArea) + return; + + if (!_scrollableArea->isOnActivePage()) + return; + + _scrollableArea->scrollAnimator()->contentAreaWillPaint(); } - (void)scrollerImpPair:(id)scrollerImpPair updateScrollerStyleForNewRecommendedScrollerStyle:(NSScrollerStyle)newRecommendedScrollerStyle diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.h b/Source/WebCore/platform/mac/ScrollbarThemeMac.h index a74a75977..13d44c23d 100644 --- a/Source/WebCore/platform/mac/ScrollbarThemeMac.h +++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.h @@ -80,6 +80,11 @@ protected: virtual bool shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent&); virtual bool shouldDragDocumentInsteadOfThumb(Scrollbar*, const PlatformMouseEvent&); int scrollbarPartToHIPressedState(ScrollbarPart); + +#if !PLATFORM(CHROMIUM) && USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING) + virtual void setUpOverhangAreasLayerContents(GraphicsLayer*) OVERRIDE; + virtual void setUpContentShadowLayer(GraphicsLayer*) OVERRIDE; +#endif }; } diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm index 85809244d..cc7482457 100644 --- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm +++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm @@ -44,6 +44,10 @@ using namespace std; using namespace WebCore; +@interface NSColor (WebNSColorDetails) ++ (NSImage *)_linenPatternImage; +@end + namespace WebCore { typedef HashMap<Scrollbar*, RetainPtr<ScrollbarPainter> > ScrollbarPainterMap; @@ -598,5 +602,49 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co } #endif +#if !PLATFORM(CHROMIUM) && USE(ACCELERATED_COMPOSITING) && ENABLE(RUBBER_BANDING) +static RetainPtr<CGColorRef> linenBackgroundColor() +{ + NSImage *image = [NSColor _linenPatternImage]; + CGImageRef cgImage = [image CGImageForProposedRect:NULL context:NULL hints:nil]; + + RetainPtr<CGPatternRef> pattern = adoptCF(wkCGPatternCreateWithImageAndTransform(cgImage, CGAffineTransformIdentity, wkPatternTilingNoDistortion)); + RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreatePattern(0)); + + const CGFloat alpha = 1.0; + return adoptCF(CGColorCreateWithPattern(colorSpace.get(), pattern.get(), &alpha)); +} + +void ScrollbarThemeMac::setUpOverhangAreasLayerContents(GraphicsLayer* graphicsLayer) +{ + static CGColorRef cachedLinenBackgroundColor = linenBackgroundColor().leakRef(); + + // We operate on the CALayer directly here, since GraphicsLayer doesn't have the concept + // of pattern images, and we know that WebCore won't touch this layer. + graphicsLayer->platformLayer().backgroundColor = cachedLinenBackgroundColor; } +void ScrollbarThemeMac::setUpContentShadowLayer(GraphicsLayer* graphicsLayer) +{ + // We operate on the CALayer directly here, since GraphicsLayer doesn't have the concept + // of shadows, and we know that WebCore won't touch this layer. + CALayer *contentShadowLayer = graphicsLayer->platformLayer(); + + static const CGFloat shadowOpacity = 0.66; + static const CGFloat shadowRadius = 3; + + // We only need to set these shadow properties once. + if (!contentShadowLayer.shadowOpacity) { + contentShadowLayer.shadowColor = CGColorGetConstantColor(kCGColorBlack); + contentShadowLayer.shadowOffset = CGSizeZero; + contentShadowLayer.shadowOpacity = shadowOpacity; + contentShadowLayer.shadowRadius = shadowRadius; + } + + RetainPtr<CGPathRef> shadowPath = adoptCF(CGPathCreateWithRect(CGRectMake(0, 0, graphicsLayer->size().width(), graphicsLayer->size().height()), NULL)); + contentShadowLayer.shadowPath = shadowPath.get(); +} + +#endif + +} // namespace WebCore diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.h b/Source/WebCore/platform/mac/WebCoreSystemInterface.h index 21eb94a18..e632e2a9a 100644 --- a/Source/WebCore/platform/mac/WebCoreSystemInterface.h +++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.h @@ -112,6 +112,7 @@ typedef enum { wkPatternTilingConstantSpacingMinimalDistortion, wkPatternTilingConstantSpacing } wkPatternTiling; +extern void (*wkCGContextResetClip)(CGContextRef); extern CGPatternRef (*wkCGPatternCreateWithImageAndTransform)(CGImageRef, CGAffineTransform, int); extern CFReadStreamRef (*wkCreateCustomCFReadStream)(void *(*formCreate)(CFReadStreamRef, void *), void (*formFinalize)(CFReadStreamRef, void *), diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm index f01747d5f..a046a892b 100644 --- a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm +++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm @@ -29,6 +29,7 @@ void (*wkAdvanceDefaultButtonPulseAnimation)(NSButtonCell *); BOOL (*wkCGContextGetShouldSmoothFonts)(CGContextRef); +void (*wkCGContextResetClip)(CGContextRef); CGPatternRef (*wkCGPatternCreateWithImageAndTransform)(CGImageRef, CGAffineTransform, int); CFStringRef (*wkCopyCFLocalizationPreferredName)(CFStringRef); NSString* (*wkCopyNSURLResponseStatusLine)(NSURLResponse*); diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp index 9203ce3ac..abccf5b9b 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp +++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.cpp @@ -55,8 +55,9 @@ void MediaStreamCenter::endLocalMediaStream(MediaStreamDescriptor* streamDescrip streamDescriptor->setEnded(); } -// FIXME: remove when real implementations are available -// Empty implementations for ports that build with MEDIA_STREAM enabled by default. +#if !PLATFORM(CHROMIUM) + +// Empty implementations for ports that build with MEDIA_STREAM enabled by default, but haven't yet implemented MediaStreamCenter. MediaStreamCenter::MediaStreamCenter() { @@ -69,7 +70,7 @@ MediaStreamCenter::~MediaStreamCenter() void MediaStreamCenter::queryMediaStreamSources(PassRefPtr<MediaStreamSourcesQueryClient> client) { MediaStreamSourceVector audioSources, videoSources; - client->mediaStreamSourcesQueryCompleted(audioSources, videoSources); + client->didCompleteQuery(audioSources, videoSources); } void MediaStreamCenter::didSetMediaStreamTrackEnabled(MediaStreamDescriptor*, MediaStreamComponent*) @@ -84,6 +85,8 @@ void MediaStreamCenter::didConstructMediaStream(MediaStreamDescriptor*) { } +#endif // !PLATFORM(CHROMIUM) + } // namespace WebCore #endif // ENABLE(MEDIA_STREAM) diff --git a/Source/WebCore/platform/mediastream/MediaStreamCenter.h b/Source/WebCore/platform/mediastream/MediaStreamCenter.h index 7d98fc52d..a37d66a26 100644 --- a/Source/WebCore/platform/mediastream/MediaStreamCenter.h +++ b/Source/WebCore/platform/mediastream/MediaStreamCenter.h @@ -38,6 +38,10 @@ namespace WebCore { +#if PLATFORM(CHROMIUM) +class MediaStreamCenterInternal; +#endif + class MediaStreamComponent; class MediaStreamDescriptor; @@ -47,8 +51,10 @@ public: virtual bool audio() const = 0; virtual bool video() const = 0; + virtual bool cameraPreferenceUser() const = 0; + virtual bool cameraPreferenceEnvironment() const = 0; - virtual void mediaStreamSourcesQueryCompleted(const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources) = 0; + virtual void didCompleteQuery(const MediaStreamSourceVector& audioSources, const MediaStreamSourceVector& videoSources) = 0; }; class MediaStreamCenter { @@ -73,6 +79,10 @@ public: private: MediaStreamCenter(); + +#if PLATFORM(CHROMIUM) + OwnPtr<MediaStreamCenterInternal> m_private; +#endif }; } // namespace WebCore diff --git a/Source/WebCore/platform/mediastream/PeerConnectionHandlerClient.h b/Source/WebCore/platform/mediastream/PeerConnectionHandlerClient.h index 7d77b5f0b..e67ef3a55 100644 --- a/Source/WebCore/platform/mediastream/PeerConnectionHandlerClient.h +++ b/Source/WebCore/platform/mediastream/PeerConnectionHandlerClient.h @@ -42,6 +42,14 @@ class MediaStreamDescriptor; class PeerConnectionHandlerClient { public: + // Name and values of the enum must match the corressponding constants in the PeerConnection.idl file. + enum ReadyState { + NEW = 0, + NEGOTIATING = 1, + ACTIVE = 2, + CLOSED = 3 + }; + virtual ~PeerConnectionHandlerClient() { } virtual void didCompleteICEProcessing() = 0; @@ -49,6 +57,7 @@ public: virtual void didReceiveDataStreamMessage(const char* data, size_t length) = 0; virtual void didAddRemoteStream(PassRefPtr<MediaStreamDescriptor>) = 0; virtual void didRemoveRemoteStream(MediaStreamDescriptor*) = 0; + virtual void didChangeState(ReadyState) = 0; }; } // namespace WebCore diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp index fc7c416ee..6be4cff08 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkJob.cpp +++ b/Source/WebCore/platform/network/blackberry/NetworkJob.cpp @@ -97,7 +97,9 @@ NetworkJob::NetworkJob() , m_isAbout(false) , m_isFTP(false) , m_isFTPDir(true) +#ifndef NDEBUG , m_isRunning(true) // Always started immediately after creation. +#endif , m_cancelled(false) , m_statusReceived(false) , m_dataReceived(false) @@ -157,30 +159,9 @@ bool NetworkJob::initialize(int playerId, return true; } -bool NetworkJob::loadAboutURL() +void NetworkJob::loadAboutURL() { - // First 6 chars are "about:". - String aboutWhat(m_response.url().string().substring(6)); - - if (!aboutWhat.isEmpty() - && !equalIgnoringCase(aboutWhat, "blank") - && !equalIgnoringCase(aboutWhat, "credits") -#if !defined(PUBLIC_BUILD) || !PUBLIC_BUILD - && !aboutWhat.startsWith("cache?query=", false) - && !equalIgnoringCase(aboutWhat, "cache") - && !equalIgnoringCase(aboutWhat, "cache/enable") - && !equalIgnoringCase(aboutWhat, "cache/disable") - && !equalIgnoringCase(aboutWhat, "version") - && (!BlackBerry::Platform::debugSetting() - || (!equalIgnoringCase(aboutWhat, "config") - && !equalIgnoringCase(aboutWhat, "build") - && !equalIgnoringCase(aboutWhat, "memory"))) -#endif - ) - return false; - m_loadAboutTimer.startOneShot(0); - return true; } int NetworkJob::cancelJob() @@ -400,7 +381,7 @@ void NetworkJob::handleNotifyDataReceived(const char* buf, size_t len) if (shouldSendClientData()) { sendResponseIfNeeded(); sendMultipartResponseIfNeeded(); - if (clientIsOk()) { + if (isClientAvailable()) { RecursionGuard guard(m_callingClient); m_handle->client()->didReceiveData(m_handle.get(), buf, len, len); } @@ -425,7 +406,7 @@ void NetworkJob::handleNotifyDataSent(unsigned long long bytesSent, unsigned lon // Protect against reentrancy. updateDeferLoadingCount(1); - if (clientIsOk()) { + if (isClientAvailable()) { RecursionGuard guard(m_callingClient); m_handle->client()->didSendData(m_handle.get(), bytesSent, totalBytesToBeSent); } @@ -443,8 +424,9 @@ void NetworkJob::notifyClose(int status) void NetworkJob::handleNotifyClose(int status) { +#ifndef NDEBUG m_isRunning = false; - +#endif if (!m_cancelled) { if (!m_statusReceived) { // Connection failed before sending notifyStatusReceived: use generic NetworkError. @@ -464,7 +446,7 @@ void NetworkJob::handleNotifyClose(int status) m_extendedStatusCode = BlackBerry::Platform::FilterStream::StatusTooManyRedirects; sendResponseIfNeeded(); - if (clientIsOk()) { + if (isClientAvailable()) { RecursionGuard guard(m_callingClient); if (isError(m_extendedStatusCode) && !m_dataReceived) { @@ -519,12 +501,13 @@ bool NetworkJob::retryAsFTPDirectory() bool NetworkJob::startNewJobWithRequest(ResourceRequest& newRequest, bool increasRedirectCount) { - if (clientIsOk()) { + if (isClientAvailable()) { RecursionGuard guard(m_callingClient); m_handle->client()->willSendRequest(m_handle.get(), newRequest, m_response); // m_cancelled can become true if the url fails the policy check. - if (m_cancelled) + // newRequest can be cleared when the redirect is rejected. + if (m_cancelled || newRequest.isEmpty()) return false; } @@ -610,12 +593,26 @@ void NetworkJob::sendResponseIfNeeded() if (!contentLength.isNull()) m_response.setExpectedContentLength(contentLength.toInt64()); - // Set suggested filename for downloads from the Content-Disposition header; if this fails, fill it in from the url - // skip this for data url's, because they have no Content-Disposition header and the format is wrong to be a filename. + // Set suggested filename for downloads from the Content-Disposition header; if this fails, + // fill it in from the url and sniffed mime type;Skip this for data and about URLs, + // because they have no Content-Disposition header and the format is wrong to be a filename. if (!m_isData && !m_isAbout) { String suggestedFilename = filenameFromHTTPContentDisposition(m_contentDisposition); - if (suggestedFilename.isNull()) - suggestedFilename = urlFilename; + if (suggestedFilename.isEmpty()) { + // Check and see if an extension already exists. + String mimeExtension = MIMETypeRegistry::getPreferredExtensionForMIMEType(mimeType); + if (urlFilename.isEmpty()) { + if (mimeExtension.isEmpty()) // No extension found for the mimeType. + suggestedFilename = String("Untitled"); + else + suggestedFilename = String("Untitled") + "." + mimeExtension; + } else { + if (urlFilename.reverseFind('.') == notFound && !mimeExtension.isEmpty()) + suggestedFilename = urlFilename + '.' + mimeExtension; + else + suggestedFilename = urlFilename; + } + } m_response.setSuggestedFilename(suggestedFilename); } @@ -623,7 +620,7 @@ void NetworkJob::sendResponseIfNeeded() if (m_isFile || m_isData || m_isAbout) m_response.setHTTPHeaderField("Cache-Control", "no-cache"); - if (clientIsOk()) { + if (isClientAvailable()) { RecursionGuard guard(m_callingClient); m_handle->client()->didReceiveResponse(m_handle.get(), m_response); } @@ -631,7 +628,7 @@ void NetworkJob::sendResponseIfNeeded() void NetworkJob::sendMultipartResponseIfNeeded() { - if (m_multipartResponse && clientIsOk()) { + if (m_multipartResponse && isClientAvailable()) { m_handle->client()->didReceiveResponse(m_handle.get(), *m_multipartResponse); m_multipartResponse = nullptr; } @@ -965,13 +962,18 @@ void NetworkJob::handleAbout() #endif } - CString resultString = result.utf8(); - - notifyStatusReceived(handled ? 404 : 200, 0); - notifyStringHeaderReceived("Content-Length", String::number(resultString.length())); - notifyStringHeaderReceived("Content-Type", "text/html"); - notifyDataReceivedPlain(resultString.data(), resultString.length()); - notifyClose(BlackBerry::Platform::FilterStream::StatusSuccess); + if (handled) { + CString resultString = result.utf8(); + notifyStatusReceived(404, 0); + notifyStringHeaderReceived("Content-Length", String::number(resultString.length())); + notifyStringHeaderReceived("Content-Type", "text/html"); + notifyDataReceivedPlain(resultString.data(), resultString.length()); + notifyClose(BlackBerry::Platform::FilterStream::StatusSuccess); + } else { + // If we can not handle it, we take it as an error of invalid URL. + notifyStatusReceived(BlackBerry::Platform::FilterStream::StatusErrorInvalidUrl, 0); + notifyClose(BlackBerry::Platform::FilterStream::StatusErrorInvalidUrl); + } } } // namespace WebCore diff --git a/Source/WebCore/platform/network/blackberry/NetworkJob.h b/Source/WebCore/platform/network/blackberry/NetworkJob.h index 4d60a6aed..447a6442e 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkJob.h +++ b/Source/WebCore/platform/network/blackberry/NetworkJob.h @@ -56,11 +56,12 @@ public: int deferLoadingCount, int redirectCount); PassRefPtr<ResourceHandle> handle() const { return m_handle; } +#ifndef NDEBUG bool isRunning() const { return m_isRunning; } +#endif bool isCancelled() const { return m_cancelled; } - bool clientIsOk() const { return !m_cancelled && m_handle && m_handle->client(); } void loadDataURL() { m_loadDataTimer.startOneShot(0); } - bool loadAboutURL(); + void loadAboutURL(); int cancelJob(); bool isDeferringLoading() const { return m_deferLoadingCount > 0; } void updateDeferLoadingCount(int delta); @@ -81,12 +82,15 @@ public: void handleNotifyDataSent(unsigned long long bytesSent, unsigned long long totalBytesToBeSent); virtual void notifyClose(int status); void handleNotifyClose(int status); + +private: + bool isClientAvailable() const { return !m_cancelled && m_handle && m_handle->client(); } + virtual void notifyDataReceived(BlackBerry::Platform::NetworkBuffer* buffer) { notifyDataReceivedPlain(BlackBerry::Platform::networkBufferData(buffer), BlackBerry::Platform::networkBufferDataLength(buffer)); } -private: virtual void setWasDiskCached(bool value) { m_response.setWasCached(value); @@ -161,7 +165,9 @@ private: bool m_isAbout; bool m_isFTP; bool m_isFTPDir; +#ifndef NDEBUG bool m_isRunning; +#endif bool m_cancelled; bool m_statusReceived; bool m_dataReceived; diff --git a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp index 077b4c219..388d6d8fd 100644 --- a/Source/WebCore/platform/network/blackberry/NetworkManager.cpp +++ b/Source/WebCore/platform/network/blackberry/NetworkManager.cpp @@ -150,9 +150,9 @@ bool NetworkManager::startJob(int playerId, const String& pageGroupName, PassRef } if (url.protocolIs("about")) { - // Try to handle the url internally; if it isn't recognized, continue and pass it to the client. - if (networkJob->loadAboutURL()) - return true; + // If the protocol matches "about", loadAboutURL should recognize and handle it. + networkJob->loadAboutURL(); + return true; } int result = networkJob->streamOpen(); diff --git a/Source/WebCore/platform/network/blackberry/ResourceRequest.h b/Source/WebCore/platform/network/blackberry/ResourceRequest.h index 8ad547395..cd9760db4 100644 --- a/Source/WebCore/platform/network/blackberry/ResourceRequest.h +++ b/Source/WebCore/platform/network/blackberry/ResourceRequest.h @@ -31,6 +31,26 @@ namespace WebCore { class ResourceRequest : public ResourceRequestBase { public: + // The type of this ResourceRequest, based on how the resource will be used. + enum TargetType { + TargetIsMainFrame, + TargetIsSubframe, + TargetIsSubresource, // Resource is a generic subresource. (Generally a specific type should be specified) + TargetIsStyleSheet, + TargetIsScript, + TargetIsFontResource, + TargetIsImage, + TargetIsObject, + TargetIsMedia, + TargetIsWorker, + TargetIsSharedWorker, + TargetIsPrefetch, + TargetIsPrerender, + TargetIsFavicon, + TargetIsXHR, + TargetIsTextTrack, + TargetIsUnspecified, + }; ResourceRequest(const String& url) : ResourceRequestBase(KURL(ParsedURLString, url), UseProtocolCachePolicy) , m_isXMLHTTPRequest(false) @@ -94,6 +114,10 @@ public: void setForceDownload(bool forceDownload) { m_forceDownload = true; } bool forceDownload() const { return m_forceDownload; } + // What this request is for. + TargetType targetType() const { return m_targetType; } + void setTargetType(TargetType type) { m_targetType = type; } + private: friend class ResourceRequestBase; @@ -104,6 +128,7 @@ private: bool m_mustHandleInternally; bool m_isRequestedByPlugin; bool m_forceDownload; + TargetType m_targetType; void doUpdatePlatformRequest() { } void doUpdateResourceRequest() { } diff --git a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp index 3ec325444..fbfb902c8 100644 --- a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp +++ b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp @@ -604,7 +604,7 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) - urlToStore = firstRequest().url(); + urlToStore = challenge.failureResponse().url(); CredentialStorage::set(core(credential.get()), challenge.protectionSpace(), urlToStore); CFURLConnectionUseCredential(d->m_connection.get(), credential.get(), challenge.cfURLAuthChallengeRef()); @@ -628,7 +628,7 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall ASSERT(credential.persistence() == CredentialPersistenceNone); if (challenge.failureResponse().httpStatusCode() == 401) { // Store the credential back, possibly adding it as a default for this directory. - CredentialStorage::set(credential, challenge.protectionSpace(), firstRequest().url()); + CredentialStorage::set(credential, challenge.protectionSpace(), challenge.failureResponse().url()); } RetainPtr<CFURLCredentialRef> cfCredential(AdoptCF, createCF(credential)); CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); @@ -675,7 +675,7 @@ void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) - urlToStore = firstRequest().url(); + urlToStore = challenge.failureResponse().url(); CredentialStorage::set(webCredential, challenge.protectionSpace(), urlToStore); CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); diff --git a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm index d22162ea2..06a81c59a 100644 --- a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm +++ b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -562,7 +562,7 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall ASSERT(credential.persistence() == CredentialPersistenceNone); if (challenge.failureResponse().httpStatusCode() == 401) { // Store the credential back, possibly adding it as a default for this directory. - CredentialStorage::set(credential, challenge.protectionSpace(), firstRequest().url()); + CredentialStorage::set(credential, challenge.protectionSpace(), challenge.failureResponse().url()); } [challenge.sender() useCredential:mac(credential) forAuthenticationChallenge:mac(challenge)]; return; @@ -620,7 +620,7 @@ void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge Credential webCredential(credential, CredentialPersistenceNone); KURL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) - urlToStore = firstRequest().url(); + urlToStore = challenge.failureResponse().url(); CredentialStorage::set(webCredential, core([d->m_currentMacChallenge protectionSpace]), urlToStore); [[d->m_currentMacChallenge sender] useCredential:mac(webCredential) forAuthenticationChallenge:d->m_currentMacChallenge]; } else diff --git a/Source/WebCore/platform/qt/PlatformScreenQt.cpp b/Source/WebCore/platform/qt/PlatformScreenQt.cpp index 846f0b8a4..3c1329ba3 100644 --- a/Source/WebCore/platform/qt/PlatformScreenQt.cpp +++ b/Source/WebCore/platform/qt/PlatformScreenQt.cpp @@ -102,15 +102,15 @@ bool screenIsMonochrome(Widget* w) return QApplication::desktop()->screen(screenNumber(w))->colorCount() == 2; } -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { - QRect r = QApplication::desktop()->screenGeometry(screenNumber(frameView)); + QRect r = QApplication::desktop()->screenGeometry(screenNumber(widget)); return FloatRect(r.x(), r.y(), r.width(), r.height()); } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { - QRect r = QApplication::desktop()->availableGeometry(screenNumber(frameView)); + QRect r = QApplication::desktop()->availableGeometry(screenNumber(widget)); return FloatRect(r.x(), r.y(), r.width(), r.height()); } diff --git a/Source/WebCore/platform/qt/RenderThemeQt.cpp b/Source/WebCore/platform/qt/RenderThemeQt.cpp index 5c6c18763..18df290db 100644 --- a/Source/WebCore/platform/qt/RenderThemeQt.cpp +++ b/Source/WebCore/platform/qt/RenderThemeQt.cpp @@ -156,7 +156,7 @@ bool RenderThemeQt::supportsFocusRing(const RenderStyle* style) const } } -int RenderThemeQt::baselinePosition(const RenderObject* o) const +LayoutUnit RenderThemeQt::baselinePosition(const RenderObject* o) const { if (!o->isBox()) return 0; diff --git a/Source/WebCore/platform/qt/RenderThemeQt.h b/Source/WebCore/platform/qt/RenderThemeQt.h index 618fad391..1393536b3 100644 --- a/Source/WebCore/platform/qt/RenderThemeQt.h +++ b/Source/WebCore/platform/qt/RenderThemeQt.h @@ -53,7 +53,7 @@ public: virtual bool supportsHover(const RenderStyle*) const; virtual bool supportsFocusRing(const RenderStyle*) const; - virtual int baselinePosition(const RenderObject*) const; + virtual LayoutUnit baselinePosition(const RenderObject*) const; // A method asking if the control changes its tint when the window has focus or not. virtual bool controlSupportsTints(const RenderObject*) const; diff --git a/Source/WebCore/platform/text/UnicodeBidi.h b/Source/WebCore/platform/text/UnicodeBidi.h index 867c58b17..08f054525 100644 --- a/Source/WebCore/platform/text/UnicodeBidi.h +++ b/Source/WebCore/platform/text/UnicodeBidi.h @@ -34,7 +34,12 @@ enum EUnicodeBidi { Override, Isolate, Plaintext -}; +}; + +inline bool isIsolated(const EUnicodeBidi& unicodeBidi) +{ + return unicodeBidi == Isolate || unicodeBidi == Plaintext; +} } diff --git a/Source/WebCore/platform/win/PlatformScreenWin.cpp b/Source/WebCore/platform/win/PlatformScreenWin.cpp index 936f8a747..caadde943 100644 --- a/Source/WebCore/platform/win/PlatformScreenWin.cpp +++ b/Source/WebCore/platform/win/PlatformScreenWin.cpp @@ -106,15 +106,15 @@ bool screenIsMonochrome(Widget* widget) #endif } -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { - MONITORINFOEX monitorInfo = monitorInfoForWidget(frameView); + MONITORINFOEX monitorInfo = monitorInfoForWidget(widget); return monitorInfo.rcMonitor; } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { - MONITORINFOEX monitorInfo = monitorInfoForWidget(frameView); + MONITORINFOEX monitorInfo = monitorInfoForWidget(widget); return monitorInfo.rcWork; } diff --git a/Source/WebCore/platform/wx/ScreenWx.cpp b/Source/WebCore/platform/wx/ScreenWx.cpp index 779d4fdf5..41edf1561 100644 --- a/Source/WebCore/platform/wx/ScreenWx.cpp +++ b/Source/WebCore/platform/wx/ScreenWx.cpp @@ -28,7 +28,6 @@ #include "Screen.h" #include "IntRect.h" #include "FloatRect.h" -#include "FrameView.h" #include "NotImplemented.h" #include "Widget.h" @@ -49,7 +48,7 @@ int screenVerticalDPI(Widget*) return 0; } -FloatRect screenRect(FrameView* frameView) +FloatRect screenRect(Widget* widget) { /* int displayNum; @@ -78,7 +77,7 @@ bool screenIsMonochrome(Widget* widget) return wxColourDisplay(); } -FloatRect screenAvailableRect(FrameView* frameView) +FloatRect screenAvailableRect(Widget* widget) { /* Widget* widget = widget->widget(); |