diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium/cc')
60 files changed, 2275 insertions, 748 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp new file mode 100644 index 000000000..556e46b4e --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 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: + * 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. 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 INC. 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. + */ + +#include "config.h" + +#include "cc/CCActiveGestureAnimation.h" + +#include "cc/CCGestureCurve.h" + +namespace WebCore { + +PassOwnPtr<CCActiveGestureAnimation> CCActiveGestureAnimation::create(double startTime, PassOwnPtr<CCGestureCurve> curve, CCGestureCurveTarget* target) +{ + return adoptPtr(new CCActiveGestureAnimation(startTime, curve, target)); +} + +CCActiveGestureAnimation::CCActiveGestureAnimation(double startTime, PassOwnPtr<CCGestureCurve> curve, CCGestureCurveTarget* target) + : m_startTime(startTime) + , m_gestureCurve(curve) + , m_gestureCurveTarget(target) +{ +} + +CCActiveGestureAnimation::~CCActiveGestureAnimation() +{ +} + +bool CCActiveGestureAnimation::animate(double time) +{ + // CCGestureCurves used zero-based time, so subtract start-time. + return m_gestureCurve->apply(time - m_startTime, m_gestureCurveTarget); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h new file mode 100644 index 000000000..c71b225df --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCActiveGestureAnimation.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2012 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: + * 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. 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 INC. 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. + */ + +#ifndef CCActiveGestureAnimation_h +#define CCActiveGestureAnimation_h + +#include <wtf/Noncopyable.h> +#include <wtf/OwnPtr.h> +#include <wtf/PassOwnPtr.h> + +namespace WebCore { + +class CCGestureCurve; +class CCGestureCurveTarget; + +class CCActiveGestureAnimation { + WTF_MAKE_NONCOPYABLE(CCActiveGestureAnimation); +public: + static PassOwnPtr<CCActiveGestureAnimation> create(double startTime, PassOwnPtr<CCGestureCurve>, CCGestureCurveTarget*); + ~CCActiveGestureAnimation(); + + bool animate(double time); + +private: + CCActiveGestureAnimation(double startTime, PassOwnPtr<CCGestureCurve>, CCGestureCurveTarget*); + + double m_startTime; + OwnPtr<CCGestureCurve> m_gestureCurve; + CCGestureCurveTarget* m_gestureCurveTarget; +}; + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp new file mode 100644 index 000000000..9f41844ca --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 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: + * 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. 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 INC. 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. + */ + +#include "config.h" + +#include "cc/CCAnimationEvents.h" + +#include <wtf/OwnPtr.h> + +namespace WebCore { + +CCAnimationEvent::CCAnimationEvent(int layerId) + : m_layerId(layerId) +{ +} + +CCAnimationEvent::~CCAnimationEvent() +{ +} + +const CCAnimationStartedEvent* CCAnimationEvent::toAnimationStartedEvent() const +{ + ASSERT(type() == Started); + return static_cast<const CCAnimationStartedEvent*>(this); +} + +const CCAnimationFinishedEvent* CCAnimationEvent::toAnimationFinishedEvent() const +{ + ASSERT(type() == Finished); + return static_cast<const CCAnimationFinishedEvent*>(this); +} + +PassOwnPtr<CCAnimationStartedEvent> CCAnimationStartedEvent::create(int layerId) +{ + return adoptPtr(new CCAnimationStartedEvent(layerId)); +} + +CCAnimationStartedEvent::CCAnimationStartedEvent(int layerId) + : CCAnimationEvent(layerId) +{ +} + +CCAnimationStartedEvent::~CCAnimationStartedEvent() +{ +} + +CCAnimationEvent::Type CCAnimationStartedEvent::type() const +{ + return Started; +} + +PassOwnPtr<CCAnimationFinishedEvent> CCAnimationFinishedEvent::create(int layerId, int animationId) +{ + return adoptPtr(new CCAnimationFinishedEvent(layerId, animationId)); +} + +CCAnimationFinishedEvent::CCAnimationFinishedEvent(int layerId, int animationId) + : CCAnimationEvent(layerId) + , m_animationId(animationId) +{ +} + +CCAnimationFinishedEvent::~CCAnimationFinishedEvent() +{ +} + +CCAnimationEvent::Type CCAnimationFinishedEvent::type() const +{ + return Finished; +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h index b21a79e31..da94e1e27 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCAnimationEvents.h @@ -25,20 +25,65 @@ #ifndef CCAnimationEvents_h #define CCAnimationEvents_h +#include <wtf/PassOwnPtr.h> #include <wtf/Vector.h> namespace WebCore { +class CCAnimationStartedEvent; +class CCAnimationFinishedEvent; + +class CCAnimationEvent { +public: + enum Type { Started, Finished }; + + virtual ~CCAnimationEvent(); + + virtual Type type() const = 0; + + int layerId() const { return m_layerId; } + + const CCAnimationStartedEvent* toAnimationStartedEvent() const; + const CCAnimationFinishedEvent* toAnimationFinishedEvent() const; + +protected: + CCAnimationEvent(int layerId); + +private: + int m_layerId; +}; + +// Indicates that an animation has started on a particular layer. +class CCAnimationStartedEvent : public CCAnimationEvent { +public: + static PassOwnPtr<CCAnimationStartedEvent> create(int layerId); + + virtual ~CCAnimationStartedEvent(); + + virtual Type type() const; + +private: + explicit CCAnimationStartedEvent(int layerId); +}; + // Indicates that an animation has started on a particular layer. -struct CCAnimationStartedEvent { - CCAnimationStartedEvent(int layerID, double time) - : layerID(layerID) - , time(time) { } - int layerID; - double time; +class CCAnimationFinishedEvent : public CCAnimationEvent { +public: + static PassOwnPtr<CCAnimationFinishedEvent> create(int layerId, int animationId); + + virtual ~CCAnimationFinishedEvent(); + + virtual Type type() const; + + int animationId() const { return m_animationId; } + +private: + CCAnimationFinishedEvent(int layerId, int animationId); + + int m_animationId; }; -typedef Vector<CCAnimationStartedEvent> CCAnimationEventsVector; +typedef Vector<OwnPtr<CCAnimationEvent> > CCAnimationEventsVector; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h index 9126a7d44..c96af246e 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCCanvasLayerImpl.h @@ -34,9 +34,9 @@ namespace WebCore { class CCCanvasLayerImpl : public CCLayerImpl { public: - static PassRefPtr<CCCanvasLayerImpl> create(int id) + static PassOwnPtr<CCCanvasLayerImpl> create(int id) { - return adoptRef(new CCCanvasLayerImpl(id)); + return adoptPtr(new CCCanvasLayerImpl(id)); } virtual ~CCCanvasLayerImpl(); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp index 2d6f43f31..6a062caca 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.cpp @@ -56,7 +56,7 @@ CCDamageTracker::~CCDamageTracker() { } -void CCDamageTracker::updateDamageTrackingState(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer) +void CCDamageTracker::updateDamageTrackingState(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer) { // // This function computes the "damage rect" of a target surface, and updates the state @@ -130,7 +130,7 @@ void CCDamageTracker::updateDamageTrackingState(const Vector<RefPtr<CCLayerImpl> // 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(); + CCLayerImpl* layer = layerList[0]; CCRenderSurface* targetSurface = layer->targetRenderSurface(); if (m_forceFullDamageNextUpdate || targetSurface->surfacePropertyChangedOnlyFromDescendant()) { @@ -161,12 +161,12 @@ void CCDamageTracker::saveRectForNextFrame(int layerID, const FloatRect& targetS m_nextRectHistory->set(layerID, targetSpaceRect); } -FloatRect CCDamageTracker::trackDamageFromActiveLayers(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID) +FloatRect CCDamageTracker::trackDamageFromActiveLayers(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID) { FloatRect damageRect = FloatRect(); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { - CCLayerImpl* layer = layerList[layerIndex].get(); + CCLayerImpl* layer = layerList[layerIndex]; if (CCLayerTreeHostCommon::renderSurfaceContributesToTarget<CCLayerImpl>(layer, targetSurfaceLayerID)) extendDamageForRenderSurface(layer, damageRect); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h index d428f26d1..7a629c478 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCDamageTracker.h @@ -44,13 +44,13 @@ public: ~CCDamageTracker(); void forceFullDamageNextUpdate() { m_forceFullDamageNextUpdate = true; } - void updateDamageTrackingState(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer); + void updateDamageTrackingState(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID, CCLayerImpl* targetSurfaceMaskLayer); const FloatRect& currentDamageRect() { return m_currentDamageRect; } private: CCDamageTracker(); - FloatRect trackDamageFromActiveLayers(const Vector<RefPtr<CCLayerImpl> >& layerList, int targetSurfaceLayerID); + FloatRect trackDamageFromActiveLayers(const Vector<CCLayerImpl*>& layerList, int targetSurfaceLayerID); FloatRect trackDamageFromSurfaceMask(CCLayerImpl* targetSurfaceMaskLayer); FloatRect trackDamageFromLeftoverRects(); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h b/Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h new file mode 100644 index 000000000..3ef935b6a --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCGestureCurve.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 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: + * 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. 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 INC. 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. + */ + +#ifndef CCGestureCurve_h +#define CCGestureCurve_h + +namespace WebCore { + +class IntPoint; + +class CCGestureCurveTarget { +public: + virtual void setScrollIncrement(const IntPoint&) = 0; + // FIXME: add interfaces for setScroll(), setPageScaleAndScroll(), etc. + +protected: + virtual ~CCGestureCurveTarget() { } +}; + +class CCGestureCurve { +public: + virtual ~CCGestureCurve() { } + + virtual bool apply(double time, CCGestureCurveTarget*) = 0; +}; + +} // namespace WebCore + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h b/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h index 6c055994c..33721f1df 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCInputHandler.h @@ -72,8 +72,8 @@ public: virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, - double startTimeMs, - double durationMs) = 0; + double startTime, + double duration) = 0; protected: CCInputHandlerClient() { } @@ -87,7 +87,7 @@ public: virtual ~CCInputHandler() { } virtual int identifier() const = 0; - virtual void willDraw(double frameDisplayTimeMs) = 0; + virtual void willDraw(double monotonicTime) = 0; protected: CCInputHandler() { } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.cpp index b615c736c..ae41fe069 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.cpp @@ -42,31 +42,173 @@ namespace WebCore { namespace { template <class Keyframe> -bool keyframesAreSorted(const Vector<Keyframe>& keyframes) +void insertKeyframe(PassOwnPtr<Keyframe> popKeyframe, Vector<OwnPtr<Keyframe> >& keyframes) { - if (!keyframes.size()) - return true; - - for (size_t i = 0; i < keyframes.size() - 1; ++i) { - if (keyframes[i].time > keyframes[i+1].time) - return false; + OwnPtr<Keyframe> keyframe = popKeyframe; + + // Usually, the keyframes will be added in order, so this loop would be unnecessary and + // we should skip it if possible. + if (!keyframes.isEmpty() && keyframe->time() < keyframes.last()->time()) { + for (size_t i = 0; i < keyframes.size(); ++i) { + if (keyframe->time() < keyframes[i]->time()) { + keyframes.insert(i, keyframe.release()); + return; + } + } } - return true; + keyframes.append(keyframe.release()); +} + +PassOwnPtr<CCTimingFunction> cloneTimingFunction(const CCTimingFunction* timingFunction) +{ + ASSERT(timingFunction); + OwnPtr<CCAnimationCurve> curve(timingFunction->clone()); + return adoptPtr(static_cast<CCTimingFunction*>(curve.leakPtr())); } } // namespace -PassOwnPtr<CCKeyframedFloatAnimationCurve> CCKeyframedFloatAnimationCurve::create(const Vector<CCFloatKeyframe>& keyframes) +CCKeyframe::CCKeyframe(double time, PassOwnPtr<CCTimingFunction> timingFunction) + : m_time(time) + , m_timingFunction(timingFunction) +{ +} + +CCKeyframe::~CCKeyframe() +{ +} + +double CCKeyframe::time() const +{ + return m_time; +} + +const CCTimingFunction* CCKeyframe::timingFunction() const +{ + return m_timingFunction.get(); +} + +PassOwnPtr<CCFloatKeyframe> CCFloatKeyframe::create(double time, float value, PassOwnPtr<CCTimingFunction> timingFunction) +{ + return adoptPtr(new CCFloatKeyframe(time, value, timingFunction)); +} + +CCFloatKeyframe::CCFloatKeyframe(double time, float value, PassOwnPtr<CCTimingFunction> timingFunction) + : CCKeyframe(time, timingFunction) + , m_value(value) +{ +} + +CCFloatKeyframe::~CCFloatKeyframe() +{ +} + +float CCFloatKeyframe::value() const { - if (!keyframes.size() || !keyframesAreSorted(keyframes)) - return nullptr; + return m_value; +} - return adoptPtr(new CCKeyframedFloatAnimationCurve(keyframes)); +PassOwnPtr<CCFloatKeyframe> CCFloatKeyframe::clone() const +{ + return CCFloatKeyframe::create(time(), value(), timingFunction() ? cloneTimingFunction(timingFunction()) : nullptr); } -CCKeyframedFloatAnimationCurve::CCKeyframedFloatAnimationCurve(const Vector<CCFloatKeyframe>& keyframes) - : m_keyframes(keyframes) +PassOwnPtr<CCTransformKeyframe> CCTransformKeyframe::create(double time, const TransformOperations& value, PassOwnPtr<CCTimingFunction> timingFunction) +{ + return adoptPtr(new CCTransformKeyframe(time, value, timingFunction)); +} + +CCTransformKeyframe::CCTransformKeyframe(double time, const TransformOperations& value, PassOwnPtr<CCTimingFunction> timingFunction) + : CCKeyframe(time, timingFunction) + , m_value(value) +{ +} + +CCTransformKeyframe::~CCTransformKeyframe() +{ +} + +const TransformOperations& CCTransformKeyframe::value() const +{ + return m_value; +} + +PassOwnPtr<CCTransformKeyframe> CCTransformKeyframe::clone() const +{ + // We need to do a deep copy the m_value may contain ref pointers to TransformOperation objects. + TransformOperations operations; + for (size_t j = 0; j < m_value.size(); ++j) { + TransformOperation::OperationType operationType = m_value.operations()[j]->getOperationType(); + switch (operationType) { + case TransformOperation::SCALE_X: + case TransformOperation::SCALE_Y: + case TransformOperation::SCALE_Z: + case TransformOperation::SCALE_3D: + case TransformOperation::SCALE: { + ScaleTransformOperation* transform = static_cast<ScaleTransformOperation*>(m_value.operations()[j].get()); + operations.operations().append(ScaleTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType)); + break; + } + case TransformOperation::TRANSLATE_X: + case TransformOperation::TRANSLATE_Y: + case TransformOperation::TRANSLATE_Z: + case TransformOperation::TRANSLATE_3D: + case TransformOperation::TRANSLATE: { + TranslateTransformOperation* transform = static_cast<TranslateTransformOperation*>(m_value.operations()[j].get()); + operations.operations().append(TranslateTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType)); + break; + } + case TransformOperation::ROTATE_X: + case TransformOperation::ROTATE_Y: + case TransformOperation::ROTATE_3D: + case TransformOperation::ROTATE: { + RotateTransformOperation* transform = static_cast<RotateTransformOperation*>(m_value.operations()[j].get()); + operations.operations().append(RotateTransformOperation::create(transform->x(), transform->y(), transform->z(), transform->angle(), operationType)); + break; + } + case TransformOperation::SKEW_X: + case TransformOperation::SKEW_Y: + case TransformOperation::SKEW: { + SkewTransformOperation* transform = static_cast<SkewTransformOperation*>(m_value.operations()[j].get()); + operations.operations().append(SkewTransformOperation::create(transform->angleX(), transform->angleY(), operationType)); + break; + } + case TransformOperation::MATRIX: { + MatrixTransformOperation* transform = static_cast<MatrixTransformOperation*>(m_value.operations()[j].get()); + TransformationMatrix m = transform->matrix(); + operations.operations().append(MatrixTransformOperation::create(m.a(), m.b(), m.c(), m.d(), m.e(), m.f())); + break; + } + case TransformOperation::MATRIX_3D: { + Matrix3DTransformOperation* transform = static_cast<Matrix3DTransformOperation*>(m_value.operations()[j].get()); + operations.operations().append(Matrix3DTransformOperation::create(transform->matrix())); + break; + } + case TransformOperation::PERSPECTIVE: { + PerspectiveTransformOperation* transform = static_cast<PerspectiveTransformOperation*>(m_value.operations()[j].get()); + operations.operations().append(PerspectiveTransformOperation::create(transform->perspective())); + break; + } + case TransformOperation::IDENTITY: { + operations.operations().append(IdentityTransformOperation::create()); + break; + } + case TransformOperation::NONE: + // Do nothing. + break; + } // switch + } // for each operation + + return CCTransformKeyframe::create(time(), operations, timingFunction() ? cloneTimingFunction(timingFunction()) : nullptr); +} + +PassOwnPtr<CCKeyframedFloatAnimationCurve> CCKeyframedFloatAnimationCurve::create() +{ + return adoptPtr(new CCKeyframedFloatAnimationCurve); +} + +CCKeyframedFloatAnimationCurve::CCKeyframedFloatAnimationCurve() { } @@ -74,159 +216,110 @@ CCKeyframedFloatAnimationCurve::~CCKeyframedFloatAnimationCurve() { } +void CCKeyframedFloatAnimationCurve::addKeyframe(PassOwnPtr<CCFloatKeyframe> keyframe) +{ + insertKeyframe(keyframe, m_keyframes); +} + double CCKeyframedFloatAnimationCurve::duration() const { - return m_keyframes.last().time - m_keyframes.first().time; + return m_keyframes.last()->time() - m_keyframes.first()->time(); } PassOwnPtr<CCAnimationCurve> CCKeyframedFloatAnimationCurve::clone() const { - return adoptPtr(new CCKeyframedFloatAnimationCurve(*this)); + OwnPtr<CCKeyframedFloatAnimationCurve> toReturn(CCKeyframedFloatAnimationCurve::create()); + for (size_t i = 0; i < m_keyframes.size(); ++i) + toReturn->addKeyframe(m_keyframes[i]->clone()); + return toReturn.release(); } float CCKeyframedFloatAnimationCurve::getValue(double t) const { - if (t <= m_keyframes.first().time) - return m_keyframes.first().value; + if (t <= m_keyframes.first()->time()) + return m_keyframes.first()->value(); - if (t >= m_keyframes.last().time) - return m_keyframes.last().value; + if (t >= m_keyframes.last()->time()) + return m_keyframes.last()->value(); size_t i = 0; for (; i < m_keyframes.size() - 1; ++i) { - if (t < m_keyframes[i+1].time) + if (t < m_keyframes[i+1]->time()) break; } - float progress = static_cast<float>((t - m_keyframes[i].time) / (m_keyframes[i+1].time - m_keyframes[i].time)); - // FIXME: apply timing function here. - return m_keyframes[i].value + (m_keyframes[i+1].value - m_keyframes[i].value) * progress; + float progress = static_cast<float>((t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time())); + + if (m_keyframes[i]->timingFunction()) + progress = m_keyframes[i]->timingFunction()->getValue(progress); + + return m_keyframes[i]->value() + (m_keyframes[i+1]->value() - m_keyframes[i]->value()) * progress; } -PassOwnPtr<CCKeyframedTransformAnimationCurve> CCKeyframedTransformAnimationCurve::create(const Vector<CCTransformKeyframe>& keyframes) +PassOwnPtr<CCKeyframedTransformAnimationCurve> CCKeyframedTransformAnimationCurve::create() { - if (!keyframes.size() || !keyframesAreSorted(keyframes)) - return nullptr; + return adoptPtr(new CCKeyframedTransformAnimationCurve); +} - return adoptPtr(new CCKeyframedTransformAnimationCurve(keyframes)); +CCKeyframedTransformAnimationCurve::CCKeyframedTransformAnimationCurve() +{ } -CCKeyframedTransformAnimationCurve::CCKeyframedTransformAnimationCurve(const Vector<CCTransformKeyframe>& keyframes) - : m_keyframes(keyframes) +CCKeyframedTransformAnimationCurve::~CCKeyframedTransformAnimationCurve() { } -CCKeyframedTransformAnimationCurve::~CCKeyframedTransformAnimationCurve() { } +void CCKeyframedTransformAnimationCurve::addKeyframe(PassOwnPtr<CCTransformKeyframe> keyframe) +{ + insertKeyframe(keyframe, m_keyframes); +} double CCKeyframedTransformAnimationCurve::duration() const { - return m_keyframes.last().time - m_keyframes.first().time; + return m_keyframes.last()->time() - m_keyframes.first()->time(); } PassOwnPtr<CCAnimationCurve> CCKeyframedTransformAnimationCurve::clone() const { - Vector<CCTransformKeyframe> keyframes; - // We need to do a deep copy of all of the keyframes since they contain ref - // pointers to TransformOperation objects. - for (size_t i = 0; i < m_keyframes.size(); ++i) { - CCTransformKeyframe keyframe(m_keyframes[i].time); - for (size_t j = 0; j < m_keyframes[i].value.size(); ++j) { - TransformOperation::OperationType operationType = m_keyframes[i].value.operations()[j]->getOperationType(); - switch (operationType) { - case TransformOperation::SCALE_X: - case TransformOperation::SCALE_Y: - case TransformOperation::SCALE_Z: - case TransformOperation::SCALE_3D: - case TransformOperation::SCALE: { - ScaleTransformOperation* transform = static_cast<ScaleTransformOperation*>(m_keyframes[i].value.operations()[j].get()); - keyframe.value.operations().append(ScaleTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType)); - break; - } - case TransformOperation::TRANSLATE_X: - case TransformOperation::TRANSLATE_Y: - case TransformOperation::TRANSLATE_Z: - case TransformOperation::TRANSLATE_3D: - case TransformOperation::TRANSLATE: { - TranslateTransformOperation* transform = static_cast<TranslateTransformOperation*>(m_keyframes[i].value.operations()[j].get()); - keyframe.value.operations().append(TranslateTransformOperation::create(transform->x(), transform->y(), transform->z(), operationType)); - break; - } - case TransformOperation::ROTATE_X: - case TransformOperation::ROTATE_Y: - case TransformOperation::ROTATE_3D: - case TransformOperation::ROTATE: { - RotateTransformOperation* transform = static_cast<RotateTransformOperation*>(m_keyframes[i].value.operations()[j].get()); - keyframe.value.operations().append(RotateTransformOperation::create(transform->x(), transform->y(), transform->z(), transform->angle(), operationType)); - break; - } - case TransformOperation::SKEW_X: - case TransformOperation::SKEW_Y: - case TransformOperation::SKEW: { - SkewTransformOperation* transform = static_cast<SkewTransformOperation*>(m_keyframes[i].value.operations()[j].get()); - keyframe.value.operations().append(SkewTransformOperation::create(transform->angleX(), transform->angleY(), operationType)); - break; - } - case TransformOperation::MATRIX: { - MatrixTransformOperation* transform = static_cast<MatrixTransformOperation*>(m_keyframes[i].value.operations()[j].get()); - TransformationMatrix m = transform->matrix(); - keyframe.value.operations().append(MatrixTransformOperation::create(m.a(), m.b(), m.c(), m.d(), m.e(), m.f())); - break; - } - case TransformOperation::MATRIX_3D: { - Matrix3DTransformOperation* transform = static_cast<Matrix3DTransformOperation*>(m_keyframes[i].value.operations()[j].get()); - keyframe.value.operations().append(Matrix3DTransformOperation::create(transform->matrix())); - break; - } - case TransformOperation::PERSPECTIVE: { - PerspectiveTransformOperation* transform = static_cast<PerspectiveTransformOperation*>(m_keyframes[i].value.operations()[j].get()); - keyframe.value.operations().append(PerspectiveTransformOperation::create(transform->perspective())); - break; - } - case TransformOperation::IDENTITY: { - keyframe.value.operations().append(IdentityTransformOperation::create()); - break; - } - case TransformOperation::NONE: - // Do nothing. - break; - } // switch - } // for each operation - keyframes.append(keyframe); - } - return CCKeyframedTransformAnimationCurve::create(keyframes); + OwnPtr<CCKeyframedTransformAnimationCurve> toReturn(CCKeyframedTransformAnimationCurve::create()); + for (size_t i = 0; i < m_keyframes.size(); ++i) + toReturn->addKeyframe(m_keyframes[i]->clone()); + return toReturn.release(); } TransformationMatrix CCKeyframedTransformAnimationCurve::getValue(double t, const IntSize& layerSize) const { TransformationMatrix transformMatrix; - if (t <= m_keyframes.first().time) { - m_keyframes.first().value.apply(layerSize, transformMatrix); + if (t <= m_keyframes.first()->time()) { + m_keyframes.first()->value().apply(layerSize, transformMatrix); return transformMatrix; } - if (t >= m_keyframes.last().time) { - m_keyframes.last().value.apply(layerSize, transformMatrix); + if (t >= m_keyframes.last()->time()) { + m_keyframes.last()->value().apply(layerSize, transformMatrix); return transformMatrix; } size_t i = 0; for (; i < m_keyframes.size() - 1; ++i) { - if (t < m_keyframes[i+1].time) + if (t < m_keyframes[i+1]->time()) break; } - // FIXME: apply timing function here. - double progress = (t - m_keyframes[i].time) / (m_keyframes[i+1].time - m_keyframes[i].time); + double progress = (t - m_keyframes[i]->time()) / (m_keyframes[i+1]->time() - m_keyframes[i]->time()); + + if (m_keyframes[i]->timingFunction()) + progress = m_keyframes[i]->timingFunction()->getValue(progress); - if (m_keyframes[i].value.operationsMatch(m_keyframes[i+1].value)) { - for (size_t j = 0; j < m_keyframes[i+1].value.size(); ++j) - m_keyframes[i+1].value.operations()[j]->blend(m_keyframes[i].value.at(j), progress)->apply(transformMatrix, layerSize); + if (m_keyframes[i]->value().operationsMatch(m_keyframes[i+1]->value())) { + for (size_t j = 0; j < m_keyframes[i+1]->value().size(); ++j) + m_keyframes[i+1]->value().operations()[j]->blend(m_keyframes[i]->value().at(j), progress)->apply(transformMatrix, layerSize); } else { TransformationMatrix source; - m_keyframes[i].value.apply(layerSize, source); - m_keyframes[i+1].value.apply(layerSize, transformMatrix); + m_keyframes[i]->value().apply(layerSize, source); + m_keyframes[i+1]->value().apply(layerSize, transformMatrix); transformMatrix.blend(source, progress); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h b/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h index 1c4d64adb..c3073bf08 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCKeyframedAnimationCurve.h @@ -27,46 +27,66 @@ #include "TransformOperations.h" #include "cc/CCAnimationCurve.h" +#include "cc/CCTimingFunction.h" #include <wtf/OwnPtr.h> #include <wtf/PassOwnPtr.h> namespace WebCore { -struct CCFloatKeyframe { - CCFloatKeyframe(double time, float value) - : time(time) - , value(value) - { - } +class CCKeyframe { +public: + double time() const; + const CCTimingFunction* timingFunction() const; + +protected: + CCKeyframe(double time, PassOwnPtr<CCTimingFunction>); + virtual ~CCKeyframe(); - double time; - float value; +private: + double m_time; + OwnPtr<CCTimingFunction> m_timingFunction; }; -struct CCTransformKeyframe { - explicit CCTransformKeyframe(double time) - : time(time) - { - } +class CCFloatKeyframe : public CCKeyframe { +public: + static PassOwnPtr<CCFloatKeyframe> create(double time, float value, PassOwnPtr<CCTimingFunction>); + virtual ~CCFloatKeyframe(); + + float value() const; - CCTransformKeyframe(double time, const TransformOperations& value) - : time(time) - , value(value) - { - } + PassOwnPtr<CCFloatKeyframe> clone() const; - double time; - TransformOperations value; +private: + CCFloatKeyframe(double time, float value, PassOwnPtr<CCTimingFunction>); + + float m_value; +}; + +class CCTransformKeyframe : public CCKeyframe { +public: + static PassOwnPtr<CCTransformKeyframe> create(double time, const TransformOperations& value, PassOwnPtr<CCTimingFunction>); + virtual ~CCTransformKeyframe(); + + const TransformOperations& value() const; + + PassOwnPtr<CCTransformKeyframe> clone() const; + +private: + CCTransformKeyframe(double time, const TransformOperations& value, PassOwnPtr<CCTimingFunction>); + + TransformOperations m_value; }; class CCKeyframedFloatAnimationCurve : public CCFloatAnimationCurve { public: // It is required that the keyframes be sorted by time. - static PassOwnPtr<CCKeyframedFloatAnimationCurve> create(const Vector<CCFloatKeyframe>& keyframes); + static PassOwnPtr<CCKeyframedFloatAnimationCurve> create(); virtual ~CCKeyframedFloatAnimationCurve(); + void addKeyframe(PassOwnPtr<CCFloatKeyframe>); + // CCAnimationCurve implementation virtual double duration() const; virtual PassOwnPtr<CCAnimationCurve> clone() const; @@ -75,20 +95,22 @@ public: virtual float getValue(double t) const; private: - explicit CCKeyframedFloatAnimationCurve(const Vector<CCFloatKeyframe>&); + CCKeyframedFloatAnimationCurve(); // Always sorted in order of increasing time. No two keyframes have the // same time. - Vector<CCFloatKeyframe> m_keyframes; + Vector<OwnPtr<CCFloatKeyframe> > m_keyframes; }; class CCKeyframedTransformAnimationCurve : public CCTransformAnimationCurve { public: // It is required that the keyframes be sorted by time. - static PassOwnPtr<CCKeyframedTransformAnimationCurve> create(const Vector<CCTransformKeyframe>& keyframes); + static PassOwnPtr<CCKeyframedTransformAnimationCurve> create(); virtual ~CCKeyframedTransformAnimationCurve(); + void addKeyframe(PassOwnPtr<CCTransformKeyframe>); + // CCAnimationCurve implementation virtual double duration() const; virtual PassOwnPtr<CCAnimationCurve> clone() const; @@ -97,11 +119,11 @@ public: virtual TransformationMatrix getValue(double t, const IntSize&) const; private: - explicit CCKeyframedTransformAnimationCurve(const Vector<CCTransformKeyframe>&); + CCKeyframedTransformAnimationCurve(); // Always sorted in order of increasing time. No two keyframes have the // same time. - Vector<CCTransformKeyframe> m_keyframes; + Vector<OwnPtr<CCTransformKeyframe> > m_keyframes; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp index d9e72efc4..335d3a58e 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationController.cpp @@ -37,16 +37,16 @@ namespace WebCore { namespace { -template <typename Keyframe, typename Value> -void appendKeyframe(Vector<Keyframe>& keyframes, double keyTime, const Value* value) +template <class Value, class Keyframe, class Curve> +void appendKeyframe(Curve& curve, double keyTime, const Value* value, PassOwnPtr<CCTimingFunction> timingFunction) { - keyframes.append(Keyframe(keyTime, value->value())); + curve.addKeyframe(Keyframe::create(keyTime, value->value(), timingFunction)); } template <> -void appendKeyframe<CCTransformKeyframe, TransformAnimationValue>(Vector<CCTransformKeyframe>& keyframes, double keyTime, const TransformAnimationValue* value) +void appendKeyframe<TransformAnimationValue, CCTransformKeyframe, CCKeyframedTransformAnimationCurve>(CCKeyframedTransformAnimationCurve& curve, double keyTime, const TransformAnimationValue* value, PassOwnPtr<CCTimingFunction> timingFunction) { - keyframes.append(CCTransformKeyframe(keyTime, *value->value())); + curve.addKeyframe(CCTransformKeyframe::create(keyTime, *value->value(), timingFunction)); } template <class Value, class Keyframe, class Curve> @@ -64,21 +64,33 @@ PassOwnPtr<CCActiveAnimation> createActiveAnimation(const KeyframeValueList& val if (animation && animation->isFillModeSet() && (animation->fillsForwards() || animation->fillsBackwards())) return nullptr; + OwnPtr<Curve> curve = Curve::create(); Vector<Keyframe> keyframes; for (size_t i = 0; i < valueList.size(); i++) { const Value* originalValue = static_cast<const Value*>(valueList.at(i)); - // FIXME: add support for timing functions. - if (originalValue->timingFunction() && originalValue->timingFunction()->type() != TimingFunction::LinearFunction) - return nullptr; + OwnPtr<CCTimingFunction> timingFunction; + if (originalValue->timingFunction()) { + switch (originalValue->timingFunction()->type()) { + case TimingFunction::StepsFunction: + // FIXME: add support for steps timing function. + return nullptr; + case TimingFunction::LinearFunction: + // Don't set the timing function. Keyframes are interpolated linearly if there is no timing function. + break; + case TimingFunction::CubicBezierFunction: + const CubicBezierTimingFunction* originalTimingFunction = static_cast<const CubicBezierTimingFunction*>(originalValue->timingFunction()); + timingFunction = CCCubicBezierTimingFunction::create(originalTimingFunction->x1(), originalTimingFunction->y1(), originalTimingFunction->x2(), originalTimingFunction->y2()); + break; + } // switch + } else + timingFunction = CCEaseTimingFunction::create(); double duration = (animation && animation->isDurationSet()) ? animation->duration() : 1; - appendKeyframe(keyframes, originalValue->keyTime() * duration, originalValue); + appendKeyframe<Value, Keyframe, Curve>(*curve, originalValue->keyTime() * duration, originalValue, timingFunction.release()); } - OwnPtr<Curve> curve = Curve::create(keyframes); - OwnPtr<CCActiveAnimation> anim = CCActiveAnimation::create(curve.release(), animationId, groupId, targetProperty); ASSERT(anim.get()); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp index 2096ce398..f09dcfae0 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.cpp @@ -49,15 +49,15 @@ CCLayerAnimationControllerImpl::~CCLayerAnimationControllerImpl() { } -void CCLayerAnimationControllerImpl::animate(double frameBeginTimeSecs, CCAnimationEventsVector& events) +void CCLayerAnimationControllerImpl::animate(double monotonicTime, CCAnimationEventsVector& events) { - startAnimationsWaitingForNextTick(frameBeginTimeSecs, events); - startAnimationsWaitingForStartTime(frameBeginTimeSecs, events); - startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs, events); - resolveConflicts(frameBeginTimeSecs); - tickAnimations(frameBeginTimeSecs); - purgeFinishedAnimations(); - startAnimationsWaitingForTargetAvailability(frameBeginTimeSecs, events); + startAnimationsWaitingForNextTick(monotonicTime, events); + startAnimationsWaitingForStartTime(monotonicTime, events); + startAnimationsWaitingForTargetAvailability(monotonicTime, events); + resolveConflicts(monotonicTime); + tickAnimations(monotonicTime); + purgeFinishedAnimations(events); + startAnimationsWaitingForTargetAvailability(monotonicTime, events); } void CCLayerAnimationControllerImpl::add(PassOwnPtr<CCActiveAnimation> anim) @@ -83,28 +83,28 @@ bool CCLayerAnimationControllerImpl::hasActiveAnimation() const return false; } -void CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick(double now, CCAnimationEventsVector& events) +void CCLayerAnimationControllerImpl::startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector& events) { for (size_t i = 0; i < m_activeAnimations.size(); ++i) { if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForNextTick) { - m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, now); - m_activeAnimations[i]->setStartTime(now); - events.append(CCAnimationStartedEvent(m_client->id(), now)); + m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); + m_activeAnimations[i]->setStartTime(monotonicTime); + events.append(CCAnimationStartedEvent::create(m_client->id())); } } } -void CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime(double now, CCAnimationEventsVector& events) +void CCLayerAnimationControllerImpl::startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector& events) { for (size_t i = 0; i < m_activeAnimations.size(); ++i) { - if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= now) { - m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, now); - events.append(CCAnimationStartedEvent(m_client->id(), now)); + if (m_activeAnimations[i]->runState() == CCActiveAnimation::WaitingForStartTime && m_activeAnimations[i]->startTime() <= monotonicTime) { + m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); + events.append(CCAnimationStartedEvent::create(m_client->id())); } } } -void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability(double now, CCAnimationEventsVector& events) +void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector& events) { // First collect running properties. TargetProperties blockedProperties; @@ -134,13 +134,13 @@ void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability // If the intersection is null, then we are free to start the animations in the group. if (nullIntersection) { - m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, now); - m_activeAnimations[i]->setStartTime(now); - events.append(CCAnimationStartedEvent(m_client->id(), now)); + m_activeAnimations[i]->setRunState(CCActiveAnimation::Running, monotonicTime); + m_activeAnimations[i]->setStartTime(monotonicTime); + events.append(CCAnimationStartedEvent::create(m_client->id())); for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { if (m_activeAnimations[i]->group() == m_activeAnimations[j]->group()) { - m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, now); - m_activeAnimations[j]->setStartTime(now); + m_activeAnimations[j]->setRunState(CCActiveAnimation::Running, monotonicTime); + m_activeAnimations[j]->setStartTime(monotonicTime); } } } @@ -148,7 +148,7 @@ void CCLayerAnimationControllerImpl::startAnimationsWaitingForTargetAvailability } } -void CCLayerAnimationControllerImpl::resolveConflicts(double now) +void CCLayerAnimationControllerImpl::resolveConflicts(double monotonicTime) { // Find any animations that are animating the same property and resolve the // confict. We could eventually blend, but for now we'll just abort the @@ -160,16 +160,16 @@ void CCLayerAnimationControllerImpl::resolveConflicts(double now) for (size_t j = i + 1; j < m_activeAnimations.size(); ++j) { if (m_activeAnimations[j]->runState() == CCActiveAnimation::Running && m_activeAnimations[i]->targetProperty() == m_activeAnimations[j]->targetProperty()) { if (m_activeAnimations[i]->startTime() > m_activeAnimations[j]->startTime()) - m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, now); + m_activeAnimations[j]->setRunState(CCActiveAnimation::Aborted, monotonicTime); else - m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, now); + m_activeAnimations[i]->setRunState(CCActiveAnimation::Aborted, monotonicTime); } } } } } -void CCLayerAnimationControllerImpl::purgeFinishedAnimations() +void CCLayerAnimationControllerImpl::purgeFinishedAnimations(CCAnimationEventsVector& events) { // Each iteration, m_activeAnimations.size() decreases or i increments, // guaranteeing progress towards loop termination. @@ -186,6 +186,7 @@ void CCLayerAnimationControllerImpl::purgeFinishedAnimations() } } if (allAnimsWithSameIdAreFinished) { + events.append(CCAnimationFinishedEvent::create(m_client->id(), m_activeAnimations[i]->id())); m_finishedAnimations.append(m_activeAnimations[i]->signature()); m_activeAnimations.remove(i); } else @@ -193,18 +194,19 @@ void CCLayerAnimationControllerImpl::purgeFinishedAnimations() } } -void CCLayerAnimationControllerImpl::tickAnimations(double now) +void CCLayerAnimationControllerImpl::tickAnimations(double monotonicTime) { for (size_t i = 0; i < m_activeAnimations.size(); ++i) { if (m_activeAnimations[i]->runState() == CCActiveAnimation::Running) { - double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(now); + double trimmed = m_activeAnimations[i]->trimTimeToCurrentIteration(monotonicTime); + switch (m_activeAnimations[i]->targetProperty()) { case CCActiveAnimation::Transform: { const CCTransformAnimationCurve* transformAnimationCurve = m_activeAnimations[i]->curve()->toTransformAnimationCurve(); const TransformationMatrix matrix = transformAnimationCurve->getValue(trimmed, m_client->bounds()); - if (m_activeAnimations[i]->isFinishedAt(now)) - m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, now); + if (m_activeAnimations[i]->isFinishedAt(monotonicTime)) + m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime); m_client->setTransform(matrix); break; @@ -213,8 +215,8 @@ void CCLayerAnimationControllerImpl::tickAnimations(double now) case CCActiveAnimation::Opacity: { const CCFloatAnimationCurve* floatAnimationCurve = m_activeAnimations[i]->curve()->toFloatAnimationCurve(); const float opacity = floatAnimationCurve->getValue(trimmed); - if (m_activeAnimations[i]->isFinishedAt(now)) - m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, now); + if (m_activeAnimations[i]->isFinishedAt(monotonicTime)) + m_activeAnimations[i]->setRunState(CCActiveAnimation::Finished, monotonicTime); m_client->setOpacity(opacity); break; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h index 296066de0..6ac00e7ae 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationControllerImpl.h @@ -61,7 +61,7 @@ public: virtual ~CCLayerAnimationControllerImpl(); - void animate(double frameBeginTimeSecs, CCAnimationEventsVector&); + void animate(double monotonicTime, CCAnimationEventsVector&); void add(PassOwnPtr<CCActiveAnimation>); @@ -78,13 +78,13 @@ private: // The animator is owned by the layer. explicit CCLayerAnimationControllerImpl(CCLayerAnimationControllerImplClient*); - void startAnimationsWaitingForNextTick(double now, CCAnimationEventsVector&); - void startAnimationsWaitingForStartTime(double now, CCAnimationEventsVector&); - void startAnimationsWaitingForTargetAvailability(double now, CCAnimationEventsVector&); - void resolveConflicts(double now); - void purgeFinishedAnimations(); + void startAnimationsWaitingForNextTick(double monotonicTime, CCAnimationEventsVector&); + void startAnimationsWaitingForStartTime(double monotonicTime, CCAnimationEventsVector&); + void startAnimationsWaitingForTargetAvailability(double monotonicTime, CCAnimationEventsVector&); + void resolveConflicts(double monotonicTime); + void purgeFinishedAnimations(CCAnimationEventsVector&); - void tickAnimations(double now); + void tickAnimations(double monotonicTime); CCLayerAnimationControllerImplClient* m_client; Vector<OwnPtr<CCActiveAnimation> > m_activeAnimations; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h new file mode 100644 index 000000000..a764cc37b --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerAnimationDelegate.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 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: + * 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. 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 INC. 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. + */ + +#ifndef CCLayerAnimationDelegate_h +#define CCLayerAnimationDelegate_h + +namespace WebCore { + +// This class is used to send notifications when layer animations begin or end. +class CCLayerAnimationDelegate { +public: + virtual void notifyAnimationStarted(double time) = 0; + virtual void notifyAnimationFinished(int animationId) = 0; +}; + +} // namespace WebCore + +#endif // CCLayerAnimationDelegate_h diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp index 0589dca8a..8f6078097 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp @@ -42,10 +42,13 @@ namespace WebCore { CCLayerImpl::CCLayerImpl(int id) : m_parent(0) + , m_maskLayerId(-1) + , m_replicaLayerId(-1) , m_layerId(id) , m_anchorPoint(0.5, 0.5) , m_anchorPointZ(0) , m_scrollable(false) + , m_shouldScrollOnMainThread(false) , m_haveWheelEventHandlers(false) , m_backgroundCoversViewport(false) , m_doubleSided(true) @@ -73,7 +76,7 @@ CCLayerImpl::~CCLayerImpl() ASSERT(CCProxy::isImplThread()); } -void CCLayerImpl::addChild(PassRefPtr<CCLayerImpl> child) +void CCLayerImpl::addChild(PassOwnPtr<CCLayerImpl> child) { child->setParent(this); m_children.append(child); @@ -83,13 +86,16 @@ void CCLayerImpl::removeFromParent() { if (!m_parent) return; - for (size_t i = 0; i < m_parent->m_children.size(); ++i) { - if (m_parent->m_children[i].get() == this) { - m_parent->m_children.remove(i); - break; + + CCLayerImpl* parent = m_parent; + m_parent = 0; + + for (size_t i = 0; i < parent->m_children.size(); ++i) { + if (parent->m_children[i].get() == this) { + parent->m_children.remove(i); + return; } } - m_parent = 0; } void CCLayerImpl::removeAllChildren() @@ -188,12 +194,6 @@ void CCLayerImpl::scrollBy(const IntSize& scroll) noteLayerPropertyChangedForSubtree(); } -void CCLayerImpl::cleanupResources() -{ - if (renderSurface()) - renderSurface()->cleanupResources(); -} - const IntRect CCLayerImpl::getDrawRect() const { // Form the matrix used by the shader to map the corners of the layer's @@ -244,7 +244,7 @@ void CCLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const ts << "drawsContent: " << (m_drawsContent ? "yes" : "no") << "\n"; } -void sortLayers(Vector<RefPtr<CCLayerImpl> >::iterator first, Vector<RefPtr<CCLayerImpl> >::iterator end, CCLayerSorter* layerSorter) +void sortLayers(Vector<CCLayerImpl*>::iterator first, Vector<CCLayerImpl*>::iterator end, CCLayerSorter* layerSorter) { TRACE_EVENT("LayerRendererChromium::sortLayers", 0, 0); layerSorter->sort(first, end); @@ -260,7 +260,7 @@ String CCLayerImpl::layerTreeAsText() const void CCLayerImpl::dumpLayer(TextStream& ts, int indent) const { writeIndent(ts, indent); - ts << layerTypeAsString() << "(" << m_name << ")\n"; + ts << layerTypeAsString() << "(" << m_debugName << ")\n"; dumpLayerProperties(ts, indent+2); if (m_replicaLayer) { writeIndent(ts, indent+2); @@ -319,21 +319,27 @@ void CCLayerImpl::setBounds(const IntSize& bounds) m_layerPropertyChanged = true; } -void CCLayerImpl::setMaskLayer(PassRefPtr<CCLayerImpl> maskLayer) +void CCLayerImpl::setMaskLayer(PassOwnPtr<CCLayerImpl> maskLayer) { - if (m_maskLayer == maskLayer) + m_maskLayer = maskLayer; + + int newLayerId = m_maskLayer ? m_maskLayer->id() : -1; + if (newLayerId == m_maskLayerId) return; - m_maskLayer = maskLayer; + m_maskLayerId = newLayerId; noteLayerPropertyChangedForSubtree(); } -void CCLayerImpl::setReplicaLayer(PassRefPtr<CCLayerImpl> replicaLayer) +void CCLayerImpl::setReplicaLayer(PassOwnPtr<CCLayerImpl> replicaLayer) { - if (m_replicaLayer == replicaLayer) + m_replicaLayer = replicaLayer; + + int newLayerId = m_replicaLayer ? m_replicaLayer->id() : -1; + if (newLayerId == m_replicaLayerId) return; - m_replicaLayer = replicaLayer; + m_replicaLayerId = newLayerId; noteLayerPropertyChangedForSubtree(); } @@ -523,6 +529,10 @@ void CCLayerImpl::setDoubleSided(bool doubleSided) noteLayerPropertyChangedForSubtree(); } +void CCLayerImpl::didLoseContext() +{ +} + } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h index c7a4f0856..f1c7b4ee5 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h @@ -30,6 +30,7 @@ #include "FilterOperations.h" #include "FloatRect.h" #include "IntRect.h" +#include "Region.h" #include "TextStream.h" #include "TransformationMatrix.h" #include "cc/CCLayerAnimationControllerImpl.h" @@ -46,11 +47,11 @@ class CCLayerSorter; class LayerChromium; class LayerRendererChromium; -class CCLayerImpl : public RefCounted<CCLayerImpl>, public CCLayerAnimationControllerImplClient { +class CCLayerImpl : public CCLayerAnimationControllerImplClient { public: - static PassRefPtr<CCLayerImpl> create(int id) + static PassOwnPtr<CCLayerImpl> create(int id) { - return adoptRef(new CCLayerImpl(id)); + return adoptPtr(new CCLayerImpl(id)); } // CCLayerAnimationControllerImplClient implementation. @@ -65,15 +66,15 @@ public: // Tree structure. CCLayerImpl* parent() const { return m_parent; } - const Vector<RefPtr<CCLayerImpl> >& children() const { return m_children; } - void addChild(PassRefPtr<CCLayerImpl>); + const Vector<OwnPtr<CCLayerImpl> >& children() const { return m_children; } + void addChild(PassOwnPtr<CCLayerImpl>); void removeFromParent(); void removeAllChildren(); - void setMaskLayer(PassRefPtr<CCLayerImpl>); + void setMaskLayer(PassOwnPtr<CCLayerImpl>); CCLayerImpl* maskLayer() const { return m_maskLayer.get(); } - void setReplicaLayer(PassRefPtr<CCLayerImpl>); + void setReplicaLayer(PassOwnPtr<CCLayerImpl>); CCLayerImpl* replicaLayer() const { return m_replicaLayer.get(); } #ifndef NDEBUG @@ -96,8 +97,6 @@ public: // Returns true if any of the layer's descendants has content to draw. bool descendantDrawsContent(); - void cleanupResources(); - void setAnchorPoint(const FloatPoint&); const FloatPoint& anchorPoint() const { return m_anchorPoint; } @@ -134,9 +133,6 @@ public: void setSublayerTransform(const TransformationMatrix&); const TransformationMatrix& sublayerTransform() const { return m_sublayerTransform; } - void setName(const String& name) { m_name = name; } - const String& name() const { return m_name; } - // Debug layer border - visual effect only, do not change geometry/clipping/etc. void setDebugBorderColor(Color); Color debugBorderColor() const { return m_debugBorderColor; } @@ -144,6 +140,10 @@ public: float debugBorderWidth() const { return m_debugBorderWidth; } bool hasDebugBorders() const; + // Debug layer name. + void setDebugName(const String& debugName) { m_debugName = debugName; } + String debugName() const { return m_debugName; } + CCRenderSurface* renderSurface() const { return m_renderSurface.get(); } void createRenderSurface(); void clearRenderSurface() { m_renderSurface.clear(); } @@ -181,9 +181,15 @@ public: bool scrollable() const { return m_scrollable; } void setScrollable(bool scrollable) { m_scrollable = scrollable; } + bool shouldScrollOnMainThread() const { return m_shouldScrollOnMainThread; } + void setShouldScrollOnMainThread(bool shouldScrollOnMainThread) { m_shouldScrollOnMainThread = shouldScrollOnMainThread; } + bool haveWheelEventHandlers() const { return m_haveWheelEventHandlers; } void setHaveWheelEventHandlers(bool haveWheelEventHandlers) { m_haveWheelEventHandlers = haveWheelEventHandlers; } + const Region& nonFastScrollableRegion() const { return m_nonFastScrollableRegion; } + void setNonFastScrollableRegion(const Region& region) { m_nonFastScrollableRegion = region; } + const IntRect& visibleLayerRect() const { return m_visibleLayerRect; } void setVisibleLayerRect(const IntRect& visibleLayerRect) { m_visibleLayerRect = visibleLayerRect; } @@ -209,6 +215,13 @@ public: CCLayerAnimationControllerImpl* layerAnimationController() { return m_layerAnimationController.get(); } + virtual Region opaqueContentsRegion() const { return Region(); }; + + // Indicates that the context previously used to render this layer + // was lost and that a new one has been created. Won't be called + // until the new context has been created successfully. + virtual void didLoseContext(); + protected: explicit CCLayerImpl(int); @@ -236,9 +249,12 @@ private: // Properties internal to CCLayerImpl CCLayerImpl* m_parent; - Vector<RefPtr<CCLayerImpl> > m_children; - RefPtr<CCLayerImpl> m_maskLayer; - RefPtr<CCLayerImpl> m_replicaLayer; + Vector<OwnPtr<CCLayerImpl> > m_children; + // m_maskLayer can be temporarily stolen during tree sync, we need this ID to confirm newly assigned layer is still the previous one + int m_maskLayerId; + OwnPtr<CCLayerImpl> m_maskLayer; + int m_replicaLayerId; // ditto + OwnPtr<CCLayerImpl> m_replicaLayer; int m_layerId; // Properties synchronized from the associated LayerChromium. @@ -248,7 +264,9 @@ private: IntSize m_contentBounds; IntPoint m_scrollPosition; bool m_scrollable; + bool m_shouldScrollOnMainThread; bool m_haveWheelEventHandlers; + Region m_nonFastScrollableRegion; Color m_backgroundColor; bool m_backgroundCoversViewport; @@ -282,8 +300,6 @@ private: int m_debugID; #endif - String m_name; - // Render surface this layer draws into. This is a surface that can belong // either to this layer (if m_targetRenderSurface == m_renderSurface) or // to an ancestor of this layer. The target render surface determines the @@ -299,6 +315,9 @@ private: Color m_debugBorderColor; float m_debugBorderWidth; + // Debug layer name. + String m_debugName; + FilterOperations m_filters; TransformationMatrix m_drawTransform; @@ -324,7 +343,7 @@ private: OwnPtr<CCLayerAnimationControllerImpl> m_layerAnimationController; }; -void sortLayers(Vector<RefPtr<CCLayerImpl> >::iterator first, Vector<RefPtr<CCLayerImpl> >::iterator end, CCLayerSorter*); +void sortLayers(Vector<CCLayerImpl*>::iterator first, Vector<CCLayerImpl*>::iterator end, CCLayerSorter*); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.cpp index 97d6d185a..2d6d2f7f7 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.cpp @@ -35,8 +35,8 @@ namespace WebCore { -template <typename LayerType, typename RenderSurfaceType, typename ActionType> -void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>& it) +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> +void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>& it) { it.m_targetRenderSurfaceLayerIndex = 0; it.m_currentLayerIndex = CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; @@ -44,15 +44,15 @@ void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator<LayerType, Rende m_highestTargetRenderSurfaceLayer = 0; } -template <typename LayerType, typename RenderSurfaceType, typename ActionType> -void CCLayerIteratorActions::BackToFront::end(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>& it) +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> +void CCLayerIteratorActions::BackToFront::end(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>& it) { it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; it.m_currentLayerIndex = 0; } -template <typename LayerType, typename RenderSurfaceType, typename ActionType> -void CCLayerIteratorActions::BackToFront::next(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>& it) +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> +void CCLayerIteratorActions::BackToFront::next(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>& it) { // If the current layer has a RS, move to its layer list. Otherwise, visit the next layer in the current RS layer list. if (it.currentLayerRepresentsContributingRenderSurface()) { @@ -85,23 +85,23 @@ void CCLayerIteratorActions::BackToFront::next(CCLayerIterator<LayerType, Render } } -template <typename LayerType, typename RenderSurfaceType, typename ActionType> -void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>& it) +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> +void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>& it) { it.m_targetRenderSurfaceLayerIndex = 0; it.m_currentLayerIndex = it.targetRenderSurfaceChildren().size() - 1; goToHighestInSubtree(it); } -template <typename LayerType, typename RenderSurfaceType, typename ActionType> -void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>& it) +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> +void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>& it) { it.m_targetRenderSurfaceLayerIndex = CCLayerIteratorValue::InvalidTargetRenderSurfaceLayerIndex; it.m_currentLayerIndex = 0; } -template <typename LayerType, typename RenderSurfaceType, typename ActionType> -void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>& it) +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> +void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>& it) { // Moves to the previous layer in the current RS layer list. Then we check if the // new current layer has its own RS, in which case there are things in that RS layer list that are higher, so @@ -128,8 +128,8 @@ void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator<LayerType, Render } } -template <typename LayerType, typename RenderSurfaceType, typename ActionType> -void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>& it) +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> +void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>& it) { if (it.currentLayerRepresentsTargetRenderSurface()) return; @@ -147,23 +147,23 @@ void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator<L } // Declare each of the above functions for LayerChromium and CCLayerImpl classes so that they are linked. -template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator<LayerChromium, RenderSurfaceChromium, BackToFront> &); -template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator<LayerChromium, RenderSurfaceChromium, BackToFront>&); -template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator<LayerChromium, RenderSurfaceChromium, BackToFront>&); - -template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator<CCLayerImpl, CCRenderSurface, BackToFront>&); -template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator<CCLayerImpl, CCRenderSurface, BackToFront>&); -template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator<CCLayerImpl, CCRenderSurface, BackToFront>&); - -template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator<LayerChromium, RenderSurfaceChromium, FrontToBack>&); -template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator<LayerChromium, RenderSurfaceChromium, FrontToBack>&); -template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator<LayerChromium, RenderSurfaceChromium, FrontToBack>&); -template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator<LayerChromium, RenderSurfaceChromium, FrontToBack>&); - -template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator<CCLayerImpl, CCRenderSurface, FrontToBack>&); -template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator<CCLayerImpl, CCRenderSurface, FrontToBack>&); -template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator<CCLayerImpl, CCRenderSurface, FrontToBack>&); -template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator<CCLayerImpl, CCRenderSurface, FrontToBack>&); +template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, BackToFront> &); +template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, BackToFront>&); +template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, BackToFront>&); + +template void CCLayerIteratorActions::BackToFront::begin(CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, BackToFront>&); +template void CCLayerIteratorActions::BackToFront::end(CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, BackToFront>&); +template void CCLayerIteratorActions::BackToFront::next(CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, BackToFront>&); + +template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, FrontToBack>&); +template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, FrontToBack>&); +template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, FrontToBack>&); +template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, FrontToBack>&); + +template void CCLayerIteratorActions::FrontToBack::next(CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, FrontToBack>&); +template void CCLayerIteratorActions::FrontToBack::end(CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, FrontToBack>&); +template void CCLayerIteratorActions::FrontToBack::begin(CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, FrontToBack>&); +template void CCLayerIteratorActions::FrontToBack::goToHighestInSubtree(CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, FrontToBack>&); } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h index be985e153..d89bd6912 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerIterator.h @@ -92,15 +92,15 @@ struct CCLayerIteratorValue { }; // An iterator class for walking over layers in the RenderSurface-Layer tree. -template <typename LayerType, typename RenderSurfaceType, typename IteratorActionType> +template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename IteratorActionType> class CCLayerIterator { - typedef CCLayerIterator<LayerType, RenderSurfaceType, IteratorActionType> CCLayerIteratorType; + typedef CCLayerIterator<LayerType, LayerList, RenderSurfaceType, IteratorActionType> CCLayerIteratorType; public: CCLayerIterator() : m_renderSurfaceLayerList(0) { } - static CCLayerIteratorType begin(const Vector<RefPtr<LayerType> >* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, true); } - static CCLayerIteratorType end(const Vector<RefPtr<LayerType> >* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, false); } + static CCLayerIteratorType begin(const LayerList* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, true); } + static CCLayerIteratorType end(const LayerList* renderSurfaceLayerList) { return CCLayerIteratorType(renderSurfaceLayerList, false); } CCLayerIteratorType& operator++() { m_actions.next(*this); return *this; } bool operator==(const CCLayerIterator& other) const @@ -117,10 +117,10 @@ public: bool representsContributingRenderSurface() const { return !representsTargetRenderSurface() && currentLayerRepresentsContributingRenderSurface(); } bool representsItself() const { return !representsTargetRenderSurface() && !representsContributingRenderSurface(); } - LayerType* targetRenderSurfaceLayer() const { return (*m_renderSurfaceLayerList)[m_targetRenderSurfaceLayerIndex].get(); } + LayerType* targetRenderSurfaceLayer() const { return getRawPtr((*m_renderSurfaceLayerList)[m_targetRenderSurfaceLayerIndex]); } private: - CCLayerIterator(const Vector<RefPtr<LayerType> >* renderSurfaceLayerList, bool start) + CCLayerIterator(const LayerList* renderSurfaceLayerList, bool start) : m_renderSurfaceLayerList(renderSurfaceLayerList) { if (start && !renderSurfaceLayerList->isEmpty()) @@ -129,16 +129,19 @@ private: m_actions.end(*this); } - inline LayerType* currentLayer() const { return currentLayerRepresentsTargetRenderSurface() ? targetRenderSurfaceLayer() : targetRenderSurfaceChildren()[m_currentLayerIndex].get(); } + inline static LayerChromium* getRawPtr(const RefPtr<LayerChromium>& ptr) { return ptr.get(); } + inline static CCLayerImpl* getRawPtr(CCLayerImpl* ptr) { return ptr; } + + inline LayerType* currentLayer() const { return currentLayerRepresentsTargetRenderSurface() ? targetRenderSurfaceLayer() : getRawPtr(targetRenderSurfaceChildren()[m_currentLayerIndex]); } inline bool currentLayerRepresentsContributingRenderSurface() const { return CCLayerTreeHostCommon::renderSurfaceContributesToTarget<LayerType>(currentLayer(), targetRenderSurfaceLayer()->id()); } inline bool currentLayerRepresentsTargetRenderSurface() const { return m_currentLayerIndex == CCLayerIteratorValue::LayerIndexRepresentingTargetRenderSurface; } inline RenderSurfaceType* targetRenderSurface() const { return targetRenderSurfaceLayer()->renderSurface(); } - inline const Vector<RefPtr<LayerType> >& targetRenderSurfaceChildren() const { return targetRenderSurface()->layerList(); } + inline const LayerList& targetRenderSurfaceChildren() const { return targetRenderSurface()->layerList(); } IteratorActionType m_actions; - const Vector<RefPtr<LayerType> >* m_renderSurfaceLayerList; + const LayerList* m_renderSurfaceLayerList; // The iterator's current position. @@ -161,14 +164,14 @@ struct CCLayerIteratorActions { // Walks layers sorted by z-order from back to front. class BackToFront { public: - template <typename LayerType, typename RenderSurfaceType, typename ActionType> - void begin(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>&); + template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> + void begin(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>&); - template <typename LayerType, typename RenderSurfaceType, typename ActionType> - void end(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>&); + template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> + void end(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>&); - template <typename LayerType, typename RenderSurfaceType, typename ActionType> - void next(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>&); + template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> + void next(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>&); private: int m_highestTargetRenderSurfaceLayer; @@ -177,18 +180,18 @@ struct CCLayerIteratorActions { // Walks layers sorted by z-order from front to back class FrontToBack { public: - template <typename LayerType, typename RenderSurfaceType, typename ActionType> - void begin(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>&); + template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> + void begin(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>&); - template <typename LayerType, typename RenderSurfaceType, typename ActionType> - void end(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>&); + template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> + void end(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>&); - template <typename LayerType, typename RenderSurfaceType, typename ActionType> - void next(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>&); + template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> + void next(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>&); private: - template <typename LayerType, typename RenderSurfaceType, typename ActionType> - void goToHighestInSubtree(CCLayerIterator<LayerType, RenderSurfaceType, ActionType>&); + template <typename LayerType, typename LayerList, typename RenderSurfaceType, typename ActionType> + void goToHighestInSubtree(CCLayerIterator<LayerType, LayerList, RenderSurfaceType, ActionType>&); }; }; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp index 752855447..c434a1d95 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.cpp @@ -295,7 +295,7 @@ void CCLayerSorter::createGraphNodes(LayerList::iterator first, LayerList::itera float minZ = FLT_MAX; float maxZ = -FLT_MAX; for (LayerList::const_iterator it = first; it < last; it++) { - m_nodes.append(GraphNode(it->get())); + m_nodes.append(GraphNode(*it)); GraphNode& node = m_nodes.at(m_nodes.size() - 1); CCRenderSurface* renderSurface = node.layer->renderSurface(); if (!node.layer->drawsContent() && !renderSurface) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h index 2c30d5dae..8ab9b7581 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerSorter.h @@ -39,7 +39,7 @@ class CCLayerSorter { public: CCLayerSorter(); - typedef Vector<RefPtr<CCLayerImpl> > LayerList; + typedef Vector<CCLayerImpl*> LayerList; void sort(LayerList::iterator first, LayerList::iterator last); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp index cfefbd2b8..19d0251dc 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.cpp @@ -112,6 +112,24 @@ IntRect CCLayerTilingData::tileRect(const Tile* tile) const return tileRect; } +Region CCLayerTilingData::opaqueRegionInLayerRect(const IntRect& layerRect) const +{ + Region opaqueRegion; + int left, top, right, bottom; + layerRectToTileIndices(layerRect, left, top, right, bottom); + for (int j = top; j <= bottom; ++j) { + for (int i = left; i <= right; ++i) { + Tile* tile = tileAt(i, j); + if (!tile) + continue; + + IntRect tileOpaqueRect = intersection(layerRect, tile->opaqueRect()); + opaqueRegion.unite(tileOpaqueRect); + } + } + return opaqueRegion; +} + void CCLayerTilingData::setBounds(const IntSize& size) { m_tilingData.setTotalSize(size.width(), size.height()); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h index 869d42e15..9e18695e8 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTilingData.h @@ -30,6 +30,7 @@ #if USE(ACCELERATED_COMPOSITING) #include "IntRect.h" +#include "Region.h" #include "TilingData.h" #include <wtf/HashMap.h> #include <wtf/HashTraits.h> @@ -69,9 +70,13 @@ public: int i() const { return m_i; } int j() const { return m_j; } void moveTo(int i, int j) { m_i = i; m_j = j; } + + const IntRect& opaqueRect() const { return m_opaqueRect; } + void setOpaqueRect(const IntRect& opaqueRect) { m_opaqueRect = opaqueRect; } private: int m_i; int m_j; + IntRect m_opaqueRect; }; // Default hash key traits for integers disallow 0 and -1 as a key, so // use a custom hash trait which disallows -1 and -2 instead. @@ -96,6 +101,8 @@ public: void layerRectToTileIndices(const IntRect&, int &left, int &top, int &right, int &bottom) const; IntRect tileRect(const Tile*) const; + Region opaqueRegionInLayerRect(const IntRect&) const; + void reset(); protected: diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp index 501ee17de..34bce1181 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp @@ -35,6 +35,7 @@ #include "cc/CCLayerIterator.h" #include "cc/CCLayerTreeHostCommon.h" #include "cc/CCLayerTreeHostImpl.h" +#include "cc/CCOcclusionTracker.h" #include "cc/CCSingleThreadProxy.h" #include "cc/CCThread.h" #include "cc/CCThreadProxy.h" @@ -66,6 +67,9 @@ CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings , m_client(client) , m_frameNumber(0) , m_layerRendererInitialized(false) + , m_contextLost(false) + , m_numTimesRecreateShouldFail(0) + , m_numFailedRecreateAttempts(0) , m_settings(settings) , m_visible(true) , m_pageScaleFactor(1) @@ -114,7 +118,7 @@ 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); + m_client->didRecreateContext(false); return; } @@ -131,6 +135,40 @@ void CCLayerTreeHost::initializeLayerRenderer() m_layerRendererInitialized = true; } +CCLayerTreeHost::RecreateResult CCLayerTreeHost::recreateContext() +{ + TRACE_EVENT0("cc", "CCLayerTreeHost::recreateContext"); + ASSERT(m_contextLost); + + bool recreated = false; + if (!m_numTimesRecreateShouldFail) + recreated = m_proxy->recreateContext(); + else + m_numTimesRecreateShouldFail--; + + if (recreated) { + m_client->didRecreateContext(true); + m_contextLost = false; + return RecreateSucceeded; + } + + // Tolerate a certain number of recreation failures to work around races + // in the context-lost machinery. + m_numFailedRecreateAttempts++; + if (m_numFailedRecreateAttempts < 5) { + // FIXME: The single thread does not self-schedule context + // recreation. So force another recreation attempt to happen by requesting + // another commit. + if (!CCProxy::hasImplThread()) + setNeedsCommit(); + return RecreateFailedButTryAgain; + } + + // We have tried too many times to recreate the context. Tell the host to fall + // back to software rendering. + m_client->didRecreateContext(false); + return RecreateFailedAndGaveUp; +} void CCLayerTreeHost::deleteContentsTexturesOnImplThread(TextureAllocator* allocator) { @@ -169,13 +207,11 @@ void CCLayerTreeHost::finishCommitOnImplThread(CCLayerTreeHostImpl* hostImpl) { ASSERT(CCProxy::isImplThread()); - // Synchronize trees, if one exists at all... - if (rootLayer()) { - hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->rootLayer())); - // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers. + hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer())); + + // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers. + if (rootLayer()) hostImpl->setNeedsAnimateLayers(); - } else - hostImpl->setRootLayer(0); hostImpl->setSourceFrameNumber(frameNumber()); hostImpl->setViewportSize(viewportSize()); @@ -191,9 +227,9 @@ void CCLayerTreeHost::commitComplete() m_contentsTextureManager->unprotectAllTextures(); } -PassRefPtr<GraphicsContext3D> CCLayerTreeHost::createLayerTreeHostContext3D() +PassRefPtr<GraphicsContext3D> CCLayerTreeHost::createContext() { - return m_client->createLayerTreeHostContext3D(); + return m_client->createContext(); } PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client) @@ -201,15 +237,18 @@ PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayer return CCLayerTreeHostImpl::create(m_settings, client); } -void CCLayerTreeHost::didRecreateGraphicsContext(bool success) +void CCLayerTreeHost::didLoseContext() { - m_client->didRecreateGraphicsContext(success); + TRACE_EVENT("CCLayerTreeHost::didLoseContext", 0, this); + ASSERT(CCProxy::isMainThread()); + m_contextLost = true; + m_numFailedRecreateAttempts = 0; + setNeedsCommit(); } // Temporary hack until WebViewImpl context creation gets simplified GraphicsContext3D* CCLayerTreeHost::context() { - ASSERT(!CCProxy::hasImplThread()); return m_proxy->context(); } @@ -220,6 +259,10 @@ bool CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect) if (!m_layerRendererInitialized) return false; } + if (m_contextLost) { + if (recreateContext() != RecreateSucceeded) + return false; + } m_triggerIdlePaints = false; bool ret = m_proxy->compositeAndReadback(pixels, rect); m_triggerIdlePaints = true; @@ -259,10 +302,10 @@ void CCLayerTreeHost::setNeedsRedraw() m_client->scheduleComposite(); } -void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events) +void CCLayerTreeHost::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime) { ASSERT(CCThreadProxy::isMainThread()); - // FIXME: need to walk the tree. + setAnimationEventsRecursive(*events, m_rootLayer.get(), wallClockTime); } void CCLayerTreeHost::setRootLayer(PassRefPtr<LayerChromium> rootLayer) @@ -309,10 +352,7 @@ void CCLayerTreeHost::setVisible(bool visible) m_visible = visible; - if (!m_layerRendererInitialized) - return; - - if (!visible) { + if (!visible && m_layerRendererInitialized) { m_contentsTextureManager->reduceMemoryToLimit(TextureManager::lowLimitBytes(viewportSize())); m_contentsTextureManager->unprotectAllTextures(); } @@ -326,6 +366,9 @@ void CCLayerTreeHost::setVisible(bool visible) void CCLayerTreeHost::didBecomeInvisibleOnImplThread(CCLayerTreeHostImpl* hostImpl) { ASSERT(CCProxy::isImplThread()); + if (!m_layerRendererInitialized) + return; + if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer) contentsTextureManager()->evictAndDeleteAllTextures(hostImpl->contentsTextureAllocator()); else { @@ -337,16 +380,15 @@ void CCLayerTreeHost::didBecomeInvisibleOnImplThread(CCLayerTreeHostImpl* hostIm // If the frontbuffer is cached, then clobber the impl tree. Otherwise, // push over the tree changes. if (m_proxy->layerRendererCapabilities().contextHasCachedFrontBuffer) { - hostImpl->setRootLayer(0); + hostImpl->setRootLayer(nullptr); return; } - if (rootLayer()) { - hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->rootLayer())); - // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers. + hostImpl->setRootLayer(TreeSynchronizer::synchronizeTrees(rootLayer(), hostImpl->releaseRootLayer())); + + // We may have added an animation during the tree sync. This will cause hostImpl to visit its controllers. + if (rootLayer()) hostImpl->setNeedsAnimateLayers(); - } else - hostImpl->setRootLayer(0); } void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) @@ -354,9 +396,11 @@ void CCLayerTreeHost::startPageScaleAnimation(const IntSize& targetPosition, boo m_proxy->startPageScaleAnimation(targetPosition, useAnchor, scale, durationSec); } -void CCLayerTreeHost::loseCompositorContext(int numTimes) +void CCLayerTreeHost::loseContext(int numTimes) { - m_proxy->loseCompositorContext(numTimes); + TRACE_EVENT1("cc", "CCLayerTreeHost::loseCompositorContext", "numTimes", numTimes); + m_numTimesRecreateShouldFail = numTimes - 1; + m_proxy->loseContext(); } TextureManager* CCLayerTreeHost::contentsTextureManager() const @@ -378,6 +422,10 @@ bool CCLayerTreeHost::updateLayers() if (!m_layerRendererInitialized) return false; } + if (m_contextLost) { + if (recreateContext() != RecreateSucceeded) + return false; + } if (!rootLayer()) return true; @@ -440,7 +488,7 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer) void CCLayerTreeHost::reserveTextures() { // Use BackToFront since it's cheap and this isn't order-dependent. - typedef CCLayerIterator<LayerChromium, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; + typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList); for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) { @@ -458,7 +506,7 @@ void CCLayerTreeHost::paintContentsIfDirty(LayerChromium* layer, PaintType paint if (PaintVisible == paintType) layer->paintContentsIfDirty(occludedScreenSpace); else - layer->idlePaintContentsIfDirty(); + layer->idlePaintContentsIfDirty(occludedScreenSpace); } void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderSurfaceLayer, PaintType paintType) @@ -486,90 +534,36 @@ void CCLayerTreeHost::paintMaskAndReplicaForRenderSurface(LayerChromium* renderS } } -struct RenderSurfaceRegion { - RenderSurfaceChromium* surface; - Region occludedInScreen; -}; - -// Add the surface to the top of the stack and copy the occlusion from the old top of the stack to the new. -static void enterTargetRenderSurface(Vector<RenderSurfaceRegion>& stack, RenderSurfaceChromium* newTarget) -{ - if (stack.isEmpty()) { - stack.append(RenderSurfaceRegion()); - stack.last().surface = newTarget; - } else if (stack.last().surface != newTarget) { - // If we are entering a subtree that is going to move pixels around, then the occlusion we've computed - // so far won't apply to the pixels we're drawing here in the same way. We discard the occlusion thus - // far to be safe, and ensure we don't cull any pixels that are moved such that they become visible. - const RenderSurfaceChromium* oldAncestorThatMovesPixels = stack.last().surface->nearestAncestorThatMovesPixels(); - const RenderSurfaceChromium* newAncestorThatMovesPixels = newTarget->nearestAncestorThatMovesPixels(); - bool enteringSubtreeThatMovesPixels = newAncestorThatMovesPixels && newAncestorThatMovesPixels != oldAncestorThatMovesPixels; - - stack.append(RenderSurfaceRegion()); - stack.last().surface = newTarget; - int lastIndex = stack.size() - 1; - if (!enteringSubtreeThatMovesPixels) - stack[lastIndex].occludedInScreen = stack[lastIndex - 1].occludedInScreen; - } -} - -// Pop the top of the stack off, push on the new surface, and merge the old top's occlusion into the new top surface. -static void leaveTargetRenderSurface(Vector<RenderSurfaceRegion>& stack, RenderSurfaceChromium* newTarget) -{ - int lastIndex = stack.size() - 1; - bool surfaceWillBeAtTopAfterPop = stack.size() > 1 && stack[lastIndex - 1].surface == newTarget; - - if (surfaceWillBeAtTopAfterPop) { - // Merge the top of the stack down. - stack[lastIndex - 1].occludedInScreen.unite(stack[lastIndex].occludedInScreen); - stack.removeLast(); - } else { - // Replace the top of the stack with the new pushed surface. Copy the occluded region to the top. - stack.last().surface = newTarget; - } -} - void CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList, PaintType paintType) { // Use FrontToBack to allow for testing occlusion and performing culling during the tree walk. - typedef CCLayerIterator<LayerChromium, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; + typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::FrontToBack> CCLayerIteratorType; - // The stack holds occluded regions for subtrees in the RenderSurface-Layer tree, so that when we leave a subtree we may - // apply a mask to it, but not to the parts outside the subtree. - // - The first time we see a new subtree under a target, we add that target to the top of the stack. This can happen as a layer representing itself, or as a target surface. - // - When we visit a target surface, we apply its mask to its subtree, which is at the top of the stack. - // - When we visit a layer representing itself, we add its occlusion to the current subtree, which is at the top of the stack. - // - When we visit a layer representing a contributing surface, the current target will never be the top of the stack since we just came from the contributing surface. - // We merge the occlusion at the top of the stack with the new current subtree. This new target is pushed onto the stack if not already there. - Vector<RenderSurfaceRegion> targetSurfaceStack; + CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), viewportSize())); + occlusionTracker.setUsePaintTracking(false); // FIXME: Remove this to turn on paint tracking for paint culling CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { if (it.representsTargetRenderSurface()) { ASSERT(it->renderSurface()->drawOpacity()); - enterTargetRenderSurface(targetSurfaceStack, it->renderSurface()); + occlusionTracker.finishedTargetRenderSurface(*it, it->renderSurface()); paintMaskAndReplicaForRenderSurface(*it, paintType); - // FIXME: add the replica layer to the current occlusion - - if (it->maskLayer() || it->renderSurface()->drawOpacity() < 1 || it->renderSurface()->filters().hasFilterThatAffectsOpacity()) - targetSurfaceStack.last().occludedInScreen = Region(); } else if (it.representsItself()) { ASSERT(!it->bounds().isEmpty()); - enterTargetRenderSurface(targetSurfaceStack, it->targetRenderSurface()); - paintContentsIfDirty(*it, paintType, targetSurfaceStack.last().occludedInScreen); - it->addSelfToOccludedScreenSpace(targetSurfaceStack.last().occludedInScreen); - } else { - leaveTargetRenderSurface(targetSurfaceStack, it.targetRenderSurfaceLayer()->renderSurface()); - } + occlusionTracker.enterTargetRenderSurface(it->targetRenderSurface()); + paintContentsIfDirty(*it, paintType, occlusionTracker.currentOcclusionInScreenSpace()); + occlusionTracker.markOccludedBehindLayer(*it); + } else + occlusionTracker.leaveToTargetRenderSurface(it.targetRenderSurfaceLayer()->renderSurface()); } } void CCLayerTreeHost::updateCompositorResources(GraphicsContext3D* context, CCTextureUpdater& updater) { // Use BackToFront since it's cheap and this isn't order-dependent. - typedef CCLayerIterator<LayerChromium, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; + typedef CCLayerIterator<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; CCLayerIteratorType end = CCLayerIteratorType::end(&m_updateList); for (CCLayerIteratorType it = CCLayerIteratorType::begin(&m_updateList); it != end; ++it) { @@ -647,4 +641,15 @@ void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> textur m_deleteTextureAfterCommitList.append(texture); } +void CCLayerTreeHost::setAnimationEventsRecursive(const CCAnimationEventsVector& events, LayerChromium* layer, double wallClockTime) +{ + for (size_t eventIndex = 0; eventIndex < events.size(); ++eventIndex) { + if (layer->id() == events[eventIndex]->layerId()) + layer->setAnimationEvent(*events[eventIndex], wallClockTime); + } + + for (size_t childIndex = 0; childIndex < layer->children().size(); ++childIndex) + setAnimationEventsRecursive(events, layer->children()[childIndex].get(), wallClockTime); } + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h index 1662f50c3..d5262262d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h @@ -55,8 +55,8 @@ public: virtual void updateAnimations(double frameBeginTime) = 0; virtual void layout() = 0; virtual void applyScrollAndScale(const IntSize& scrollDelta, float pageScale) = 0; - virtual PassRefPtr<GraphicsContext3D> createLayerTreeHostContext3D() = 0; - virtual void didRecreateGraphicsContext(bool success) = 0; + virtual PassRefPtr<GraphicsContext3D> createContext() = 0; + virtual void didRecreateContext(bool success) = 0; virtual void didCommitAndDrawFrame() = 0; virtual void didCompleteSwapBuffers() = 0; @@ -130,13 +130,21 @@ public: void beginCommitOnImplThread(CCLayerTreeHostImpl*); void finishCommitOnImplThread(CCLayerTreeHostImpl*); void commitComplete(); - PassRefPtr<GraphicsContext3D> createLayerTreeHostContext3D(); + PassRefPtr<GraphicsContext3D> createContext(); virtual PassOwnPtr<CCLayerTreeHostImpl> createLayerTreeHostImpl(CCLayerTreeHostImplClient*); void didBecomeInvisibleOnImplThread(CCLayerTreeHostImpl*); - void didRecreateGraphicsContext(bool success); + void didLoseContext(); + enum RecreateResult { + RecreateSucceeded, + RecreateFailedButTryAgain, + RecreateFailedAndGaveUp, + }; + RecreateResult recreateContext(); void didCommitAndDrawFrame() { m_client->didCommitAndDrawFrame(); } void didCompleteSwapBuffers() { m_client->didCompleteSwapBuffers(); } void deleteContentsTexturesOnImplThread(TextureAllocator*); + // Returns false if we should abort this frame due to initialization failure. + bool updateLayers(); CCLayerTreeHostClient* client() { return m_client; } @@ -145,6 +153,8 @@ public: // Only used when compositing on the main thread. void composite(); + // NOTE: The returned value can only be used to make GL calls or make the + // context current on the thread the compositor is running on! GraphicsContext3D* context(); // Composites and attempts to read back the result into the provided @@ -159,14 +169,14 @@ public: const LayerRendererCapabilities& layerRendererCapabilities() const; // Test only hook - void loseCompositorContext(int numTimes); + void loseContext(int numTimes); void setNeedsAnimate(); // virtual for testing virtual void setNeedsCommit(); void setNeedsRedraw(); - void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>); + void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime); LayerChromium* rootLayer() { return m_rootLayer.get(); } const LayerChromium* rootLayer() const { return m_rootLayer.get(); } @@ -185,9 +195,6 @@ public: bool visible() const { return m_visible; } void setVisible(bool); - // Returns false if we should abort this frame due to initialization failure. - bool updateLayers(); - void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec); void updateCompositorResources(GraphicsContext3D*, CCTextureUpdater&); @@ -218,6 +225,8 @@ private: void reserveTextures(); void clearPendingUpdate(); + void setAnimationEventsRecursive(const CCAnimationEventsVector&, LayerChromium*, double wallClockTime); + int m_compositorIdentifier; bool m_animating; @@ -228,6 +237,9 @@ private: OwnPtr<CCProxy> m_proxy; bool m_layerRendererInitialized; + bool m_contextLost; + int m_numTimesRecreateShouldFail; + int m_numFailedRecreateAttempts; RefPtr<LayerChromium> m_rootLayer; OwnPtr<TextureManager> m_contentsTextureManager; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp index 4fc869400..c86d74d86 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp @@ -149,11 +149,9 @@ static bool subtreeShouldRenderToSeparateSurface(LayerType* layer, bool axisAlig // Recursively walks the layer tree starting at the given node and computes all the // necessary transformations, clipRects, render surfaces, etc. -template<typename LayerType, typename RenderSurfaceType, typename LayerSorter> -static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, LayerType* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, RenderSurfaceType* nearestAncestorThatMovesPixels, Vector<RefPtr<LayerType> >& renderSurfaceLayerList, Vector<RefPtr<LayerType> >& layerList, LayerSorter* layerSorter, int maxTextureSize) +template<typename LayerType, typename LayerList, typename RenderSurfaceType, typename LayerSorter> +static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, LayerType* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, RenderSurfaceType* nearestAncestorThatMovesPixels, LayerList& renderSurfaceLayerList, LayerList& layerList, LayerSorter* layerSorter, int maxTextureSize) { - typedef Vector<RefPtr<LayerType> > LayerList; - // This function computes the new matrix transformations recursively for this // layer and all its descendants. It also computes the appropriate render surfaces. // Some important points to remember: @@ -390,7 +388,7 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer for (size_t i = 0; i < layer->children().size(); ++i) { LayerType* child = layer->children()[i].get(); - bool drawsContent = calculateDrawTransformsAndVisibilityInternal<LayerType, RenderSurfaceType, LayerSorter>(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, nearestAncestorThatMovesPixels, renderSurfaceLayerList, descendants, layerSorter, maxTextureSize); + bool drawsContent = calculateDrawTransformsAndVisibilityInternal<LayerType, LayerList, RenderSurfaceType, LayerSorter>(child, rootLayer, sublayerMatrix, nextHierarchyMatrix, nearestAncestorThatMovesPixels, renderSurfaceLayerList, descendants, layerSorter, maxTextureSize); if (drawsContent) { if (child->renderSurface()) { @@ -495,11 +493,11 @@ static bool calculateDrawTransformsAndVisibilityInternal(LayerType* layer, Layer // FIXME: Instead of using the following function to set visibility rects on a second // tree pass, revise calculateVisibleLayerRect() so that this can be done in a single // pass inside calculateDrawTransformsAndVisibilityInternal<>(). -template<typename LayerType, typename RenderSurfaceType> -static void walkLayersAndCalculateVisibleLayerRects(const Vector<RefPtr<LayerType> >& renderSurfaceLayerList) +template<typename LayerType, typename LayerList, typename RenderSurfaceType> +static void walkLayersAndCalculateVisibleLayerRects(const LayerList& renderSurfaceLayerList) { // Use BackToFront since it's cheap and this isn't order-dependent. - typedef CCLayerIterator<LayerType, RenderSurfaceType, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; + typedef CCLayerIterator<LayerType, LayerList, RenderSurfaceType, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { @@ -512,14 +510,14 @@ static void walkLayersAndCalculateVisibleLayerRects(const Vector<RefPtr<LayerTyp void CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(LayerChromium* layer, LayerChromium* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList, Vector<RefPtr<LayerChromium> >& layerList, int maxTextureSize) { - WebCore::calculateDrawTransformsAndVisibilityInternal<LayerChromium, RenderSurfaceChromium, void*>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, 0, renderSurfaceLayerList, layerList, 0, maxTextureSize); - walkLayersAndCalculateVisibleLayerRects<LayerChromium, RenderSurfaceChromium>(renderSurfaceLayerList); + WebCore::calculateDrawTransformsAndVisibilityInternal<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium, void>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, 0, renderSurfaceLayerList, layerList, 0, maxTextureSize); + walkLayersAndCalculateVisibleLayerRects<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium>(renderSurfaceLayerList); } -void CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(CCLayerImpl* layer, CCLayerImpl* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<CCLayerImpl> >& renderSurfaceLayerList, Vector<RefPtr<CCLayerImpl> >& layerList, CCLayerSorter* layerSorter, int maxTextureSize) +void CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(CCLayerImpl* layer, CCLayerImpl* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList, CCLayerSorter* layerSorter, int maxTextureSize) { - calculateDrawTransformsAndVisibilityInternal<CCLayerImpl, CCRenderSurface, CCLayerSorter>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, 0, renderSurfaceLayerList, layerList, layerSorter, maxTextureSize); - walkLayersAndCalculateVisibleLayerRects<CCLayerImpl, CCRenderSurface>(renderSurfaceLayerList); + calculateDrawTransformsAndVisibilityInternal<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerSorter>(layer, rootLayer, parentMatrix, fullHierarchyMatrix, 0, renderSurfaceLayerList, layerList, layerSorter, maxTextureSize); + walkLayersAndCalculateVisibleLayerRects<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface>(renderSurfaceLayerList); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h index 2e0cbcf2c..df23cd01f 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h @@ -43,7 +43,7 @@ public: template<typename LayerType> static IntRect calculateVisibleLayerRect(LayerType*); static void calculateDrawTransformsAndVisibility(LayerChromium*, LayerChromium* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList, Vector<RefPtr<LayerChromium> >& layerList, int maxTextureSize); - static void calculateDrawTransformsAndVisibility(CCLayerImpl*, CCLayerImpl* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<RefPtr<CCLayerImpl> >& renderSurfaceLayerList, Vector<RefPtr<CCLayerImpl> >& layerList, CCLayerSorter*, int maxTextureSize); + static void calculateDrawTransformsAndVisibility(CCLayerImpl*, CCLayerImpl* rootLayer, const TransformationMatrix& parentMatrix, const TransformationMatrix& fullHierarchyMatrix, Vector<CCLayerImpl*>& renderSurfaceLayerList, Vector<CCLayerImpl*>& layerList, CCLayerSorter*, int maxTextureSize); template<typename LayerType> static bool renderSurfaceContributesToTarget(LayerType*, int targetSurfaceLayerID); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp index d30c68c37..002e7826d 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp @@ -31,6 +31,7 @@ #include "LayerRendererChromium.h" #include "TraceEvent.h" #include "cc/CCDamageTracker.h" +#include "cc/CCDelayBasedTimeSource.h" #include "cc/CCLayerIterator.h" #include "cc/CCLayerTreeHost.h" #include "cc/CCLayerTreeHostCommon.h" @@ -39,8 +40,48 @@ #include "cc/CCThreadTask.h" #include <wtf/CurrentTime.h> +namespace { +const double lowFrequencyAnimationInterval = 1; +} // namespace + namespace WebCore { +class CCLayerTreeHostImplTimeSourceAdapter : public CCTimeSourceClient { + WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImplTimeSourceAdapter); +public: + static PassOwnPtr<CCLayerTreeHostImplTimeSourceAdapter> create(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource) + { + return adoptPtr(new CCLayerTreeHostImplTimeSourceAdapter(layerTreeHostImpl, timeSource)); + } + virtual ~CCLayerTreeHostImplTimeSourceAdapter() + { + m_timeSource->setClient(0); + m_timeSource->setActive(false); + } + + virtual void onTimerTick() + { + m_layerTreeHostImpl->animate(monotonicallyIncreasingTime(), currentTime()); + } + + void setActive(bool active) + { + if (active != m_timeSource->active()) + m_timeSource->setActive(active); + } + +private: + CCLayerTreeHostImplTimeSourceAdapter(CCLayerTreeHostImpl* layerTreeHostImpl, PassRefPtr<CCDelayBasedTimeSource> timeSource) + : m_layerTreeHostImpl(layerTreeHostImpl) + , m_timeSource(timeSource) + { + m_timeSource->setClient(this); + } + + CCLayerTreeHostImpl* m_layerTreeHostImpl; + RefPtr<CCDelayBasedTimeSource> m_timeSource; +}; + PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHostImpl::create(const CCSettings& settings, CCLayerTreeHostImplClient* client) { return adoptPtr(new CCLayerTreeHostImpl(settings, client)); @@ -50,6 +91,7 @@ CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCSettings& settings, CCLayerTree : m_client(client) , m_sourceFrameNumber(-1) , m_frameNumber(0) + , m_scrollLayerImpl(0) , m_settings(settings) , m_visible(true) , m_pageScale(1) @@ -59,6 +101,7 @@ CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCSettings& settings, CCLayerTree , m_maxPageScale(0) , m_needsAnimateLayers(false) , m_pinchGestureActive(false) + , m_timeSourceClientAdapter(CCLayerTreeHostImplTimeSourceAdapter::create(this, CCDelayBasedTimeSource::create(lowFrequencyAnimationInterval * 1000.0, CCProxy::currentThread()))) { ASSERT(CCProxy::isImplThread()); } @@ -96,13 +139,13 @@ GraphicsContext3D* CCLayerTreeHostImpl::context() return m_layerRenderer ? m_layerRenderer->context() : 0; } -void CCLayerTreeHostImpl::animate(double frameBeginTimeMs) +void CCLayerTreeHostImpl::animate(double monotonicTime, double wallClockTime) { - animatePageScale(frameBeginTimeMs); - animateLayers(frameBeginTimeMs); + animatePageScale(monotonicTime); + animateLayers(monotonicTime, wallClockTime); } -void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTimeMs, double durationMs) +void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration) { if (!m_scrollLayerImpl) return; @@ -113,15 +156,15 @@ void CCLayerTreeHostImpl::startPageScaleAnimation(const IntSize& targetPosition, IntSize scaledContentSize = contentSize(); scaledContentSize.scale(m_pageScaleDelta); - m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_viewportSize, scaledContentSize, startTimeMs); + m_pageScaleAnimation = CCPageScaleAnimation::create(scrollTotal, scaleTotal, m_viewportSize, scaledContentSize, startTime); if (anchorPoint) { IntSize windowAnchor(targetPosition); windowAnchor.scale(scaleTotal / pageScale); windowAnchor -= scrollTotal; - m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, durationMs); + m_pageScaleAnimation->zoomWithAnchor(windowAnchor, pageScale, duration); } else - m_pageScaleAnimation->zoomTo(targetPosition, pageScale, durationMs); + m_pageScaleAnimation->zoomTo(targetPosition, pageScale, duration); m_client->setNeedsRedrawOnImplThread(); m_client->setNeedsCommitOnImplThread(); @@ -134,7 +177,7 @@ void CCLayerTreeHostImpl::trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, // damage rect. The root damage rect is then used to scissor each surface. for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get(); + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); ASSERT(renderSurface); renderSurface->damageTracker()->updateDamageTrackingState(renderSurface->layerList(), renderSurfaceLayer->id(), renderSurfaceLayer->maskLayer()); @@ -198,7 +241,7 @@ void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLaye m_rootDamageRect = rootLayer()->renderSurface()->damageTracker()->currentDamageRect(); for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) { - CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get(); + CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex]; CCRenderSurface* renderSurface = renderSurfaceLayer->renderSurface(); OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface); @@ -210,7 +253,7 @@ void CCLayerTreeHostImpl::calculateRenderPasses(CCRenderPassList& passes, CCLaye const CCLayerList& layerList = renderSurface->layerList(); for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) { - CCLayerImpl* layer = layerList[layerIndex].get(); + CCLayerImpl* layer = layerList[layerIndex]; if (layer->visibleLayerRect().isEmpty()) continue; @@ -233,20 +276,27 @@ void CCLayerTreeHostImpl::optimizeRenderPasses(CCRenderPassList& passes) bool haveDamageRect = layerRendererCapabilities().usingPartialSwap; + // FIXME: compute overdraw metrics only occasionally, not every frame. + CCOverdrawCounts overdrawCounts; for (unsigned i = 0; i < passes.size(); ++i) { - FloatRect damageRect = passes[i]->targetSurface()->damageTracker()->currentDamageRect(); - passes[i]->optimizeQuads(haveDamageRect, damageRect); + FloatRect damageRect = passes[i]->surfaceDamageRect(); + passes[i]->optimizeQuads(haveDamageRect, damageRect, &overdrawCounts); } + + float normalization = 1000.f / (m_layerRenderer->viewportWidth() * m_layerRenderer->viewportHeight()); + PlatformSupport::histogramCustomCounts("Renderer4.pixelOverdrawOpaque", static_cast<int>(normalization * overdrawCounts.m_pixelsDrawnOpaque), 100, 1000000, 50); + PlatformSupport::histogramCustomCounts("Renderer4.pixelOverdrawTransparent", static_cast<int>(normalization * overdrawCounts.m_pixelsDrawnTransparent), 100, 1000000, 50); + PlatformSupport::histogramCustomCounts("Renderer4.pixelOverdrawCulled", static_cast<int>(normalization * overdrawCounts.m_pixelsCulled), 100, 1000000, 50); } -void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double frameBeginTimeSecs, CCAnimationEventsVector& events, bool& didAnimate, bool& needsAnimateLayers) +void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double monotonicTime, double wallClockTime, CCAnimationEventsVector& events, bool& didAnimate, bool& needsAnimateLayers) { bool subtreeNeedsAnimateLayers = false; CCLayerAnimationControllerImpl* currentController = current->layerAnimationController(); bool hadActiveAnimation = currentController->hasActiveAnimation(); - currentController->animate(frameBeginTimeSecs, events); + currentController->animate(monotonicTime, events); bool startedAnimation = events.size() > 0; // We animated if we either ticked a running animation, or started a new animation. @@ -259,7 +309,7 @@ void CCLayerTreeHostImpl::animateLayersRecursive(CCLayerImpl* current, double fr for (size_t i = 0; i < current->children().size(); ++i) { bool childNeedsAnimateLayers = false; - animateLayersRecursive(current->children()[i].get(), frameBeginTimeSecs, events, didAnimate, childNeedsAnimateLayers); + animateLayersRecursive(current->children()[i].get(), monotonicTime, wallClockTime, events, didAnimate, childNeedsAnimateLayers); if (childNeedsAnimateLayers) subtreeNeedsAnimateLayers = true; } @@ -294,7 +344,7 @@ void CCLayerTreeHostImpl::drawLayers() for (size_t i = 0; i < passes.size(); ++i) m_layerRenderer->drawRenderPass(passes[i].get()); - typedef CCLayerIterator<CCLayerImpl, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; + typedef CCLayerIterator<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface, CCLayerIteratorActions::BackToFront> CCLayerIteratorType; CCLayerIteratorType end = CCLayerIteratorType::end(&renderSurfaceLayerList); for (CCLayerIteratorType it = CCLayerIteratorType::begin(&renderSurfaceLayerList); it != end; ++it) { @@ -311,7 +361,8 @@ void CCLayerTreeHostImpl::drawLayers() void CCLayerTreeHostImpl::finishAllRendering() { - m_layerRenderer->finish(); + if (m_layerRenderer) + m_layerRenderer->finish(); } bool CCLayerTreeHostImpl::isContextLost() @@ -331,10 +382,15 @@ TextureAllocator* CCLayerTreeHostImpl::contentsTextureAllocator() const void CCLayerTreeHostImpl::swapBuffers() { - ASSERT(m_layerRenderer && !isContextLost()); + ASSERT(m_layerRenderer); m_layerRenderer->swapBuffers(enclosingIntRect(m_rootDamageRect)); } +void CCLayerTreeHostImpl::didLoseContext() +{ + m_client->didLoseContextOnImplThread(); +} + void CCLayerTreeHostImpl::onSwapBuffersComplete() { m_client->onSwapBuffersCompleteOnImplThread(); @@ -342,7 +398,7 @@ void CCLayerTreeHostImpl::onSwapBuffersComplete() void CCLayerTreeHostImpl::readback(void* pixels, const IntRect& rect) { - ASSERT(m_layerRenderer && !isContextLost()); + ASSERT(m_layerRenderer); m_layerRenderer->getFramebufferPixels(pixels, rect); } @@ -363,7 +419,7 @@ static CCLayerImpl* findScrollLayer(CCLayerImpl* layer) return 0; } -void CCLayerTreeHostImpl::setRootLayer(PassRefPtr<CCLayerImpl> layer) +void CCLayerTreeHostImpl::setRootLayer(PassOwnPtr<CCLayerImpl> layer) { m_rootLayerImpl = layer; @@ -377,8 +433,18 @@ void CCLayerTreeHostImpl::setVisible(bool visible) return; m_visible = visible; - if (m_layerRenderer) - m_layerRenderer->setVisible(visible); + if (!m_layerRenderer) + return; + + m_layerRenderer->setVisible(visible); + + // Reset the damage tracker because the front/back buffers may have been damaged by the GPU + // process on visibility change. + if (visible && m_layerRenderer->capabilities().usingPartialSwap) + setFullRootLayerDamage(); + + const bool shouldTickInBackground = !visible && m_needsAnimateLayers; + m_timeSourceClientAdapter->setActive(shouldTickInBackground); } bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<GraphicsContext3D> context) @@ -386,10 +452,16 @@ bool CCLayerTreeHostImpl::initializeLayerRenderer(PassRefPtr<GraphicsContext3D> OwnPtr<LayerRendererChromium> layerRenderer; layerRenderer = LayerRendererChromium::create(this, context); - if (m_layerRenderer) + if (m_layerRenderer) { m_layerRenderer->close(); + sendDidLoseContextRecursive(m_rootLayerImpl.get()); + } m_layerRenderer = layerRenderer.release(); + + if (!m_visible && m_layerRenderer) + m_layerRenderer->setVisible(m_visible); + return m_layerRenderer; } @@ -470,6 +542,10 @@ void CCLayerTreeHostImpl::updateMaxScrollPosition() return; FloatSize viewBounds = m_viewportSize; + if (CCLayerImpl* clipLayer = m_scrollLayerImpl->parent()) { + if (clipLayer->masksToBounds()) + viewBounds = clipLayer->bounds(); + } viewBounds.scale(1 / m_pageScaleDelta); IntSize maxScroll = contentSize() - expandedIntSize(viewBounds); @@ -487,7 +563,7 @@ void CCLayerTreeHostImpl::setNeedsRedraw() m_client->setNeedsRedrawOnImplThread(); } -CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& point, CCInputHandlerClient::ScrollInputType type) +CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoint& viewportPoint, CCInputHandlerClient::ScrollInputType type) { // TODO: Check for scrollable sublayers. if (!m_scrollLayerImpl || !m_scrollLayerImpl->scrollable()) { @@ -495,6 +571,17 @@ CCInputHandlerClient::ScrollStatus CCLayerTreeHostImpl::scrollBegin(const IntPoi return ScrollIgnored; } + if (m_scrollLayerImpl->shouldScrollOnMainThread()) { + TRACE_EVENT("scrollBegin Failed shouldScrollOnMainThread", this, 0); + return ScrollFailed; + } + + IntPoint scrollLayerContentPoint(m_scrollLayerImpl->screenSpaceTransform().inverse().mapPoint(viewportPoint)); + if (m_scrollLayerImpl->nonFastScrollableRegion().contains(scrollLayerContentPoint)) { + TRACE_EVENT("scrollBegin Failed nonFastScrollableRegion", this, 0); + return ScrollFailed; + } + if (type == CCInputHandlerClient::Wheel && m_scrollLayerImpl->haveWheelEventHandlers()) { TRACE_EVENT("scrollBegin Failed wheelEventHandlers", this, 0); return ScrollFailed; @@ -643,26 +730,26 @@ void CCLayerTreeHostImpl::setFullRootLayerDamage() } } -void CCLayerTreeHostImpl::animatePageScale(double frameBeginTimeMs) +void CCLayerTreeHostImpl::animatePageScale(double monotonicTime) { if (!m_pageScaleAnimation) return; IntSize scrollTotal = toSize(m_scrollLayerImpl->scrollPosition() + m_scrollLayerImpl->scrollDelta()); - setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(frameBeginTimeMs) / m_pageScale); - IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(frameBeginTimeMs); + setPageScaleDelta(m_pageScaleAnimation->pageScaleAtTime(monotonicTime) / m_pageScale); + IntSize nextScroll = m_pageScaleAnimation->scrollOffsetAtTime(monotonicTime); nextScroll.scale(1 / m_pageScaleDelta); m_scrollLayerImpl->scrollBy(nextScroll - scrollTotal); m_client->setNeedsRedrawOnImplThread(); - if (m_pageScaleAnimation->isAnimationCompleteAtTime(frameBeginTimeMs)) { + if (m_pageScaleAnimation->isAnimationCompleteAtTime(monotonicTime)) { m_pageScaleAnimation.clear(); m_client->setNeedsCommitOnImplThread(); } } -void CCLayerTreeHostImpl::animateLayers(double frameBeginTimeMs) +void CCLayerTreeHostImpl::animateLayers(double monotonicTime, double wallClockTime) { if (!m_settings.threadedAnimationEnabled || !m_needsAnimateLayers || !m_rootLayerImpl) return; @@ -672,13 +759,28 @@ void CCLayerTreeHostImpl::animateLayers(double frameBeginTimeMs) OwnPtr<CCAnimationEventsVector> events(adoptPtr(new CCAnimationEventsVector)); bool didAnimate = false; - animateLayersRecursive(m_rootLayerImpl.get(), frameBeginTimeMs / 1000, *events, didAnimate, m_needsAnimateLayers); + animateLayersRecursive(m_rootLayerImpl.get(), monotonicTime, wallClockTime, *events, didAnimate, m_needsAnimateLayers); if (!events->isEmpty()) - m_client->postAnimationEventsToMainThreadOnImplThread(events.release()); + m_client->postAnimationEventsToMainThreadOnImplThread(events.release(), wallClockTime); if (didAnimate) m_client->setNeedsRedrawOnImplThread(); + + const bool shouldTickInBackground = m_needsAnimateLayers && !m_visible; + m_timeSourceClientAdapter->setActive(shouldTickInBackground); +} + +void CCLayerTreeHostImpl::sendDidLoseContextRecursive(CCLayerImpl* current) +{ + if (!current) + return; + + current->didLoseContext(); + sendDidLoseContextRecursive(current->maskLayer()); + sendDidLoseContextRecursive(current->replicaLayer()); + for (size_t i = 0; i < current->children().size(); ++i) + sendDidLoseContextRecursive(current->children()[i].get()); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h index e438db0c4..1cfd0fb67 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h @@ -25,6 +25,7 @@ #ifndef CCLayerTreeHostImpl_h #define CCLayerTreeHostImpl_h +#include "LayerRendererChromium.h" #include "cc/CCAnimationEvents.h" #include "cc/CCInputHandler.h" #include "cc/CCLayerSorter.h" @@ -39,6 +40,7 @@ namespace WebCore { class CCCompletionEvent; class CCPageScaleAnimation; class CCLayerImpl; +class CCLayerTreeHostImplTimeSourceAdapter; class LayerRendererChromium; class TextureAllocator; struct LayerRendererCapabilities; @@ -47,14 +49,15 @@ class TransformationMatrix; // CCLayerTreeHost->CCProxy callback interface. class CCLayerTreeHostImplClient { public: + virtual void didLoseContextOnImplThread() = 0; virtual void onSwapBuffersCompleteOnImplThread() = 0; virtual void setNeedsRedrawOnImplThread() = 0; virtual void setNeedsCommitOnImplThread() = 0; - virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>) = 0; + virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime) = 0; }; // CCLayerTreeHostImpl owns the CCLayerImpl tree as well as associated rendering state -class CCLayerTreeHostImpl : public CCInputHandlerClient { +class CCLayerTreeHostImpl : public CCInputHandlerClient, LayerRendererChromiumClient { WTF_MAKE_NONCOPYABLE(CCLayerTreeHostImpl); public: static PassOwnPtr<CCLayerTreeHostImpl> create(const CCSettings&, CCLayerTreeHostImplClient*); @@ -68,14 +71,23 @@ public: virtual void pinchGestureBegin(); virtual void pinchGestureUpdate(float, const IntPoint&); virtual void pinchGestureEnd(); - virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTimeMs, double durationMs); + virtual void startPageScaleAnimation(const IntSize& targetPosition, bool anchorPoint, float pageScale, double startTime, double duration); // Virtual for testing. virtual void beginCommit(); virtual void commitComplete(); - virtual void animate(double frameDisplayTimeMs); + virtual void animate(double monotonicTime, double wallClockTime); virtual void drawLayers(); + // LayerRendererChromiumClient implementation + virtual const IntSize& viewportSize() const { return m_viewportSize; } + virtual const CCSettings& settings() const { return m_settings; } + virtual CCLayerImpl* rootLayer() { return m_rootLayerImpl.get(); } + virtual const CCLayerImpl* rootLayer() const { return m_rootLayerImpl.get(); } + virtual void didLoseContext(); + virtual void onSwapBuffersComplete(); + + // Implementation bool canDraw(); GraphicsContext3D* context(); @@ -89,14 +101,13 @@ public: TextureAllocator* contentsTextureAllocator() const; void swapBuffers(); - void onSwapBuffersComplete(); void readback(void* pixels, const IntRect&); - CCLayerImpl* rootLayer() const { return m_rootLayerImpl.get(); } - void setRootLayer(PassRefPtr<CCLayerImpl>); + void setRootLayer(PassOwnPtr<CCLayerImpl>); + PassOwnPtr<CCLayerImpl> releaseRootLayer() { return m_rootLayerImpl.release(); } - CCLayerImpl* scrollLayer() const { return m_scrollLayerImpl.get(); } + CCLayerImpl* scrollLayer() const { return m_scrollLayerImpl; } bool visible() const { return m_visible; } void setVisible(bool); @@ -105,13 +116,10 @@ public: void setSourceFrameNumber(int frameNumber) { m_sourceFrameNumber = frameNumber; } void setViewportSize(const IntSize&); - const IntSize& viewportSize() const { return m_viewportSize; } void setPageScaleFactorAndLimits(float pageScale, float minPageScale, float maxPageScale); float pageScale() const { return m_pageScale; } - const CCSettings& settings() const { return m_settings; } - PassOwnPtr<CCScrollAndScaleSet> processScrollDeltas(); // Where possible, redraws are scissored to a damage region calculated from changes to @@ -126,17 +134,17 @@ public: protected: CCLayerTreeHostImpl(const CCSettings&, CCLayerTreeHostImplClient*); - void animatePageScale(double frameBeginTimeMs); + void animatePageScale(double monotonicTime); // Virtual for testing. - virtual void animateLayers(double frameBeginTimeMs); + virtual void animateLayers(double monotonicTime, double wallClockTime); CCLayerTreeHostImplClient* m_client; int m_sourceFrameNumber; int m_frameNumber; private: - typedef Vector<RefPtr<CCLayerImpl> > CCLayerList; + typedef Vector<CCLayerImpl*> CCLayerList; void computeDoubleTapZoomDeltas(CCScrollAndScaleSet* scrollInfo); void computePinchZoomDeltas(CCScrollAndScaleSet* scrollInfo); @@ -149,12 +157,13 @@ private: void trackDamageForAllSurfaces(CCLayerImpl* rootDrawLayer, const CCLayerList& renderSurfaceLayerList); void calculateRenderPasses(CCRenderPassList&, CCLayerList& renderSurfaceLayerList); void optimizeRenderPasses(CCRenderPassList&); - void animateLayersRecursive(CCLayerImpl*, double frameBeginTimeSecs, CCAnimationEventsVector&, bool& didAnimate, bool& needsAnimateLayers); + void animateLayersRecursive(CCLayerImpl*, double monotonicTime, double wallClockTime, CCAnimationEventsVector&, bool& didAnimate, bool& needsAnimateLayers); IntSize contentSize() const; + void sendDidLoseContextRecursive(CCLayerImpl*); OwnPtr<LayerRendererChromium> m_layerRenderer; - RefPtr<CCLayerImpl> m_rootLayerImpl; - RefPtr<CCLayerImpl> m_scrollLayerImpl; + OwnPtr<CCLayerImpl> m_rootLayerImpl; + CCLayerImpl* m_scrollLayerImpl; CCSettings m_settings; IntSize m_viewportSize; bool m_visible; @@ -171,6 +180,9 @@ private: OwnPtr<CCPageScaleAnimation> m_pageScaleAnimation; + // This is used for ticking animations slowly when hidden. + OwnPtr<CCLayerTreeHostImplTimeSourceAdapter> m_timeSourceClientAdapter; + CCLayerSorter m_layerSorter; FloatRect m_rootDamageRect; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp index c5611ac27..f1c933882 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp @@ -39,6 +39,22 @@ using namespace std; namespace WebCore { template<typename LayerType, typename RenderSurfaceType> +CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace) + : m_scissorRectInScreenSpace(scissorRectInScreenSpace) + , m_surfaceDamageClient(0) + , m_usePaintTracking(true) // FIXME: Remove this when paint tracking is on for paint culling. +{ +} + +template<typename LayerType, typename RenderSurfaceType> +CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const DamageClientType* surfaceDamageClient) + : m_scissorRectInScreenSpace(scissorRectInScreenSpace) + , m_surfaceDamageClient(surfaceDamageClient) + , m_usePaintTracking(true) // FIXME: Remove this when paint tracking is on for paint culling. +{ +} + +template<typename LayerType, typename RenderSurfaceType> void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::enterTargetRenderSurface(const RenderSurfaceType* newTarget) { if (!m_stack.isEmpty() && m_stack.last().surface == newTarget) @@ -170,8 +186,9 @@ static inline TransformationMatrix contentToTargetSurfaceTransform(const LayerTy return transform; } +// FIXME: Remove usePaintTracking when paint tracking is on for paint culling. template<typename LayerType> -static inline Region computeOcclusionBehindLayer(const LayerType* layer, const TransformationMatrix& transform) +static inline Region computeOcclusionBehindLayer(const LayerType* layer, const TransformationMatrix& transform, bool usePaintTracking) { Region opaqueRegion; @@ -182,7 +199,14 @@ static inline Region computeOcclusionBehindLayer(const LayerType* layer, const T if (layer->opaque()) opaqueRegion = enclosedIntRect(unoccludedQuad.boundingBox()); - // FIXME: Capture opaque paints: else opaqueRegion = layer->opaqueContentsRegion(transform); + else if (usePaintTracking && transform.isIdentity()) + opaqueRegion = layer->opaqueContentsRegion(); + else if (usePaintTracking) { + Region contentRegion = layer->opaqueContentsRegion(); + Vector<IntRect> contentRects = contentRegion.rects(); + for (size_t i = 0; i < contentRects.size(); ++i) + opaqueRegion.unite(enclosedIntRect(transform.mapRect(FloatRect(contentRects[i])))); + } return opaqueRegion; } @@ -191,6 +215,8 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::markOccludedBehindLay { ASSERT(!m_stack.isEmpty()); ASSERT(layer->targetRenderSurface() == m_stack.last().surface); + if (m_stack.isEmpty()) + return; if (layer->drawOpacity() != 1) return; @@ -198,45 +224,31 @@ void CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::markOccludedBehindLay TransformationMatrix contentToScreenSpace = contentToScreenSpaceTransform<LayerType>(layer); TransformationMatrix contentToTargetSurface = contentToTargetSurfaceTransform<LayerType>(layer); - m_stack.last().occlusionInScreen.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToScreenSpace)); - m_stack.last().occlusionInTarget.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToTargetSurface)); + // FIXME: Remove m_usePaintTracking when paint tracking is on for paint culling. + m_stack.last().occlusionInScreen.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToScreenSpace, m_usePaintTracking)); + m_stack.last().occlusionInTarget.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToTargetSurface, m_usePaintTracking)); } -static inline bool testContentRectOccluded(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const Region& occlusion) +static inline bool testContentRectOccluded(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion) { - FloatQuad transformedQuad = contentSpaceTransform.mapQuad(FloatQuad(contentRect)); - return occlusion.contains(transformedQuad.enclosingBoundingBox()); + FloatRect transformedRect = contentSpaceTransform.mapRect(FloatRect(contentRect)); + // Take the enclosingIntRect, as we want to include partial pixels in the test. + IntRect targetRect = intersection(enclosingIntRect(transformedRect), scissorRect); + return targetRect.isEmpty() || occlusion.contains(targetRect); } template<typename LayerType, typename RenderSurfaceType> bool CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::occluded(const LayerType* layer, const IntRect& contentRect) const { + ASSERT(!m_stack.isEmpty()); if (m_stack.isEmpty()) return false; ASSERT(layer->targetRenderSurface() == m_stack.last().surface); - if (testContentRectOccluded(contentRect, contentToScreenSpaceTransform<LayerType>(layer), m_stack.last().occlusionInScreen)) + if (testContentRectOccluded(contentRect, contentToScreenSpaceTransform<LayerType>(layer), m_scissorRectInScreenSpace, m_stack.last().occlusionInScreen)) return true; - if (testContentRectOccluded(contentRect, contentToTargetSurfaceTransform<LayerType>(layer), m_stack.last().occlusionInTarget)) - return true; - return false; -} - -template<typename LayerType, typename RenderSurfaceType> -bool CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::surfaceOccluded(const LayerType* layer, const IntRect& surfaceContentRect) const -{ - // A surface is not occluded by layers drawing into itself, so we need to use occlusion from one spot down on the stack. - if (m_stack.size() < 2) - return false; - - ASSERT(layer->renderSurface()); - ASSERT(layer->renderSurface() == m_stack.last().surface); - - TransformationMatrix surfaceContentToScreenSpace = contentToScreenSpaceTransform<LayerType>(layer); - - const StackObject& secondLast = m_stack[m_stack.size()-2]; - if (testContentRectOccluded(surfaceContentRect, surfaceContentToScreenSpace, secondLast.occlusionInScreen)) + if (testContentRectOccluded(contentRect, contentToTargetSurfaceTransform<LayerType>(layer), layerScissorRectInTargetSurface(layer), m_stack.last().occlusionInTarget)) return true; return false; } @@ -256,22 +268,20 @@ static inline IntRect rectSubtractRegion(const IntRect& rect, const Region& regi return boundsRect; } -static IntRect computeUnoccludedContentRect(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const Region& occlusion) +static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion) { - FloatQuad transformedQuad = contentSpaceTransform.mapQuad(FloatQuad(contentRect)); - if (!transformedQuad.isRectilinear()) - return contentRect; - // Take the enclosingIntRect at each step here, as we want to contain any unoccluded partial pixels in the resulting IntRect. - IntRect shrunkRect = rectSubtractRegion(enclosingIntRect(transformedQuad.boundingBox()), occlusion); + FloatRect transformedRect = contentSpaceTransform.mapRect(FloatRect(contentRect)); + // Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect. + IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), scissorRect), occlusion); IntRect unoccludedRect = enclosingIntRect(contentSpaceTransform.inverse().mapRect(FloatRect(shrunkRect))); - // The use of enclosingIntRect, with floating point rounding, can give us a result that is not a sub-rect of contentRect, but our - // return value should be a sub-rect. + // The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds. return intersection(unoccludedRect, contentRect); } template<typename LayerType, typename RenderSurfaceType> IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContentRect(const LayerType* layer, const IntRect& contentRect) const { + ASSERT(!m_stack.isEmpty()); if (m_stack.isEmpty()) return contentRect; @@ -281,31 +291,24 @@ IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::unoccludedContentR TransformationMatrix contentToScreenSpace = contentToScreenSpaceTransform<LayerType>(layer); TransformationMatrix contentToTargetSurface = contentToTargetSurfaceTransform<LayerType>(layer); - IntRect unoccludedInScreen = computeUnoccludedContentRect(contentRect, contentToScreenSpace, m_stack.last().occlusionInScreen); - IntRect unoccludedInTarget = computeUnoccludedContentRect(contentRect, contentToTargetSurface, m_stack.last().occlusionInTarget); + IntRect unoccludedInScreen = computeUnoccludedContentRect(contentRect, contentToScreenSpace, m_scissorRectInScreenSpace, m_stack.last().occlusionInScreen); + if (unoccludedInScreen.isEmpty()) + return IntRect(); + IntRect unoccludedInTarget = computeUnoccludedContentRect(contentRect, contentToTargetSurface, layerScissorRectInTargetSurface(layer), m_stack.last().occlusionInTarget); return intersection(unoccludedInScreen, unoccludedInTarget); } template<typename LayerType, typename RenderSurfaceType> -IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::surfaceUnoccludedContentRect(const LayerType* layer, const IntRect& surfaceContentRect) const +IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerScissorRectInTargetSurface(const LayerType* layer) const { - // A surface is not occluded by layers drawing into itself, so we need to use occlusion from one spot down on the stack. - if (m_stack.size() < 2) - return surfaceContentRect; - - ASSERT(layer->renderSurface()); - ASSERT(layer->renderSurface() == m_stack.last().surface); - - // We want to return a rect that contains all the visible parts of |contentRect| in both screen space and in the target surface. - // So we find the visible parts of |contentRect| in each space, and take the intersection. - - TransformationMatrix contentToScreenSpace = contentToScreenSpaceTransform<LayerType>(layer); - - const StackObject& secondLast = m_stack[m_stack.size()-2]; - IntRect unoccludedInScreen = computeUnoccludedContentRect(surfaceContentRect, contentToScreenSpace, secondLast.occlusionInScreen); - - return unoccludedInScreen; + const RenderSurfaceType* targetSurface = m_stack.last().surface; + FloatRect totalScissor = targetSurface->contentRect(); + if (m_surfaceDamageClient) + totalScissor.intersect(m_surfaceDamageClient->damageRect(targetSurface)); + if (!layer->clipRect().isEmpty()) + totalScissor.intersect(layer->clipRect()); + return enclosingIntRect(totalScissor); } template<typename LayerType, typename RenderSurfaceType> @@ -324,27 +327,29 @@ const Region& CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::currentOcclu // Declare the possible functions here for the linker. +template CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace); +template CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const CCOcclusionTrackerDamageClient* surfaceDamageClient); template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::enterTargetRenderSurface(const RenderSurfaceChromium* newTarget); template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::finishedTargetRenderSurface(const LayerChromium* owningLayer, const RenderSurfaceChromium* finishedTarget); template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::leaveToTargetRenderSurface(const RenderSurfaceChromium* newTarget); template void CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::markOccludedBehindLayer(const LayerChromium*); template bool CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::occluded(const LayerChromium*, const IntRect& contentRect) const; -template bool CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::surfaceOccluded(const LayerChromium*, const IntRect& surfaceContentRect) const; template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::unoccludedContentRect(const LayerChromium*, const IntRect& contentRect) const; -template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::surfaceUnoccludedContentRect(const LayerChromium*, const IntRect& surfaceContentRect) const; template const Region& CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::currentOcclusionInScreenSpace() const; template const Region& CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::currentOcclusionInTargetSurface() const; +template IntRect CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium>::layerScissorRectInTargetSurface(const LayerChromium*) const; +template CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace); +template CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const CCOcclusionTrackerDamageClientImpl* surfaceDamageClient); template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::enterTargetRenderSurface(const CCRenderSurface* newTarget); template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::finishedTargetRenderSurface(const CCLayerImpl* owningLayer, const CCRenderSurface* finishedTarget); template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::leaveToTargetRenderSurface(const CCRenderSurface* newTarget); template void CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::markOccludedBehindLayer(const CCLayerImpl*); template bool CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::occluded(const CCLayerImpl*, const IntRect& contentRect) const; -template bool CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::surfaceOccluded(const CCLayerImpl*, const IntRect& surfaceContentRect) const; template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::unoccludedContentRect(const CCLayerImpl*, const IntRect& contentRect) const; -template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::surfaceUnoccludedContentRect(const CCLayerImpl*, const IntRect& surfaceContentRect) const; template const Region& CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::currentOcclusionInScreenSpace() const; template const Region& CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::currentOcclusionInTargetSurface() const; +template IntRect CCOcclusionTrackerBase<CCLayerImpl, CCRenderSurface>::layerScissorRectInTargetSurface(const CCLayerImpl*) const; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h index d1c833e1a..19fc2c1dd 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.h @@ -36,6 +36,15 @@ class CCRenderSurface; class LayerChromium; class RenderSurfaceChromium; +template<typename RenderSurfaceType> +class CCOcclusionTrackerDamageClientBase { +public: + virtual FloatRect damageRect(const RenderSurfaceType*) const = 0; +}; + +typedef CCOcclusionTrackerDamageClientBase<RenderSurfaceChromium> CCOcclusionTrackerDamageClient; +typedef CCOcclusionTrackerDamageClientBase<CCRenderSurface> CCOcclusionTrackerDamageClientImpl; + // This class is used to track occlusion of layers while traversing them in a front-to-back order. As each layer is visited, one of the // methods in this class is called to notify it about the current target surface. // Then, occlusion in the content space of the current layer may be queried, via methods such as occluded() and unoccludedContentRect(). @@ -43,8 +52,11 @@ class RenderSurfaceChromium; // Finally, once finished with the layer, occlusion behind the layer should be marked by calling markOccludedBehindLayer(). template<typename LayerType, typename RenderSurfaceType> class CCOcclusionTrackerBase { + WTF_MAKE_NONCOPYABLE(CCOcclusionTrackerBase); + typedef CCOcclusionTrackerDamageClientBase<RenderSurfaceType> DamageClientType; public: - CCOcclusionTrackerBase() { } + CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace); + CCOcclusionTrackerBase(IntRect scissorRectInScreenSpace, const DamageClientType*); // Called when visiting a layer representing itself. If the target was not already current, then this indicates we have entered a new surface subtree. void enterTargetRenderSurface(const RenderSurfaceType* newTarget); @@ -65,10 +77,8 @@ public: // Gives an unoccluded sub-rect of |contentRect| in the content space of the layer. Used when considering occlusion for a layer that paints/draws something. IntRect unoccludedContentRect(const LayerType*, const IntRect& contentRect) const; - // Returns true if the given rect in content space for the RenderSurface owned by the layer is fully occluded in either screen space or the layer's target surface. - bool surfaceOccluded(const LayerType*, const IntRect& contentRect) const; - // Gives an unoccluded sub-rect of |contentRect| in the content space of the RenderSurface owned by the layer. Used when considering occlusion for a target surface. - IntRect surfaceUnoccludedContentRect(const LayerType*, const IntRect& contentRect) const; + // FIXME: Remove this when paint tracking is on for paint culling. + void setUsePaintTracking(bool use) { m_usePaintTracking = use; } // FIXME: Remove these in future, they are to make CLs for transitioning to this easier. const Region& currentOcclusionInScreenSpace() const; @@ -90,8 +100,13 @@ protected: // We merge the occlusion at the top of the stack with the new current subtree. This new target is pushed onto the stack if not already there. Vector<StackObject, 1> m_stack; + // Allow tests to override this. + virtual IntRect layerScissorRectInTargetSurface(const LayerType*) const; + private: - WTF_MAKE_NONCOPYABLE(CCOcclusionTrackerBase); + IntRect m_scissorRectInScreenSpace; + const DamageClientType* m_surfaceDamageClient; + bool m_usePaintTracking; // FIXME: Remove this when paint tracking is on for paint culling. }; typedef CCOcclusionTrackerBase<LayerChromium, RenderSurfaceChromium> CCOcclusionTracker; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp index 33b6f22fb..49a125d23 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.cpp @@ -22,7 +22,7 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" @@ -36,13 +36,13 @@ namespace WebCore { -PassOwnPtr<CCPageScaleAnimation> CCPageScaleAnimation::create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTimeMs) +PassOwnPtr<CCPageScaleAnimation> CCPageScaleAnimation::create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime) { - return adoptPtr(new CCPageScaleAnimation(scrollStart, pageScaleStart, windowSize, contentSize, startTimeMs)); + return adoptPtr(new CCPageScaleAnimation(scrollStart, pageScaleStart, windowSize, contentSize, startTime)); } -CCPageScaleAnimation::CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTimeMs) +CCPageScaleAnimation::CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime) : m_scrollStart(scrollStart) , m_pageScaleStart(pageScaleStart) , m_windowSize(windowSize) @@ -50,11 +50,11 @@ CCPageScaleAnimation::CCPageScaleAnimation(const IntSize& scrollStart, float pag , m_anchorMode(false) , m_scrollEnd(scrollStart) , m_pageScaleEnd(pageScaleStart) - , m_startTimeMs(startTimeMs) + , m_startTime(startTime) { } -void CCPageScaleAnimation::zoomTo(const IntSize& finalScroll, float finalPageScale, double durationMs) +void CCPageScaleAnimation::zoomTo(const IntSize& finalScroll, float finalPageScale, double duration) { if (m_pageScaleStart != finalPageScale) { // For uniform-looking zooming, infer the anchor (point that remains in @@ -78,18 +78,18 @@ void CCPageScaleAnimation::zoomTo(const IntSize& finalScroll, float finalPageSca float ratioY = (startRect.y() - endRect.y()) / (endRect.height() - startRect.height()); IntSize anchor(m_windowSize.width() * ratioX, m_windowSize.height() * ratioY); - zoomWithAnchor(anchor, finalPageScale, durationMs); + zoomWithAnchor(anchor, finalPageScale, duration); } else { // If this is a pure translation, then there exists no anchor. Linearly // interpolate the scroll offset instead. m_scrollEnd = finalScroll; m_pageScaleEnd = finalPageScale; - m_durationMs = durationMs; + m_duration = duration; m_anchorMode = false; } } -void CCPageScaleAnimation::zoomWithAnchor(const IntSize& anchor, float finalPageScale, double durationMs) +void CCPageScaleAnimation::zoomWithAnchor(const IntSize& anchor, float finalPageScale, double duration) { m_scrollEnd = m_scrollStart + anchor; m_scrollEnd.scale(finalPageScale / m_pageScaleStart); @@ -103,31 +103,31 @@ void CCPageScaleAnimation::zoomWithAnchor(const IntSize& anchor, float finalPage m_anchor = anchor; m_pageScaleEnd = finalPageScale; - m_durationMs = durationMs; + m_duration = duration; m_anchorMode = true; } -IntSize CCPageScaleAnimation::scrollOffsetAtTime(double timeMs) const +IntSize CCPageScaleAnimation::scrollOffsetAtTime(double time) const { - return scrollOffsetAtRatio(progressRatioForTime(timeMs)); + return scrollOffsetAtRatio(progressRatioForTime(time)); } -float CCPageScaleAnimation::pageScaleAtTime(double timeMs) const +float CCPageScaleAnimation::pageScaleAtTime(double time) const { - return pageScaleAtRatio(progressRatioForTime(timeMs)); + return pageScaleAtRatio(progressRatioForTime(time)); } -bool CCPageScaleAnimation::isAnimationCompleteAtTime(double timeMs) const +bool CCPageScaleAnimation::isAnimationCompleteAtTime(double time) const { - return timeMs >= endTimeMs(); + return time >= endTime(); } -float CCPageScaleAnimation::progressRatioForTime(double timeMs) const +float CCPageScaleAnimation::progressRatioForTime(double time) const { - if (isAnimationCompleteAtTime(timeMs)) + if (isAnimationCompleteAtTime(time)) return 1; - return (timeMs - m_startTimeMs) / m_durationMs; + return (time - m_startTime) / m_duration; } IntSize CCPageScaleAnimation::scrollOffsetAtRatio(float ratio) const diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.h b/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.h index f4b1bf47a..d9acb4911 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPageScaleAnimation.h @@ -39,39 +39,39 @@ public: // Construct with the starting page scale and scroll offset (which is in // pageScaleStart space). The window size is the user-viewable area // in pixels. - static PassOwnPtr<CCPageScaleAnimation> create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTimeMs); + static PassOwnPtr<CCPageScaleAnimation> create(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime); // The following methods initialize the animation. Call one of them // immediately after construction to set the final scroll and page scale. // Zoom while explicitly specifying the top-left scroll position. The // scroll offset is in finalPageScale coordinates. - void zoomTo(const IntSize& finalScroll, float finalPageScale, double durationMs); + void zoomTo(const IntSize& finalScroll, float finalPageScale, double duration); // Zoom based on a specified onscreen anchor, which will remain at the same // position on the screen throughout the animation. The anchor is in local // space relative to scrollStart. - void zoomWithAnchor(const IntSize& anchor, float finalPageScale, double durationMs); + void zoomWithAnchor(const IntSize& anchor, float finalPageScale, double duration); // Call these functions while the animation is in progress to output the // current state. - IntSize scrollOffsetAtTime(double timeMs) const; - float pageScaleAtTime(double timeMs) const; - bool isAnimationCompleteAtTime(double timeMs) const; + IntSize scrollOffsetAtTime(double time) const; + float pageScaleAtTime(double time) const; + bool isAnimationCompleteAtTime(double time) const; // The following methods return state which is invariant throughout the // course of the animation. - double startTimeMs() const { return m_startTimeMs; } - double durationMs() const { return m_durationMs; } - double endTimeMs() const { return m_startTimeMs + m_durationMs; } + double startTime() const { return m_startTime; } + double duration() const { return m_duration; } + double endTime() const { return m_startTime + m_duration; } const IntSize& finalScrollOffset() const { return m_scrollEnd; } float finalPageScale() const { return m_pageScaleEnd; } protected: - CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTimeMs); + CCPageScaleAnimation(const IntSize& scrollStart, float pageScaleStart, const IntSize& windowSize, const IntSize& contentSize, double startTime); private: - float progressRatioForTime(double timeMs) const; + float progressRatioForTime(double time) const; IntSize scrollOffsetAtRatio(float ratio) const; float pageScaleAtRatio(float ratio) const; @@ -85,8 +85,8 @@ private: IntSize m_scrollEnd; float m_pageScaleEnd; - double m_startTimeMs; - double m_durationMs; + double m_startTime; + double m_duration; }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp index 5e4aca6d9..74538168e 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.cpp @@ -53,7 +53,9 @@ CCPluginLayerImpl::CCPluginLayerImpl(int id) CCPluginLayerImpl::~CCPluginLayerImpl() { - cleanupResources(); + // FIXME: it seems there is no layer renderer / GraphicsContext3D available here. Ideally we + // would like to delete m_ioSurfaceTextureId. + m_ioSurfaceTextureId = 0; } void CCPluginLayerImpl::willDraw(LayerRendererChromium* layerRenderer) @@ -101,6 +103,16 @@ void CCPluginLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const CCLayerImpl::dumpLayerProperties(ts, indent); } +void CCPluginLayerImpl::didLoseContext() +{ + if (m_ioSurfaceId) { + // We don't have a valid texture ID in the new context; however, + // the IOSurface is still valid. + m_ioSurfaceTextureId = 0; + m_ioSurfaceChanged = true; + } +} + void CCPluginLayerImpl::setIOSurfaceProperties(int width, int height, uint32_t ioSurfaceId) { if (m_ioSurfaceId != ioSurfaceId) @@ -111,13 +123,6 @@ void CCPluginLayerImpl::setIOSurfaceProperties(int width, int height, uint32_t i m_ioSurfaceId = ioSurfaceId; } -void CCPluginLayerImpl::cleanupResources() -{ - // FIXME: it seems there is no layer renderer / GraphicsContext3D available here. Ideally we - // would like to delete m_ioSurfaceTextureId. - m_ioSurfaceTextureId = 0; -} - } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h index 39a95951d..370e09d94 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCPluginLayerImpl.h @@ -35,9 +35,9 @@ namespace WebCore { class CCPluginLayerImpl : public CCLayerImpl { public: - static PassRefPtr<CCPluginLayerImpl> create(int id) + static PassOwnPtr<CCPluginLayerImpl> create(int id) { - return adoptRef(new CCPluginLayerImpl(id)); + return adoptPtr(new CCPluginLayerImpl(id)); } virtual ~CCPluginLayerImpl(); @@ -50,6 +50,7 @@ public: typedef ProgramBinding<VertexShaderPosTexTransform, FragmentShaderRGBATexRectFlipAlpha> TexRectProgramFlip; virtual void dumpLayerProperties(TextStream&, int indent) const; + virtual void didLoseContext(); void setTextureId(unsigned id) { m_textureId = id; } void setFlipped(bool flipped) { m_flipped = flipped; } @@ -61,8 +62,6 @@ private: virtual const char* layerTypeAsString() const { return "PluginLayer"; } - void cleanupResources(); - unsigned m_textureId; bool m_flipped; FloatRect m_uvRect; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.cpp index e4d601451..9ebb71dc7 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.cpp @@ -69,28 +69,38 @@ CCThread* CCProxy::implThread() return s_implThread; } +CCThread* CCProxy::currentThread() +{ + ThreadIdentifier currentThreadIdentifier = WTF::currentThread(); + if (s_mainThread && s_mainThread->threadID() == currentThreadIdentifier) + return s_mainThread; + if (s_implThread && s_implThread->threadID() == currentThreadIdentifier) + return s_implThread; + return 0; +} + #ifndef NDEBUG bool CCProxy::isMainThread() { ASSERT(s_mainThread); - if (implThreadIsOverridden && currentThread() == threadIDOverridenToBeImplThread) + if (implThreadIsOverridden && WTF::currentThread() == threadIDOverridenToBeImplThread) return false; - return currentThread() == s_mainThread->threadID(); + return WTF::currentThread() == s_mainThread->threadID(); } bool CCProxy::isImplThread() { WTF::ThreadIdentifier implThreadID = s_implThread ? s_implThread->threadID() : 0; - if (implThreadIsOverridden && currentThread() == threadIDOverridenToBeImplThread) + if (implThreadIsOverridden && WTF::currentThread() == threadIDOverridenToBeImplThread) return true; - return currentThread() == implThreadID; + return WTF::currentThread() == implThreadID; } void CCProxy::setCurrentThreadIsImplThread(bool isImplThread) { implThreadIsOverridden = isImplThread; if (isImplThread) - threadIDOverridenToBeImplThread = currentThread(); + threadIDOverridenToBeImplThread = WTF::currentThread(); } #endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h index b4358aadd..016226ca5 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCProxy.h @@ -53,6 +53,9 @@ public: static void setImplThread(CCThread*); static CCThread* implThread(); + // Returns 0 if the current thread is neither the main thread nor the impl thread. + static CCThread* currentThread(); + virtual ~CCProxy(); virtual bool compositeAndReadback(void *pixels, const IntRect&) = 0; @@ -70,6 +73,10 @@ public: // Attempts to initialize the layer renderer. Returns false if the context isn't usable for compositing. virtual bool initializeLayerRenderer() = 0; + // Attempts to recreate the context and layer renderer after a context lost. Returns false if the renderer couldn't be + // reinitialized. + virtual bool recreateContext() = 0; + virtual int compositorIdentifier() const = 0; virtual const LayerRendererCapabilities& layerRendererCapabilities() const = 0; @@ -95,7 +102,7 @@ public: virtual GraphicsContext3D* context() = 0; // Testing hooks - virtual void loseCompositorContext(int numTimes) = 0; + virtual void loseContext() = 0; #ifndef NDEBUG static void setCurrentThreadIsImplThread(bool); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp index 4f6435dc0..1c4a499cc 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp @@ -75,7 +75,22 @@ static IntRect rectSubtractRegion(const Region& region, const IntRect& rect) return rect; } -void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList, bool haveDamageRect, const FloatRect& damageRect) +static float wedgeProduct(const FloatPoint& p1, const FloatPoint& p2) +{ + return p1.x() * p2.y() - p1.y() * p2.x(); +} + +// Computes area of quads that are possibly non-rectangular. Can +// be easily extended to polygons. +static float quadArea(const FloatQuad& quad) +{ + return fabs(0.5 * (wedgeProduct(quad.p1(), quad.p2()) + + wedgeProduct(quad.p2(), quad.p3()) + + wedgeProduct(quad.p3(), quad.p4()) + + wedgeProduct(quad.p4(), quad.p1()))); +} + +void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList, bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts* overdrawMetrics) { if (!quadList.size()) return; @@ -96,21 +111,43 @@ void CCQuadCuller::cullOccludedQuads(CCQuadList& quadList, bool haveDamageRect, IntRect transformedVisibleQuadRect = rectSubtractRegion(opaqueCoverageThusFar, transformedQuadRect); bool keepQuad = !transformedVisibleQuadRect.isEmpty(); - if (!keepQuad) - continue; // See if we can reduce the number of pixels to draw by reducing the size of the draw // quad - we do this by changing its visible rect. - if (transformedVisibleQuadRect != transformedQuadRect && drawQuad->isLayerAxisAlignedIntRect()) - drawQuad->setQuadVisibleRect(drawQuad->quadTransform().inverse().mapRect(transformedVisibleQuadRect)); - - // When adding rect to opaque region, deflate it to stay conservative. - if (drawQuad->isLayerAxisAlignedIntRect() && !drawQuad->opaqueRect().isEmpty()) { - FloatRect floatOpaqueRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->opaqueRect())); - opaqueCoverageThusFar.unite(Region(enclosedIntRect(floatOpaqueRect))); + bool didReduceQuadSize = false; + if (keepQuad) { + if (transformedVisibleQuadRect != transformedQuadRect && drawQuad->isLayerAxisAlignedIntRect()) { + drawQuad->setQuadVisibleRect(drawQuad->quadTransform().inverse().mapRect(transformedVisibleQuadRect)); + didReduceQuadSize = true; + } + + // When adding rect to opaque region, deflate it to stay conservative. + if (drawQuad->isLayerAxisAlignedIntRect() && !drawQuad->opaqueRect().isEmpty()) { + FloatRect floatOpaqueRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->opaqueRect())); + opaqueCoverageThusFar.unite(Region(enclosedIntRect(floatOpaqueRect))); + } + + culledList.append(quadList[i].release()); } - culledList.append(quadList[i].release()); + if (overdrawMetrics) { + // We compute the area of the transformed quad, as this should be in pixels. + float area = quadArea(drawQuad->quadTransform().mapQuad(FloatQuad(drawQuad->quadRect()))); + if (keepQuad) { + if (didReduceQuadSize) { + float visibleQuadRectArea = quadArea(drawQuad->quadTransform().mapQuad(FloatQuad(drawQuad->quadVisibleRect()))); + overdrawMetrics->m_pixelsCulled += area - visibleQuadRectArea; + area = visibleQuadRectArea; + } + IntRect visibleOpaqueRect(drawQuad->quadVisibleRect()); + visibleOpaqueRect.intersect(drawQuad->opaqueRect()); + FloatQuad visibleOpaqueQuad = drawQuad->quadTransform().mapQuad(FloatQuad(visibleOpaqueRect)); + float opaqueArea = quadArea(visibleOpaqueQuad); + overdrawMetrics->m_pixelsDrawnOpaque += opaqueArea; + overdrawMetrics->m_pixelsDrawnTransparent += area - opaqueArea; + } else + overdrawMetrics->m_pixelsCulled += area; + } } quadList.clear(); // Release anything that remains. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h index 3cc315ec4..89582573b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.h @@ -32,7 +32,9 @@ namespace WebCore { class CCQuadCuller { public: - static void cullOccludedQuads(CCQuadList&, bool haveDamageRect, const FloatRect& damageRect); + // Passing 0 for CCOverdrawCounts* is valid, and disable the extra computation + // done to estimate over draw statistics. + static void cullOccludedQuads(CCQuadList&, bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts*); private: // Make non-instantiable. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp index da4b2222c..bd877ec30 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp @@ -65,9 +65,9 @@ void CCRenderPass::appendQuadsForRenderSurfaceLayer(CCLayerImpl* layer) m_sharedQuadStateList.append(sharedQuadState.release()); } -void CCRenderPass::optimizeQuads(bool haveDamageRect, const FloatRect& damageRect) +void CCRenderPass::optimizeQuads(bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts* overdraw) { - CCQuadCuller::cullOccludedQuads(m_quadList, haveDamageRect, damageRect); + CCQuadCuller::cullOccludedQuads(m_quadList, haveDamageRect, damageRect, overdraw); } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h index 11fbd4016..2affce541 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h @@ -38,6 +38,22 @@ class CCSharedQuadState; typedef Vector<OwnPtr<CCDrawQuad> > CCQuadList; +struct CCOverdrawCounts { + CCOverdrawCounts() + : m_pixelsDrawnOpaque(0) + , m_pixelsDrawnTransparent(0) + , m_pixelsCulled(0) + { + } + // Count of pixels that are opaque (and thus occlude). Ideally this is no more + // than wiewport width x height. + float m_pixelsDrawnOpaque; + // Count of pixels that are possibly transparent, and cannot occlude. + float m_pixelsDrawnTransparent; + // Count of pixels not drawn as they are occluded by somthing opaque. + float m_pixelsCulled; +}; + class CCRenderPass { WTF_MAKE_NONCOPYABLE(CCRenderPass); public: @@ -46,7 +62,8 @@ public: void appendQuadsForLayer(CCLayerImpl*); void appendQuadsForRenderSurfaceLayer(CCLayerImpl*); - void optimizeQuads(bool haveDamageRect, const FloatRect& damageRect); + // Passing in 0 for CCOverdrawCounts is valid, and disables performing overdraw calculations. + void optimizeQuads(bool haveDamageRect, const FloatRect& damageRect, CCOverdrawCounts*); const CCQuadList& quadList() const { return m_quadList; } CCRenderSurface* targetSurface() const { return m_targetSurface; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp index 169999808..25ac8fa9b 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp @@ -58,15 +58,6 @@ CCRenderSurface::CCRenderSurface(CCLayerImpl* owningLayer) CCRenderSurface::~CCRenderSurface() { - cleanupResources(); -} - -void CCRenderSurface::cleanupResources() -{ - if (!m_contentsTexture) - return; - - m_contentsTexture.clear(); } FloatRect CCRenderSurface::drawableContentRect() const @@ -216,7 +207,7 @@ void CCRenderSurface::drawSurface(LayerRendererChromium* layerRenderer, CCLayerI float edge[24]; layerQuad.toFloatArray(edge); deviceRect.toFloatArray(&edge[12]); - GLC(context3D, context3D->uniform3fv(shaderEdgeLocation, edge, 8)); + GLC(context3D, context3D->uniform3fv(shaderEdgeLocation, 8, edge)); } // Map device space quad to layer space. @@ -239,7 +230,7 @@ SkBitmap CCRenderSurface::applyFilters(LayerRendererChromium* layerRenderer) String CCRenderSurface::name() const { - return String::format("RenderSurface(id=%i,owner=%s)", m_owningLayer->id(), m_owningLayer->name().utf8().data()); + return String::format("RenderSurface(id=%i,owner=%s)", m_owningLayer->id(), m_owningLayer->debugName().utf8().data()); } static void writeIndent(TextStream& ts, int indent) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h index 1bcec9260..141ed2d24 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h @@ -55,7 +55,7 @@ public: bool prepareContentsTexture(LayerRendererChromium*); void releaseContentsTexture(); - void cleanupResources(); + void draw(LayerRendererChromium*, const FloatRect& surfaceDamageRect); String name() const; @@ -95,7 +95,7 @@ public: bool skipsDraw() const { return m_skipsDraw; } void clearLayerList() { m_layerList.clear(); } - Vector<RefPtr<CCLayerImpl> >& layerList() { return m_layerList; } + Vector<CCLayerImpl*>& layerList() { return m_layerList; } void setMaskLayer(CCLayerImpl* maskLayer) { m_maskLayer = maskLayer; } @@ -133,7 +133,7 @@ private: TransformationMatrix m_originTransform; FilterOperations m_filters; IntRect m_clipRect; - Vector<RefPtr<CCLayerImpl> > m_layerList; + Vector<CCLayerImpl*> m_layerList; // The nearest ancestor target surface that will contain the contents of this surface, and that is going // to move pixels within the surface (such as with a blur). This can point to itself. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp index 8580467f0..633f21d47 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.cpp @@ -86,10 +86,19 @@ void CCScheduler::didSwapBuffersComplete() m_frameRateController->didFinishFrame(); } -void CCScheduler::didSwapBuffersAbort() +void CCScheduler::didLoseContext() { - TRACE_EVENT("CCScheduler::didSwapBuffersAbort", this, 0); + TRACE_EVENT("CCScheduler::didLoseContext", this, 0); m_frameRateController->didAbortAllPendingFrames(); + m_stateMachine.didLoseContext(); + processScheduledActions(); +} + +void CCScheduler::didRecreateContext() +{ + TRACE_EVENT("CCScheduler::didRecreateContext", this, 0); + m_stateMachine.didRecreateContext(); + processScheduledActions(); } void CCScheduler::beginFrame() @@ -151,6 +160,9 @@ void CCScheduler::processScheduledActions() m_client->scheduledActionDrawAndSwap(); m_frameRateController->didBeginFrame(); break; + case CCSchedulerStateMachine::ACTION_BEGIN_CONTEXT_RECREATION: + m_client->scheduledActionBeginContextRecreation(); + break; } } while (action != CCSchedulerStateMachine::ACTION_NONE); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h index 7310581b1..f8ba21f99 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScheduler.h @@ -44,6 +44,7 @@ public: virtual void scheduledActionDrawAndSwap() = 0; virtual void scheduledActionUpdateMoreResources() = 0; virtual void scheduledActionCommit() = 0; + virtual void scheduledActionBeginContextRecreation() = 0; protected: virtual ~CCSchedulerClient() { } @@ -71,7 +72,9 @@ public: void setMaxFramesPending(int); void didSwapBuffersComplete(); - void didSwapBuffersAbort(); + + void didLoseContext(); + void didRecreateContext(); bool commitPending() const { return m_stateMachine.commitPending(); } bool redrawPending() const { return m_stateMachine.redrawPending(); } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp index d1aa5ccdc..054a4edd7 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.cpp @@ -38,27 +38,60 @@ CCSchedulerStateMachine::CCSchedulerStateMachine() , m_updateMoreResourcesPending(false) , m_insideVSync(false) , m_visible(false) - , m_canDraw(true) { } + , m_canDraw(true) + , m_contextState(CONTEXT_ACTIVE) +{ +} + +bool CCSchedulerStateMachine::hasDrawnThisFrame() const +{ + return m_currentFrameNumber == m_lastFrameNumberWhereDrawWasCalled; +} + +bool CCSchedulerStateMachine::shouldDraw() const +{ + if (m_needsForcedRedraw) + return true; + + if (!m_needsRedraw) + return false; + if (!m_insideVSync) + return false; + if (!m_visible) + return false; + if (hasDrawnThisFrame()) + return false; + if (!m_canDraw) + return false; + if (m_contextState != CONTEXT_ACTIVE) + return false; + return true; +} CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const { - bool canDraw = m_currentFrameNumber != m_lastFrameNumberWhereDrawWasCalled; - bool shouldDraw = (m_needsRedraw && m_insideVSync && m_visible && canDraw && m_canDraw) || m_needsForcedRedraw; + switch (m_commitState) { case COMMIT_STATE_IDLE: - if (shouldDraw) + if (m_contextState != CONTEXT_ACTIVE && m_needsForcedRedraw) + return ACTION_DRAW; + if (m_contextState == CONTEXT_LOST) + return ACTION_BEGIN_CONTEXT_RECREATION; + if (m_contextState == CONTEXT_RECREATING) + return ACTION_NONE; + if (shouldDraw()) return ACTION_DRAW; if (m_needsCommit && m_visible) return ACTION_BEGIN_FRAME; return ACTION_NONE; case COMMIT_STATE_FRAME_IN_PROGRESS: - if (shouldDraw) + if (shouldDraw()) return ACTION_DRAW; return ACTION_NONE; case COMMIT_STATE_UPDATING_RESOURCES: - if (shouldDraw) + if (shouldDraw()) return ACTION_DRAW; if (!m_updateMoreResourcesPending) return ACTION_BEGIN_UPDATE_MORE_RESOURCES; @@ -68,7 +101,7 @@ CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction() const return ACTION_COMMIT; case COMMIT_STATE_WAITING_FOR_FIRST_DRAW: - if (shouldDraw) + if (shouldDraw() || m_contextState == CONTEXT_LOST) return ACTION_DRAW; // COMMIT_STATE_WAITING_FOR_FIRST_DRAW wants to enforce a draw. If m_canDraw is false, // proceed to the next step (similar as in COMMIT_STATE_IDLE). @@ -115,12 +148,18 @@ void CCSchedulerStateMachine::updateState(Action action) m_commitState = COMMIT_STATE_IDLE; } return; + + case ACTION_BEGIN_CONTEXT_RECREATION: + ASSERT(m_commitState == COMMIT_STATE_IDLE); + ASSERT(m_contextState == CONTEXT_LOST); + m_contextState = CONTEXT_RECREATING; + return; } } bool CCSchedulerStateMachine::vsyncCallbackNeeded() const { - if (!m_visible) { + if (!m_visible || m_contextState != CONTEXT_ACTIVE) { if (m_needsForcedRedraw) return true; @@ -176,4 +215,18 @@ void CCSchedulerStateMachine::beginUpdateMoreResourcesComplete(bool morePending) m_commitState = COMMIT_STATE_READY_TO_COMMIT; } +void CCSchedulerStateMachine::didLoseContext() +{ + if (m_contextState == CONTEXT_LOST || m_contextState == CONTEXT_RECREATING) + return; + m_contextState = CONTEXT_LOST; +} + +void CCSchedulerStateMachine::didRecreateContext() +{ + ASSERT(m_contextState == CONTEXT_RECREATING); + m_contextState = CONTEXT_ACTIVE; + setNeedsCommit(); +} + } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h index 7de718846..22fcdf422 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSchedulerStateMachine.h @@ -51,6 +51,11 @@ public: COMMIT_STATE_WAITING_FOR_FIRST_DRAW, }; + enum ContextState { + CONTEXT_ACTIVE, + CONTEXT_LOST, + CONTEXT_RECREATING, + }; bool commitPending() const { return m_commitState != COMMIT_STATE_IDLE; @@ -64,6 +69,7 @@ public: ACTION_BEGIN_UPDATE_MORE_RESOURCES, ACTION_COMMIT, ACTION_DRAW, + ACTION_BEGIN_CONTEXT_RECREATION }; Action nextAction() const; void updateState(Action); @@ -107,7 +113,13 @@ public: // when such behavior would be undesirable. void setCanDraw(bool can) { m_canDraw = can; } + void didLoseContext(); + void didRecreateContext(); + protected: + bool shouldDraw() const; + bool hasDrawnThisFrame() const; + CommitState m_commitState; int m_currentFrameNumber; @@ -119,6 +131,7 @@ protected: bool m_insideVSync; bool m_visible; bool m_canDraw; + ContextState m_contextState; }; } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp new file mode 100644 index 000000000..872a35832 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.cpp @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2012 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: + * + * 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. + */ + +#include "config.h" + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCScrollbarLayerImpl.h" + +#include "CCTileDrawQuad.h" +#include "LayerRendererChromium.h" +#include "ManagedTexture.h" +#include "PlatformCanvas.h" +#include "ScrollbarTheme.h" + +namespace WebCore { + +PassOwnPtr<CCScrollbarLayerImpl> CCScrollbarLayerImpl::create(int id) +{ + return adoptPtr(new CCScrollbarLayerImpl(id)); +} + +CCScrollbarLayerImpl::CCScrollbarLayerImpl(int id) + : CCLayerImpl(id) + , m_scrollLayer(0) + , m_scrollbar(this) +{ +} + +void CCScrollbarLayerImpl::willDraw(LayerRendererChromium* layerRenderer) +{ + if (bounds().isEmpty() || contentBounds().isEmpty()) + return; + + if (!m_texture) + m_texture = ManagedTexture::create(layerRenderer->renderSurfaceTextureManager()); + + IntSize textureSize = contentBounds(); + if (!m_texture->reserve(textureSize, GraphicsContext3D::RGBA)) + return; + + PlatformCanvas canvas; + canvas.resize(textureSize); + { + PlatformCanvas::Painter painter(&canvas, PlatformCanvas::Painter::GrayscaleText); + paint(painter.context()); + } + + { + PlatformCanvas::AutoLocker locker(&canvas); + GraphicsContext3D* context = layerRenderer->context(); + m_texture->bindTexture(context, layerRenderer->renderSurfaceTextureAllocator()); + + // FIXME: Skia uses BGRA actually, we correct that with the swizzle pixel shader. + GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, m_texture->format(), canvas.size().width(), canvas.size().height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, locker.pixels())); + } +} + +void CCScrollbarLayerImpl::appendQuads(CCQuadList& quadList, const CCSharedQuadState* sharedQuadState) +{ + if (!m_texture->isReserved()) + return; + + IntRect quadRect(IntPoint(), bounds()); + quadList.append(CCTileDrawQuad::create(sharedQuadState, quadRect, quadRect, m_texture->textureId(), IntPoint(), m_texture->size(), GraphicsContext3D::NEAREST, true, true, true, true, true)); +} + +void CCScrollbarLayerImpl::didDraw() +{ + m_texture->unreserve(); +} + +void CCScrollbarLayerImpl::paint(GraphicsContext* context) +{ + ScrollbarTheme* theme = ScrollbarTheme::theme(); // FIXME: should make impl-side clone if needed + + context->clearRect(IntRect(IntPoint(), contentBounds())); + theme->paint(&m_scrollbar, context, IntRect(IntPoint(), contentBounds())); +} + + +int CCScrollbarLayerImpl::CCScrollbar::x() const +{ + return frameRect().x(); +} + +int CCScrollbarLayerImpl::CCScrollbar::y() const +{ + return frameRect().y(); +} + +int CCScrollbarLayerImpl::CCScrollbar::width() const +{ + return frameRect().width(); +} + +int CCScrollbarLayerImpl::CCScrollbar::height() const +{ + return frameRect().height(); +} + +IntSize CCScrollbarLayerImpl::CCScrollbar::size() const +{ + return frameRect().size(); +} + +IntPoint CCScrollbarLayerImpl::CCScrollbar::location() const +{ + return frameRect().location(); +} + +ScrollView* CCScrollbarLayerImpl::CCScrollbar::parent() const +{ + ASSERT_NOT_REACHED(); + return 0; +} + +ScrollView* CCScrollbarLayerImpl::CCScrollbar::root() const +{ + ASSERT_NOT_REACHED(); + return 0; +} + +void CCScrollbarLayerImpl::CCScrollbar::setFrameRect(const IntRect&) +{ + ASSERT_NOT_REACHED(); +} + +IntRect CCScrollbarLayerImpl::CCScrollbar::frameRect() const +{ + return IntRect(IntPoint(), m_owner->contentBounds()); +} + +void CCScrollbarLayerImpl::CCScrollbar::invalidate() +{ + invalidateRect(frameRect()); +} + +void CCScrollbarLayerImpl::CCScrollbar::invalidateRect(const IntRect&) +{ + ASSERT_NOT_REACHED(); +} + +ScrollbarOverlayStyle CCScrollbarLayerImpl::CCScrollbar::scrollbarOverlayStyle() const +{ + return m_owner->m_scrollbarOverlayStyle; +} + +void CCScrollbarLayerImpl::CCScrollbar::getTickmarks(Vector<IntRect>& tickmarks) const +{ + tickmarks = m_owner->m_tickmarks; +} + +bool CCScrollbarLayerImpl::CCScrollbar::isScrollableAreaActive() const +{ + return m_owner->m_isScrollableAreaActive; +} + +bool CCScrollbarLayerImpl::CCScrollbar::isScrollViewScrollbar() const +{ + return m_owner->m_isScrollViewScrollbar; +} + +IntPoint CCScrollbarLayerImpl::CCScrollbar::convertFromContainingWindow(const IntPoint& windowPoint) +{ + ASSERT_NOT_REACHED(); + return windowPoint; +} + +bool CCScrollbarLayerImpl::CCScrollbar::isCustomScrollbar() const +{ + return false; +} + +ScrollbarOrientation CCScrollbarLayerImpl::CCScrollbar::orientation() const +{ + return m_owner->m_orientation; +} + +int CCScrollbarLayerImpl::CCScrollbar::value() const +{ + if (!m_owner->m_scrollLayer) + return 0; + if (orientation() == HorizontalScrollbar) + return m_owner->m_scrollLayer->scrollPosition().x() + m_owner->m_scrollLayer->scrollDelta().width(); + return m_owner->m_scrollLayer->scrollPosition().y() + m_owner->m_scrollLayer->scrollDelta().height(); +} + +float CCScrollbarLayerImpl::CCScrollbar::currentPos() const +{ + return value(); +} + +int CCScrollbarLayerImpl::CCScrollbar::visibleSize() const +{ + return totalSize() - maximum(); +} + +int CCScrollbarLayerImpl::CCScrollbar::totalSize() const +{ + if (!m_owner->m_scrollLayer || !m_owner->m_scrollLayer->children().size()) + return 0; + // Copy & paste from CCLayerTreeHostImpl... + // FIXME: Hardcoding the first child here is weird. Think of + // a cleaner way to get the contentBounds on the Impl side. + if (orientation() == HorizontalScrollbar) + return m_owner->m_scrollLayer->children()[0]->contentBounds().width(); + return m_owner->m_scrollLayer->children()[0]->contentBounds().height(); +} + +int CCScrollbarLayerImpl::CCScrollbar::maximum() const +{ + if (!m_owner->m_scrollLayer) + return 0; + if (orientation() == HorizontalScrollbar) + return m_owner->m_scrollLayer->maxScrollPosition().width(); + return m_owner->m_scrollLayer->maxScrollPosition().height(); +} + +ScrollbarControlSize CCScrollbarLayerImpl::CCScrollbar::controlSize() const +{ + return m_owner->m_controlSize; +} + +int CCScrollbarLayerImpl::CCScrollbar::lineStep() const +{ + ASSERT_NOT_REACHED(); + return 0; +} + +int CCScrollbarLayerImpl::CCScrollbar::pageStep() const +{ + ASSERT_NOT_REACHED(); + return 0; +} + +ScrollbarPart CCScrollbarLayerImpl::CCScrollbar::pressedPart() const +{ + return m_owner->m_pressedPart; +} + +ScrollbarPart CCScrollbarLayerImpl::CCScrollbar::hoveredPart() const +{ + return m_owner->m_hoveredPart; +} + +void CCScrollbarLayerImpl::CCScrollbar::styleChanged() +{ +} + +bool CCScrollbarLayerImpl::CCScrollbar::enabled() const +{ + return m_owner->m_enabled; +} + +void CCScrollbarLayerImpl::CCScrollbar::setEnabled(bool) +{ + ASSERT_NOT_REACHED(); +} + +} +#endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h new file mode 100644 index 000000000..f6f005360 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCScrollbarLayerImpl.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2012 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: + * + * 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. + */ + +#ifndef CCScrollbarLayerImpl_h +#define CCScrollbarLayerImpl_h + +#if USE(ACCELERATED_COMPOSITING) + +#include "CCLayerImpl.h" +#include "ManagedTexture.h" +#include "ScrollbarThemeClient.h" + +namespace WebCore { + +class GraphicsContext; +class ScrollView; + +class CCScrollbarLayerImpl : public CCLayerImpl { +public: + static PassOwnPtr<CCScrollbarLayerImpl> create(int id); + + void setScrollbarOverlayStyle(ScrollbarOverlayStyle scrollbarOverlayStyle) { m_scrollbarOverlayStyle = scrollbarOverlayStyle; } + void setTickmarks(const Vector<IntRect>& tickmarks) { m_tickmarks = tickmarks; } + void setIsScrollableAreaActive(bool isScrollableAreaActive) { m_isScrollableAreaActive = isScrollableAreaActive; } + void setIsScrollViewScrollbar(bool isScrollViewScrollbar) { m_isScrollViewScrollbar = isScrollViewScrollbar; } + + void setOrientation(ScrollbarOrientation orientation) { m_orientation = orientation; } + + void setControlSize(ScrollbarControlSize controlSize) { m_controlSize = controlSize; } + + void setPressedPart(ScrollbarPart pressedPart) { m_pressedPart = pressedPart; } + void setHoveredPart(ScrollbarPart hoveredPart) { m_hoveredPart = hoveredPart; } + + void setEnabled(bool enabled) { m_enabled = enabled; } + + + CCLayerImpl* scrollLayer() const { return m_scrollLayer; } + void setScrollLayer(CCLayerImpl* scrollLayer) { m_scrollLayer = scrollLayer; } + + virtual void willDraw(LayerRendererChromium*); + virtual void appendQuads(CCQuadList&, const CCSharedQuadState*); + virtual void didDraw(); + +protected: + explicit CCScrollbarLayerImpl(int id); + +private: + void paint(GraphicsContext*); + + CCLayerImpl* m_scrollLayer; + OwnPtr<ManagedTexture> m_texture; + + // nested class only to avoid namespace problem + class CCScrollbar : public ScrollbarThemeClient { + public: + explicit CCScrollbar(CCScrollbarLayerImpl* owner) : m_owner(owner) { } + + // ScrollbarThemeClient implementation + virtual int x() const; + virtual int y() const; + virtual int width() const; + virtual int height() const; + virtual IntSize size() const; + virtual IntPoint location() const; + + virtual ScrollView* parent() const; + virtual ScrollView* root() const; + + virtual void setFrameRect(const IntRect&); + virtual IntRect frameRect() const; + + virtual void invalidate(); + virtual void invalidateRect(const IntRect&); + + virtual ScrollbarOverlayStyle scrollbarOverlayStyle() const; + virtual void getTickmarks(Vector<IntRect>&) const; + virtual bool isScrollableAreaActive() const; + virtual bool isScrollViewScrollbar() const; + + virtual IntPoint convertFromContainingWindow(const IntPoint& windowPoint); + + virtual bool isCustomScrollbar() const; + virtual ScrollbarOrientation orientation() const; + + virtual int value() const; + virtual float currentPos() const; + virtual int visibleSize() const; + virtual int totalSize() const; + virtual int maximum() const; + virtual ScrollbarControlSize controlSize() const; + + virtual int lineStep() const; + virtual int pageStep() const; + + virtual ScrollbarPart pressedPart() const; + virtual ScrollbarPart hoveredPart() const; + + virtual void styleChanged(); + + virtual bool enabled() const; + virtual void setEnabled(bool); + + private: + CCScrollbarLayerImpl* m_owner; + + }; + CCScrollbar m_scrollbar; + + ScrollbarOverlayStyle m_scrollbarOverlayStyle; + Vector<IntRect> m_tickmarks; + bool m_isScrollableAreaActive; + bool m_isScrollViewScrollbar; + + ScrollbarOrientation m_orientation; + + ScrollbarControlSize m_controlSize; + + ScrollbarPart m_pressedPart; + ScrollbarPart m_hoveredPart; + + bool m_enabled; +}; + +} +#endif // USE(ACCELERATED_COMPOSITING) + +#endif diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp index ea8c40f12..b6fc76b52 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp @@ -45,11 +45,9 @@ PassOwnPtr<CCProxy> CCSingleThreadProxy::create(CCLayerTreeHost* layerTreeHost) CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost) : m_layerTreeHost(layerTreeHost) + , m_contextLost(false) , m_compositorIdentifier(-1) , m_layerRendererInitialized(false) - , m_numFailedRecreateAttempts(0) - , m_graphicsContextLost(false) - , m_timesRecreateShouldFail(0) , m_nextFrameIsNewlyCommittedFrame(false) { TRACE_EVENT("CCSingleThreadProxy::CCSingleThreadProxy", this, 0); @@ -74,11 +72,6 @@ bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect TRACE_EVENT("CCSingleThreadProxy::compositeAndReadback", this, 0); ASSERT(CCProxy::isMainThread()); - if (!recreateContextIfNeeded()) { - TRACE_EVENT("compositeAndReadback_EarlyOut_ContextLost", this, 0); - return false; - } - if (!commitIfNeeded()) return false; @@ -90,12 +83,15 @@ bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect if (m_layerTreeHostImpl->isContextLost()) return false; + m_layerTreeHostImpl->swapBuffers(); + didSwapFrame(); + return true; } -void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) +void CCSingleThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) { - m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime() * 1000.0, durationSec * 1000.0); + m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration); } GraphicsContext3D* CCSingleThreadProxy::context() @@ -125,7 +121,7 @@ bool CCSingleThreadProxy::isStarted() const bool CCSingleThreadProxy::initializeContext() { ASSERT(CCProxy::isMainThread()); - RefPtr<GraphicsContext3D> context = m_layerTreeHost->createLayerTreeHostContext3D(); + RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext(); if (!context) return false; ASSERT(context->hasOneRef()); @@ -148,6 +144,33 @@ bool CCSingleThreadProxy::initializeLayerRenderer() } } +bool CCSingleThreadProxy::recreateContext() +{ + TRACE_EVENT0("cc", "CCSingleThreadProxy::recreateContext"); + ASSERT(CCProxy::isMainThread()); + ASSERT(m_contextLost); + + RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext(); + if (!context) + return false; + + ASSERT(context->hasOneRef()); + bool initialized; + { + DebugScopedSetImplThread impl; + m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator()); + initialized = m_layerTreeHostImpl->initializeLayerRenderer(context); + if (initialized) { + m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities(); + } + } + + if (initialized) + m_contextLost = false; + + return initialized; +} + const LayerRendererCapabilities& CCSingleThreadProxy::layerRendererCapabilities() const { ASSERT(m_layerRendererInitialized); @@ -155,10 +178,11 @@ const LayerRendererCapabilities& CCSingleThreadProxy::layerRendererCapabilities( return m_layerRendererCapabilitiesForMainThread; } -void CCSingleThreadProxy::loseCompositorContext(int numTimes) +void CCSingleThreadProxy::loseContext() { - m_graphicsContextLost = true; - m_timesRecreateShouldFail = numTimes - 1; + ASSERT(CCProxy::isMainThread()); + m_layerTreeHost->didLoseContext(); + m_contextLost = true; } void CCSingleThreadProxy::setNeedsAnimate() @@ -212,12 +236,14 @@ void CCSingleThreadProxy::setNeedsRedraw() void CCSingleThreadProxy::setVisible(bool visible) { + m_layerTreeHostImpl->setVisible(visible); + if (!visible) { DebugScopedSetImplThread impl; m_layerTreeHost->didBecomeInvisibleOnImplThread(m_layerTreeHostImpl.get()); - m_layerTreeHostImpl->setVisible(false); return; } + setNeedsCommit(); } @@ -233,72 +259,23 @@ void CCSingleThreadProxy::stop() m_layerTreeHost = 0; } -void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events) +void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime) { ASSERT(CCProxy::isImplThread()); DebugScopedSetMainThread main; - m_layerTreeHost->setAnimationEvents(events); + m_layerTreeHost->setAnimationEvents(events, wallClockTime); } // Called by the legacy scheduling path (e.g. where render_widget does the scheduling) void CCSingleThreadProxy::compositeImmediately() { - if (!recreateContextIfNeeded()) - return; - if (!commitIfNeeded()) return; - if (doComposite()) + if (doComposite()) { m_layerTreeHostImpl->swapBuffers(); -} - -bool CCSingleThreadProxy::recreateContextIfNeeded() -{ - ASSERT(CCProxy::isMainThread()); - - if (!m_graphicsContextLost && m_layerTreeHostImpl->isContextLost()) { - m_graphicsContextLost = true; - m_numFailedRecreateAttempts = 0; - } - - if (!m_graphicsContextLost) - return true; - RefPtr<GraphicsContext3D> context; - if (!m_timesRecreateShouldFail) - context = m_layerTreeHost->createLayerTreeHostContext3D(); - else - m_timesRecreateShouldFail--; - - if (context) { - ASSERT(context->hasOneRef()); - bool ok; - { - DebugScopedSetImplThread impl; - m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator()); - ok = m_layerTreeHostImpl->initializeLayerRenderer(context); - if (ok) - m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities(); - } - if (ok) { - m_layerTreeHost->didRecreateGraphicsContext(true); - m_graphicsContextLost = false; - return true; - } + didSwapFrame(); } - - // Tolerate a certain number of recreation failures to work around races - // in the context-lost machinery. - m_numFailedRecreateAttempts++; - if (m_numFailedRecreateAttempts < 5) { - setNeedsCommit(); - return false; - } - - // We have tried too many times to recreate the context. Tell the host to fall - // back to software rendering. - m_layerTreeHost->didRecreateGraphicsContext(false); - return false; } bool CCSingleThreadProxy::commitIfNeeded() @@ -314,34 +291,31 @@ bool CCSingleThreadProxy::commitIfNeeded() bool CCSingleThreadProxy::doComposite() { - ASSERT(!m_graphicsContextLost); - + ASSERT(!m_contextLost); { DebugScopedSetImplThread impl; - double frameDisplayTimeMs = monotonicallyIncreasingTime() * 1000.0; - m_layerTreeHostImpl->animate(frameDisplayTimeMs); + double monotonicTime = monotonicallyIncreasingTime(); + double wallClockTime = currentTime(); + + m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); m_layerTreeHostImpl->drawLayers(); } if (m_layerTreeHostImpl->isContextLost()) { - // Trying to recover the context right here will not work if GPU process - // died. This is because GpuChannelHost::OnErrorMessage will only be - // called at the next iteration of the message loop, reverting our - // recovery attempts here. Instead, we detach the root layer from the - // renderer, recreate the renderer at the next message loop iteration - // and request a repaint yet again. - m_graphicsContextLost = true; - m_numFailedRecreateAttempts = 0; - setNeedsCommit(); + m_contextLost = true; + m_layerTreeHost->didLoseContext(); return false; } + return true; +} + +void CCSingleThreadProxy::didSwapFrame() +{ if (m_nextFrameIsNewlyCommittedFrame) { m_nextFrameIsNewlyCommittedFrame = false; m_layerTreeHost->didCommitAndDrawFrame(); } - - return true; } } diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h index 71b5e99b2..ebbd96e2c 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.h @@ -43,15 +43,16 @@ public: // CCProxy implementation virtual bool compositeAndReadback(void *pixels, const IntRect&); - virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec); + virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration); virtual GraphicsContext3D* context(); virtual void finishAllRendering(); virtual bool isStarted() const; virtual bool initializeContext(); virtual bool initializeLayerRenderer(); + virtual bool recreateContext(); virtual int compositorIdentifier() const { return m_compositorIdentifier; } virtual const LayerRendererCapabilities& layerRendererCapabilities() const; - virtual void loseCompositorContext(int numTimes); + virtual void loseContext(); virtual void setNeedsAnimate(); virtual void setNeedsCommit(); virtual void setNeedsRedraw(); @@ -61,23 +62,26 @@ public: virtual size_t maxPartialTextureUpdates() const { return std::numeric_limits<size_t>::max(); } // CCLayerTreeHostImplClient implementation + virtual void didLoseContextOnImplThread() { } virtual void onSwapBuffersCompleteOnImplThread() { ASSERT_NOT_REACHED(); } virtual void setNeedsRedrawOnImplThread() { m_layerTreeHost->setNeedsCommit(); } virtual void setNeedsCommitOnImplThread() { m_layerTreeHost->setNeedsCommit(); } - virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>); + virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime); // Called by the legacy path where RenderWidget does the scheduling. void compositeImmediately(); private: explicit CCSingleThreadProxy(CCLayerTreeHost*); - bool recreateContextIfNeeded(); + bool commitIfNeeded(); void doCommit(); bool doComposite(); + void didSwapFrame(); // Accessed on main thread only. CCLayerTreeHost* m_layerTreeHost; + bool m_contextLost; int m_compositorIdentifier; // Holds on to the context between initializeContext() and initializeLayerRenderer() calls. Shouldn't @@ -89,9 +93,6 @@ private: bool m_layerRendererInitialized; LayerRendererCapabilities m_layerRendererCapabilitiesForMainThread; - int m_numFailedRecreateAttempts; - bool m_graphicsContextLost; - int m_timesRecreateShouldFail; // Used during testing. bool m_nextFrameIsNewlyCommittedFrame; }; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h index c7edc18b2..2e7441666 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCSolidColorLayerImpl.h @@ -35,9 +35,9 @@ class LayerRendererChromium; class CCSolidColorLayerImpl : public CCLayerImpl { public: - static PassRefPtr<CCSolidColorLayerImpl> create(int id) + static PassOwnPtr<CCSolidColorLayerImpl> create(int id) { - return adoptRef(new CCSolidColorLayerImpl(id)); + return adoptPtr(new CCSolidColorLayerImpl(id)); } virtual ~CCSolidColorLayerImpl(); diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp index 75ef13623..8454e21ff 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp @@ -59,6 +59,7 @@ PassOwnPtr<CCProxy> CCThreadProxy::create(CCLayerTreeHost* layerTreeHost) CCThreadProxy::CCThreadProxy(CCLayerTreeHost* layerTreeHost) : m_animateRequested(false) , m_commitRequested(false) + , m_contextLost(false) , m_layerTreeHost(layerTreeHost) , m_compositorIdentifier(-1) , m_layerRendererInitialized(false) @@ -133,17 +134,17 @@ void CCThreadProxy::requestReadbackOnImplThread(ReadbackRequest* request) m_schedulerOnImplThread->setNeedsForcedRedraw(); } -void CCThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec) +void CCThreadProxy::startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration) { ASSERT(CCProxy::isMainThread()); - CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestStartPageScaleAnimationOnImplThread, targetPosition, useAnchor, scale, durationSec)); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::requestStartPageScaleAnimationOnImplThread, targetPosition, useAnchor, scale, duration)); } -void CCThreadProxy::requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double durationSec) +void CCThreadProxy::requestStartPageScaleAnimationOnImplThread(IntSize targetPosition, bool useAnchor, float scale, double duration) { ASSERT(CCProxy::isImplThread()); if (m_layerTreeHostImpl) - m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime() * 1000.0, durationSec * 1000.0); + m_layerTreeHostImpl->startPageScaleAnimation(targetPosition, useAnchor, scale, monotonicallyIncreasingTime(), duration); } GraphicsContext3D* CCThreadProxy::context() @@ -170,7 +171,7 @@ bool CCThreadProxy::isStarted() const bool CCThreadProxy::initializeContext() { TRACE_EVENT("CCThreadProxy::initializeContext", this, 0); - RefPtr<GraphicsContext3D> context = m_layerTreeHost->createLayerTreeHostContext3D(); + RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext(); if (!context) return false; ASSERT(context->hasOneRef()); @@ -193,9 +194,9 @@ bool CCThreadProxy::initializeLayerRenderer() bool initializeSucceeded = false; LayerRendererCapabilities capabilities; CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::initializeLayerRendererOnImplThread, - AllowCrossThreadAccess(&completion), - AllowCrossThreadAccess(&initializeSucceeded), - AllowCrossThreadAccess(&capabilities))); + AllowCrossThreadAccess(&completion), + AllowCrossThreadAccess(&initializeSucceeded), + AllowCrossThreadAccess(&capabilities))); completion.wait(); if (initializeSucceeded) { @@ -205,6 +206,39 @@ bool CCThreadProxy::initializeLayerRenderer() return initializeSucceeded; } +bool CCThreadProxy::recreateContext() +{ + TRACE_EVENT0("cc", "CCThreadProxy::recreateContext"); + ASSERT(isMainThread()); + + // Try to create the context. + RefPtr<GraphicsContext3D> context = m_layerTreeHost->createContext(); + if (!context) + return false; + ASSERT(context->hasOneRef()); + + // Leak the context pointer so we can transfer ownership of it to the other side... + GraphicsContext3D* contextPtr = context.release().leakRef(); + ASSERT(contextPtr->hasOneRef()); + + // Make a blocking call to recreateContextOnImplThread. The results of that + // call are pushed into the recreateSucceeded and capabilities local + // variables. + CCCompletionEvent completion; + bool recreateSucceeded = false; + LayerRendererCapabilities capabilities; + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::recreateContextOnImplThread, + AllowCrossThreadAccess(&completion), + AllowCrossThreadAccess(contextPtr), + AllowCrossThreadAccess(&recreateSucceeded), + AllowCrossThreadAccess(&capabilities))); + completion.wait(); + + if (recreateSucceeded) + m_layerRendererCapabilitiesMainThreadCopy = capabilities; + return recreateSucceeded; +} + int CCThreadProxy::compositorIdentifier() const { ASSERT(isMainThread()); @@ -217,9 +251,9 @@ const LayerRendererCapabilities& CCThreadProxy::layerRendererCapabilities() cons return m_layerRendererCapabilitiesMainThreadCopy; } -void CCThreadProxy::loseCompositorContext(int numTimes) +void CCThreadProxy::loseContext() { - ASSERT_NOT_REACHED(); + CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::didLoseContextOnImplThread)); } void CCThreadProxy::setNeedsAnimate() @@ -244,6 +278,13 @@ void CCThreadProxy::setNeedsCommit() CCProxy::implThread()->postTask(createCCThreadTask(this, &CCThreadProxy::setNeedsCommitOnImplThread)); } +void CCThreadProxy::didLoseContextOnImplThread() +{ + ASSERT(isImplThread()); + TRACE_EVENT0("cc", "CCThreadProxy::didLoseContextOnImplThread"); + m_schedulerOnImplThread->didLoseContext(); +} + void CCThreadProxy::onSwapBuffersCompleteOnImplThread() { ASSERT(isImplThread()); @@ -259,11 +300,11 @@ void CCThreadProxy::setNeedsCommitOnImplThread() m_schedulerOnImplThread->setNeedsCommit(); } -void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events) +void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime) { ASSERT(isImplThread()); TRACE_EVENT("CCThreadProxy::postAnimationEventsToMainThreadOnImplThread", this, 0); - m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events)); + m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events, wallClockTime)); } void CCThreadProxy::setNeedsRedraw() @@ -511,6 +552,12 @@ void CCThreadProxy::scheduledActionCommit() m_commitCompletionEventOnImplThread = 0; } +void CCThreadProxy::scheduledActionBeginContextRecreation() +{ + ASSERT(isImplThread()); + m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::beginContextRecreation)); +} + void CCThreadProxy::scheduledActionDrawAndSwap() { TRACE_EVENT("CCThreadProxy::scheduledActionDrawAndSwap", this, 0); @@ -519,26 +566,23 @@ void CCThreadProxy::scheduledActionDrawAndSwap() return; // FIXME: compute the frame display time more intelligently - double frameDisplayTimeMs = monotonicallyIncreasingTime() * 1000.0; + double monotonicTime = monotonicallyIncreasingTime(); + double wallClockTime = currentTime(); - m_inputHandlerOnImplThread->willDraw(frameDisplayTimeMs); - m_layerTreeHostImpl->animate(frameDisplayTimeMs); + m_inputHandlerOnImplThread->willDraw(monotonicTime); + m_layerTreeHostImpl->animate(monotonicTime, wallClockTime); m_layerTreeHostImpl->drawLayers(); // Check for a pending compositeAndReadback. if (m_readbackRequestOnImplThread) { - m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect); - m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost(); - m_readbackRequestOnImplThread->completion.signal(); - m_readbackRequestOnImplThread = 0; + m_layerTreeHostImpl->readback(m_readbackRequestOnImplThread->pixels, m_readbackRequestOnImplThread->rect); + m_readbackRequestOnImplThread->success = !m_layerTreeHostImpl->isContextLost(); + m_readbackRequestOnImplThread->completion.signal(); + m_readbackRequestOnImplThread = 0; } m_layerTreeHostImpl->swapBuffers(); - // FIXME: handle case where m_layerTreeHostImpl->isContextLost. - // FIXME: pass didSwapBuffersAbort if m_layerTreeHostImpl->isContextLost. - ASSERT(!m_layerTreeHostImpl->isContextLost()); - // Process any finish request if (m_finishAllRenderingCompletionEventOnImplThread) { m_layerTreeHostImpl->finishAllRendering(); @@ -569,12 +613,55 @@ void CCThreadProxy::didCompleteSwapBuffers() m_layerTreeHost->didCompleteSwapBuffers(); } -void CCThreadProxy::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events) +void CCThreadProxy::setAnimationEvents(PassOwnPtr<CCAnimationEventsVector> events, double wallClockTime) { + TRACE_EVENT0("cc", "CCThreadProxy::setAnimationEvents"); ASSERT(isMainThread()); if (!m_layerTreeHost) return; - m_layerTreeHost->setAnimationEvents(events); + m_layerTreeHost->setAnimationEvents(events, wallClockTime); +} + +class CCThreadProxyContextRecreationTimer : public CCTimer, CCTimerClient { +public: + static PassOwnPtr<CCThreadProxyContextRecreationTimer> create(CCThreadProxy* proxy) { return adoptPtr(new CCThreadProxyContextRecreationTimer(proxy)); } + + virtual void onTimerFired() + { + m_proxy->tryToRecreateContext(); + } + + enum Recreation { RecreationTickRateMs = 30 }; + +private: + explicit CCThreadProxyContextRecreationTimer(CCThreadProxy* proxy) + : CCTimer(CCProxy::mainThread(), this) + , m_proxy(proxy) + { + } + + CCThreadProxy* m_proxy; +}; + +void CCThreadProxy::beginContextRecreation() +{ + TRACE_EVENT0("cc", "CCThreadProxy::beginContextRecreation"); + ASSERT(isMainThread()); + ASSERT(!m_contextRecreationTimer); + m_contextRecreationTimer = CCThreadProxyContextRecreationTimer::create(this); + m_layerTreeHost->didLoseContext(); + m_contextRecreationTimer->startOneShot(CCThreadProxyContextRecreationTimer::RecreationTickRateMs); +} + +void CCThreadProxy::tryToRecreateContext() +{ + ASSERT(isMainThread()); + ASSERT(m_layerTreeHost); + CCLayerTreeHost::RecreateResult result = m_layerTreeHost->recreateContext(); + if (result == CCLayerTreeHost::RecreateFailedButTryAgain) + m_contextRecreationTimer->startOneShot(CCThreadProxyContextRecreationTimer::RecreationTickRateMs); + else if (result == CCLayerTreeHost::RecreateSucceeded) + m_contextRecreationTimer.clear(); } void CCThreadProxy::initializeImplOnImplThread(CCCompletionEvent* completion) @@ -637,4 +724,17 @@ size_t CCThreadProxy::maxPartialTextureUpdates() const return textureUpdatesPerFrame; } +void CCThreadProxy::recreateContextOnImplThread(CCCompletionEvent* completion, GraphicsContext3D* contextPtr, bool* recreateSucceeded, LayerRendererCapabilities* capabilities) +{ + TRACE_EVENT0("cc", "CCThreadProxy::recreateContextOnImplThread"); + ASSERT(isImplThread()); + m_layerTreeHost->deleteContentsTexturesOnImplThread(m_layerTreeHostImpl->contentsTextureAllocator()); + *recreateSucceeded = m_layerTreeHostImpl->initializeLayerRenderer(adoptRef(contextPtr)); + if (*recreateSucceeded) { + *capabilities = m_layerTreeHostImpl->layerRendererCapabilities(); + m_schedulerOnImplThread->didRecreateContext(); + } + completion->signal(); +} + } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h index 330ef51ca..057691213 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.h @@ -31,6 +31,7 @@ #include "cc/CCProxy.h" #include "cc/CCScheduler.h" #include "cc/CCThread.h" +#include "cc/CCTimer.h" #include <wtf/OwnPtr.h> namespace WebCore { @@ -41,6 +42,7 @@ class CCScheduler; class CCScopedThreadProxy; class CCTextureUpdater; class CCThread; +class CCThreadProxyContextRecreationTimer; class CCThreadProxy : public CCProxy, CCLayerTreeHostImplClient, CCSchedulerClient { public: @@ -50,15 +52,16 @@ public: // CCProxy implementation virtual bool compositeAndReadback(void *pixels, const IntRect&); - virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double durationSec); + virtual void startPageScaleAnimation(const IntSize& targetPosition, bool useAnchor, float scale, double duration); virtual GraphicsContext3D* context(); virtual void finishAllRendering(); virtual bool isStarted() const; virtual bool initializeContext(); virtual bool initializeLayerRenderer(); + virtual bool recreateContext(); virtual int compositorIdentifier() const; virtual const LayerRendererCapabilities& layerRendererCapabilities() const; - virtual void loseCompositorContext(int numTimes); + virtual void loseContext(); virtual void setNeedsAnimate(); virtual void setNeedsCommit(); virtual void setNeedsRedraw(); @@ -68,10 +71,11 @@ public: virtual size_t maxPartialTextureUpdates() const; // CCLayerTreeHostImplClient implementation + virtual void didLoseContextOnImplThread(); virtual void onSwapBuffersCompleteOnImplThread(); virtual void setNeedsRedrawOnImplThread(); virtual void setNeedsCommitOnImplThread(); - virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>); + virtual void postAnimationEventsToMainThreadOnImplThread(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime); // CCSchedulerClient implementation virtual bool canDraw(); @@ -80,15 +84,19 @@ public: virtual void scheduledActionDrawAndSwap(); virtual void scheduledActionUpdateMoreResources(); virtual void scheduledActionCommit(); + virtual void scheduledActionBeginContextRecreation(); private: explicit CCThreadProxy(CCLayerTreeHost*); + friend class CCThreadProxyContextRecreationTimer; // Called on main thread void beginFrameAndCommit(int sequenceNumber, double frameBeginTime, PassOwnPtr<CCScrollAndScaleSet>); void didCommitAndDrawFrame(); void didCompleteSwapBuffers(); - void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>); + void setAnimationEvents(PassOwnPtr<CCAnimationEventsVector>, double wallClockTime); + void beginContextRecreation(); + void tryToRecreateContext(); // Called on impl thread struct ReadbackRequest { @@ -109,10 +117,13 @@ private: void setVisibleOnImplThread(CCCompletionEvent*, bool visible); void layerTreeHostClosedOnImplThread(CCCompletionEvent*); void setFullRootLayerDamageOnImplThread(); + void recreateContextOnImplThread(CCCompletionEvent*, GraphicsContext3D*, bool* recreateSucceeded, LayerRendererCapabilities*); // Accessed on main thread only. bool m_animateRequested; bool m_commitRequested; + bool m_contextLost; + OwnPtr<CCThreadProxyContextRecreationTimer> m_contextRecreationTimer; CCLayerTreeHost* m_layerTreeHost; int m_compositorIdentifier; bool m_layerRendererInitialized; diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp index 47d0a708c..e8d2a6c45 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp @@ -52,14 +52,10 @@ public: Platform3DObject textureId() const { return m_textureId; } void setTextureId(Platform3DObject textureId) { m_textureId = textureId; } - const IntRect& opaqueRect() const { return m_opaqueRect; } - void setOpaqueRect(const IntRect& opaqueRect) { m_opaqueRect = opaqueRect; } - private: DrawableTile() : m_textureId(0) { } Platform3DObject m_textureId; - IntRect m_opaqueRect; }; CCTiledLayerImpl::CCTiledLayerImpl(int id) @@ -203,6 +199,14 @@ void CCTiledLayerImpl::pushTileProperties(int i, int j, Platform3DObject texture tile->setOpaqueRect(opaqueRect); } +Region CCTiledLayerImpl::opaqueContentsRegion() const +{ + if (m_skipsDraw) + return Region(); + + return m_tiler->opaqueRegionInLayerRect(visibleLayerRect()); +} + } // namespace WebCore #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h index 7ad71599b..84fe47621 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.h @@ -37,9 +37,9 @@ class DrawableTile; class CCTiledLayerImpl : public CCLayerImpl { public: - static PassRefPtr<CCTiledLayerImpl> create(int id) + static PassOwnPtr<CCTiledLayerImpl> create(int id) { - return adoptRef(new CCTiledLayerImpl(id)); + return adoptPtr(new CCTiledLayerImpl(id)); } virtual ~CCTiledLayerImpl(); @@ -56,6 +56,8 @@ public: void setContentsSwizzled(bool contentsSwizzled) { m_contentsSwizzled = contentsSwizzled; } bool contentsSwizzled() const { return m_contentsSwizzled; } + virtual Region opaqueContentsRegion() const; + typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexAlpha> Program; // Shader program that swaps red and blue components of texture. // Used when texture format does not match native color format. diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.cpp new file mode 100644 index 000000000..decc00c8f --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 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: + * 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. 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 INC. 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. + */ + +#include "config.h" + +#include "cc/CCTimingFunction.h" + +#include <wtf/OwnPtr.h> + +namespace { +const double epsilon = 1e-6; +} // namespace + +namespace WebCore { + +CCTimingFunction::CCTimingFunction() +{ +} + +CCTimingFunction::~CCTimingFunction() +{ +} + +double CCTimingFunction::duration() const +{ + return 1.0; +} + +PassOwnPtr<CCCubicBezierTimingFunction> CCCubicBezierTimingFunction::create(double x1, double y1, double x2, double y2) +{ + return adoptPtr(new CCCubicBezierTimingFunction(x1, y1, x2, y2)); +} + +CCCubicBezierTimingFunction::CCCubicBezierTimingFunction(double x1, double y1, double x2, double y2) + : m_curve(x1, y1, x2, y2) +{ +} + +CCCubicBezierTimingFunction::~CCCubicBezierTimingFunction() +{ +} + +float CCCubicBezierTimingFunction::getValue(double x) const +{ + UnitBezier temp(m_curve); + return static_cast<float>(temp.solve(x, epsilon)); +} + +PassOwnPtr<CCAnimationCurve> CCCubicBezierTimingFunction::clone() const +{ + return adoptPtr(new CCCubicBezierTimingFunction(*this)); +} + +// These numbers come from http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag. +PassOwnPtr<CCTimingFunction> CCEaseTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0.25, 0.1, 0.25, 1); +} + +PassOwnPtr<CCTimingFunction> CCEaseInTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0.42, 0, 1.0, 1); +} + +PassOwnPtr<CCTimingFunction> CCEaseOutTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0, 0, 0.58, 1); +} + +PassOwnPtr<CCTimingFunction> CCEaseInOutTimingFunction::create() +{ + return CCCubicBezierTimingFunction::create(0.42, 0, 0.58, 1); +} + +} // namespace WebCore diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h b/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h new file mode 100644 index 000000000..77e5c43c5 --- /dev/null +++ b/Source/WebCore/platform/graphics/chromium/cc/CCTimingFunction.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2012 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: + * 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. 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 INC. 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. + */ + +#ifndef CCTimingFunction_h +#define CCTimingFunction_h + +#include "UnitBezier.h" +#include "cc/CCAnimationCurve.h" + +#include <wtf/PassOwnPtr.h> + +namespace WebCore { + +// See http://www.w3.org/TR/css3-transitions/. +class CCTimingFunction : public CCFloatAnimationCurve { +public: + virtual ~CCTimingFunction(); + + // Partial implementation of CCFloatAnimationCurve. + virtual double duration() const; + +protected: + CCTimingFunction(); +}; + +class CCCubicBezierTimingFunction : public CCTimingFunction { +public: + static PassOwnPtr<CCCubicBezierTimingFunction> create(double x1, double y1, double x2, double y2); + virtual ~CCCubicBezierTimingFunction(); + + // Partial implementation of CCFloatAnimationCurve. + virtual float getValue(double time) const; + virtual PassOwnPtr<CCAnimationCurve> clone() const; + +protected: + CCCubicBezierTimingFunction(double x1, double y1, double x2, double y2); + + UnitBezier m_curve; +}; + +class CCEaseTimingFunction { +public: + static PassOwnPtr<CCTimingFunction> create(); +}; + +class CCEaseInTimingFunction { +public: + static PassOwnPtr<CCTimingFunction> create(); +}; + +class CCEaseOutTimingFunction { +public: + static PassOwnPtr<CCTimingFunction> create(); +}; + +class CCEaseInOutTimingFunction { +public: + static PassOwnPtr<CCTimingFunction> create(); +}; + +} // namespace WebCore + +#endif // CCTimingFunction_h + diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp index 35f269f50..fd53e41d3 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp +++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.cpp @@ -34,6 +34,7 @@ #include "LayerRendererChromium.h" #include "NotImplemented.h" #include "ProgramBinding.h" +#include "cc/CCLayerTreeHostImpl.h" #include "cc/CCProxy.h" #include "cc/CCVideoDrawQuad.h" #include <wtf/text/WTFString.h> @@ -89,7 +90,6 @@ CCVideoLayerImpl::~CCVideoLayerImpl() } for (unsigned i = 0; i < MaxPlanes; ++i) m_textures[i].m_texture.clear(); - cleanupResources(); } void CCVideoLayerImpl::stopUsingProvider() diff --git a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h index caa72dfb9..4c4e23102 100644 --- a/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h +++ b/Source/WebCore/platform/graphics/chromium/cc/CCVideoLayerImpl.h @@ -43,9 +43,9 @@ template<class VertexShader, class FragmentShader> class ProgramBinding; class CCVideoLayerImpl : public CCLayerImpl , public VideoFrameProvider::Client { public: - static PassRefPtr<CCVideoLayerImpl> create(int id, VideoFrameProvider* provider) + static PassOwnPtr<CCVideoLayerImpl> create(int id, VideoFrameProvider* provider) { - return adoptRef(new CCVideoLayerImpl(id, provider)); + return adoptPtr(new CCVideoLayerImpl(id, provider)); } virtual ~CCVideoLayerImpl(); |