diff options
-rw-r--r-- | libs/hwui/Android.mk | 8 | ||||
-rw-r--r-- | libs/hwui/CanvasState.cpp (renamed from libs/hwui/StatefulBaseRenderer.cpp) | 89 | ||||
-rw-r--r-- | libs/hwui/CanvasState.h | 196 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 35 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 32 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 4 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.h | 2 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.cpp | 236 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.h | 95 | ||||
-rw-r--r-- | libs/hwui/StatefulBaseRenderer.h | 170 |
10 files changed, 511 insertions, 356 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 5b74add..51f257f 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -25,10 +25,9 @@ ifeq ($(USE_OPENGL_RENDERER),true) Animator.cpp \ AnimatorManager.cpp \ AssetAtlas.cpp \ - DamageAccumulator.cpp \ - FontRenderer.cpp \ - GammaFontRenderer.cpp \ Caches.cpp \ + CanvasState.cpp \ + DamageAccumulator.cpp \ DisplayList.cpp \ DeferredDisplayList.cpp \ DeferredLayerUpdater.cpp \ @@ -38,6 +37,8 @@ ifeq ($(USE_OPENGL_RENDERER),true) DrawProfiler.cpp \ Extensions.cpp \ FboCache.cpp \ + FontRenderer.cpp \ + GammaFontRenderer.cpp \ GradientCache.cpp \ Image.cpp \ Interpolator.cpp \ @@ -62,7 +63,6 @@ ifeq ($(USE_OPENGL_RENDERER),true) SkiaShader.cpp \ Snapshot.cpp \ SpotShadow.cpp \ - StatefulBaseRenderer.cpp \ Stencil.cpp \ TessellationCache.cpp \ Texture.cpp \ diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/CanvasState.cpp index 88d6f68..20cc17e 100644 --- a/libs/hwui/StatefulBaseRenderer.cpp +++ b/libs/hwui/CanvasState.cpp @@ -14,41 +14,45 @@ * limitations under the License. */ -#define LOG_TAG "OpenGLRenderer" - #include <SkCanvas.h> -#include "StatefulBaseRenderer.h" - +#include "CanvasState.h" #include "utils/MathUtils.h" namespace android { namespace uirenderer { -StatefulBaseRenderer::StatefulBaseRenderer() + +CanvasState::CanvasState(CanvasStateClient& renderer) : mDirtyClip(false) , mWidth(-1) , mHeight(-1) , mSaveCount(1) , mFirstSnapshot(new Snapshot) + , mCanvas(renderer) , mSnapshot(mFirstSnapshot) { + } -void StatefulBaseRenderer::initializeSaveStack(float clipLeft, float clipTop, +CanvasState::~CanvasState() { + +} + +void CanvasState::initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom, const Vector3& lightCenter) { mSnapshot = new Snapshot(mFirstSnapshot, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom); - mSnapshot->fbo = getTargetFbo(); + mSnapshot->fbo = mCanvas.onGetTargetFbo(); mSnapshot->setRelativeLightCenter(lightCenter); mSaveCount = 1; } -void StatefulBaseRenderer::setViewport(int width, int height) { +void CanvasState::setViewport(int width, int height) { mWidth = width; mHeight = height; mFirstSnapshot->initializeViewport(width, height); - onViewportInitialized(); + mCanvas.onViewportInitialized(); // create a temporary 1st snapshot, so old snapshots are released, // and viewport can be queried safely. @@ -63,24 +67,24 @@ void StatefulBaseRenderer::setViewport(int width, int height) { /////////////////////////////////////////////////////////////////////////////// /** - * Non-virtual implementation of save, guaranteed to save without side-effects + * Guaranteed to save without side-effects * - * The approach here and in restoreSnapshot(), allows subclasses to directly manipulate the save + * This approach, here and in restoreSnapshot(), allows subclasses to directly manipulate the save * stack, and ensures restoreToCount() doesn't call back into subclass overrides. */ -int StatefulBaseRenderer::saveSnapshot(int flags) { +int CanvasState::saveSnapshot(int flags) { mSnapshot = new Snapshot(mSnapshot, flags); return mSaveCount++; } -int StatefulBaseRenderer::save(int flags) { +int CanvasState::save(int flags) { return saveSnapshot(flags); } /** - * Non-virtual implementation of restore, guaranteed to restore without side-effects. + * Guaranteed to restore without side-effects. */ -void StatefulBaseRenderer::restoreSnapshot() { +void CanvasState::restoreSnapshot() { sp<Snapshot> toRemove = mSnapshot; sp<Snapshot> toRestore = mSnapshot->previous; @@ -88,16 +92,16 @@ void StatefulBaseRenderer::restoreSnapshot() { mSnapshot = toRestore; // subclass handles restore implementation - onSnapshotRestored(*toRemove, *toRestore); + mCanvas.onSnapshotRestored(*toRemove, *toRestore); } -void StatefulBaseRenderer::restore() { +void CanvasState::restore() { if (mSaveCount > 1) { restoreSnapshot(); } } -void StatefulBaseRenderer::restoreToCount(int saveCount) { +void CanvasState::restoreToCount(int saveCount) { if (saveCount < 1) saveCount = 1; while (mSaveCount > saveCount) { @@ -109,40 +113,40 @@ void StatefulBaseRenderer::restoreToCount(int saveCount) { // Matrix /////////////////////////////////////////////////////////////////////////////// -void StatefulBaseRenderer::getMatrix(SkMatrix* matrix) const { +void CanvasState::getMatrix(SkMatrix* matrix) const { mSnapshot->transform->copyTo(*matrix); } -void StatefulBaseRenderer::translate(float dx, float dy, float dz) { +void CanvasState::translate(float dx, float dy, float dz) { mSnapshot->transform->translate(dx, dy, dz); } -void StatefulBaseRenderer::rotate(float degrees) { +void CanvasState::rotate(float degrees) { mSnapshot->transform->rotate(degrees, 0.0f, 0.0f, 1.0f); } -void StatefulBaseRenderer::scale(float sx, float sy) { +void CanvasState::scale(float sx, float sy) { mSnapshot->transform->scale(sx, sy, 1.0f); } -void StatefulBaseRenderer::skew(float sx, float sy) { +void CanvasState::skew(float sx, float sy) { mSnapshot->transform->skew(sx, sy); } -void StatefulBaseRenderer::setMatrix(const SkMatrix& matrix) { +void CanvasState::setMatrix(const SkMatrix& matrix) { mSnapshot->transform->load(matrix); } -void StatefulBaseRenderer::setMatrix(const Matrix4& matrix) { +void CanvasState::setMatrix(const Matrix4& matrix) { mSnapshot->transform->load(matrix); } -void StatefulBaseRenderer::concatMatrix(const SkMatrix& matrix) { +void CanvasState::concatMatrix(const SkMatrix& matrix) { mat4 transform(matrix); mSnapshot->transform->multiply(transform); } -void StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) { +void CanvasState::concatMatrix(const Matrix4& matrix) { mSnapshot->transform->multiply(matrix); } @@ -150,7 +154,7 @@ void StatefulBaseRenderer::concatMatrix(const Matrix4& matrix) { // Clip /////////////////////////////////////////////////////////////////////////////// -bool StatefulBaseRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { +bool CanvasState::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { if (CC_LIKELY(currentTransform()->rectToRect())) { mDirtyClip |= mSnapshot->clip(left, top, right, bottom, op); return !mSnapshot->clipRect->isEmpty(); @@ -159,10 +163,10 @@ bool StatefulBaseRenderer::clipRect(float left, float top, float right, float bo SkPath path; path.addRect(left, top, right, bottom); - return StatefulBaseRenderer::clipPath(&path, op); + return CanvasState::clipPath(&path, op); } -bool StatefulBaseRenderer::clipPath(const SkPath* path, SkRegion::Op op) { +bool CanvasState::clipPath(const SkPath* path, SkRegion::Op op) { SkMatrix transform; currentTransform()->copyTo(transform); @@ -189,12 +193,12 @@ bool StatefulBaseRenderer::clipPath(const SkPath* path, SkRegion::Op op) { return !mSnapshot->clipRect->isEmpty(); } -bool StatefulBaseRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) { +bool CanvasState::clipRegion(const SkRegion* region, SkRegion::Op op) { mDirtyClip |= mSnapshot->clipRegionTransformed(*region, op); return !mSnapshot->clipRect->isEmpty(); } -void StatefulBaseRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { +void CanvasState::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { Rect bounds; float radius; if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported @@ -209,7 +213,7 @@ void StatefulBaseRenderer::setClippingOutline(LinearAllocator& allocator, const } } -void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator, +void CanvasState::setClippingRoundRect(LinearAllocator& allocator, const Rect& rect, float radius, bool highPriority) { mSnapshot->setClippingRoundRect(allocator, rect, radius, highPriority); } @@ -229,7 +233,7 @@ void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator, * @param snapOut if set, the geometry will be treated as having an AA ramp. * See Rect::snapGeometryToPixelBoundaries() */ -bool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top, +bool CanvasState::calculateQuickRejectForScissor(float left, float top, float right, float bottom, bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const { @@ -259,18 +263,7 @@ bool StatefulBaseRenderer::calculateQuickRejectForScissor(float left, float top, return false; } -/** - * Returns false if drawing won't be clipped out. - * - * Makes the decision conservatively, by rounding out the mapped rect before comparing with the - * clipRect. To be used when perfect, pixel accuracy is not possible (esp. with tessellation) but - * rejection is still desired. - * - * This function, unlike quickRejectSetupScissor, should be used where precise geometry information - * isn't known (esp. when geometry adjusts based on scale). Generally, this will be first pass - * rejection where precise rejection isn't important, or precise information isn't available. - */ -bool StatefulBaseRenderer::quickRejectConservative(float left, float top, +bool CanvasState::quickRejectConservative(float left, float top, float right, float bottom) const { if (mSnapshot->isIgnored() || bottom <= top || right <= left) { return true; @@ -288,5 +281,5 @@ bool StatefulBaseRenderer::quickRejectConservative(float left, float top, return false; } -}; // namespace uirenderer -}; // namespace android +} // namespace uirenderer +} // namespace android diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h new file mode 100644 index 0000000..b15698e --- /dev/null +++ b/libs/hwui/CanvasState.h @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_HWUI_CANVAS_STATE_H +#define ANDROID_HWUI_CANVAS_STATE_H + +#include <SkMatrix.h> +#include <SkPath.h> +#include <SkRegion.h> + +#include "Snapshot.h" + +namespace android { +namespace uirenderer { + +/** + * Abstract base class for any class containing CanvasState. + * Defines three mandatory callbacks. + */ +class CanvasStateClient { +public: + CanvasStateClient() { } + virtual ~CanvasStateClient() { } + + /** + * Callback allowing embedder to take actions in the middle of a + * setViewport() call. + */ + virtual void onViewportInitialized() = 0; + + /** + * Callback allowing embedder to take actions in the middle of a + * restore() call. May be called several times sequentially. + */ + virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) = 0; + + /** + * Allows subclasses to control what value is stored in snapshot's + * fbo field in * initializeSaveStack. + */ + virtual GLuint onGetTargetFbo() const = 0; + +}; // class CanvasStateClient + +/** + * Implements Canvas state methods on behalf of Renderers. + * + * Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the + * Renderer interface. Drawing and recording classes that include a CanvasState will have + * different use cases: + * + * Drawing subclasses (i.e. OpenGLRenderer) can query attributes (such as transform) or hook into + * changes (e.g. save/restore) with minimal surface area for manipulating the stack itself. + * + * Recording subclasses (i.e. DisplayListRenderer) can both record and pass through state operations + * to CanvasState, so that not only will querying operations work (getClip/Matrix), but so + * that quickRejection can also be used. + */ + +class CanvasState { +public: + CanvasState(CanvasStateClient& renderer); + ~CanvasState(); + + /** + * Initializes the first snapshot, computing the projection matrix, + * and stores the dimensions of the render target. + */ + void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom, + const Vector3& lightCenter); + + void setViewport(int width, int height); + + bool hasRectToRectTransform() const { + return CC_LIKELY(currentTransform()->rectToRect()); + } + + // Save (layer) + int getSaveCount() const { return mSaveCount; } + int save(int flags); + void restore(); + void restoreToCount(int saveCount); + + // Save/Restore without side-effects + int saveSnapshot(int flags); + void restoreSnapshot(); + + // Matrix + void getMatrix(SkMatrix* outMatrix) const; + void translate(float dx, float dy, float dz = 0.0f); + void rotate(float degrees); + void scale(float sx, float sy); + void skew(float sx, float sy); + + void setMatrix(const SkMatrix& matrix); + void setMatrix(const Matrix4& matrix); // internal only convenience method + void concatMatrix(const SkMatrix& matrix); + void concatMatrix(const Matrix4& matrix); // internal only convenience method + + // Clip + const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); } + const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); } + + bool quickRejectConservative(float left, float top, float right, float bottom) const; + + bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); + bool clipPath(const SkPath* path, SkRegion::Op op); + bool clipRegion(const SkRegion* region, SkRegion::Op op); + + bool isCurrentClipSimple() const { + return currentSnapshot()->clipRegion->isEmpty(); + } + + /** + * Sets a "clipping outline", which is independent from the regular clip. + * Currently only supports rectangles or rounded rectangles; passing in a + * more complicated outline fails silently. Replaces any previous clipping + * outline. + */ + void setClippingOutline(LinearAllocator& allocator, const Outline* outline); + void setClippingRoundRect(LinearAllocator& allocator, + const Rect& rect, float radius, bool highPriority = true); + + /** + * Returns true if drawing in the rectangle (left, top, right, bottom) + * will be clipped out. Is conservative: might return false when subpixel- + * perfect tests would return true. + */ + bool calculateQuickRejectForScissor(float left, float top, float right, float bottom, + bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const; + + void setDirtyClip(bool opaque) { mDirtyClip = opaque; } + bool getDirtyClip() const { return mDirtyClip; } + + void scaleAlpha(float alpha) { mSnapshot->alpha *= alpha; } + void setEmpty(bool value) { mSnapshot->empty = value; } + void setInvisible(bool value) { mSnapshot->invisible = value; } + + inline const mat4* currentTransform() const { return currentSnapshot()->transform; } + inline const Rect* currentClipRect() const { return currentSnapshot()->clipRect; } + inline Region* currentRegion() const { return currentSnapshot()->region; } + inline int currentFlags() const { return currentSnapshot()->flags; } + const Vector3& currentLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); } + inline bool currentlyIgnored() const { return currentSnapshot()->isIgnored(); } + int getViewportWidth() const { return currentSnapshot()->getViewportWidth(); } + int getViewportHeight() const { return currentSnapshot()->getViewportHeight(); } + int getWidth() { return mWidth; } + int getHeight() { return mHeight; } + + inline const Snapshot* currentSnapshot() const { + return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get(); + } + inline Snapshot* writableSnapshot() { return mSnapshot.get(); } + inline const Snapshot* firstSnapshot() const { return mFirstSnapshot.get(); } + +private: + /// No default constructor - must supply a CanvasStateClient (mCanvas). + CanvasState(); + + /// indicates that the clip has been changed since the last time it was consumed + bool mDirtyClip; + + /// Dimensions of the drawing surface + int mWidth, mHeight; + + /// Number of saved states + int mSaveCount; + + /// Base state + sp<Snapshot> mFirstSnapshot; + + /// Host providing callbacks + CanvasStateClient& mCanvas; + + /// Current state + sp<Snapshot> mSnapshot; + +}; // class CanvasState + +}; // namespace uirenderer +}; // namespace android + +#endif // ANDROID_HWUI_CANVAS_STATE_H diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index ab9ca1f..c0b8a56 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -32,7 +32,8 @@ namespace android { namespace uirenderer { DisplayListRenderer::DisplayListRenderer() - : mCaches(Caches::getInstance()) + : mState(*this) + , mCaches(Caches::getInstance()) , mDisplayListData(NULL) , mTranslateX(0.0f) , mTranslateY(0.0f) @@ -66,10 +67,10 @@ void DisplayListRenderer::prepareDirty(float left, float top, "prepareDirty called a second time during a recording!"); mDisplayListData = new DisplayListData(); - initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3()); + mState.initializeSaveStack(0, 0, mState.getWidth(), mState.getHeight(), Vector3()); mDeferredBarrierType = kBarrier_InOrder; - mDirtyClip = opaque; + mState.setDirtyClip(opaque); mRestoreSaveCount = -1; } @@ -93,7 +94,7 @@ void DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) { int DisplayListRenderer::save(int flags) { addStateOp(new (alloc()) SaveOp(flags)); - return StatefulBaseRenderer::save(flags); + return mState.save(flags); } void DisplayListRenderer::restore() { @@ -104,13 +105,13 @@ void DisplayListRenderer::restore() { mRestoreSaveCount--; flushTranslate(); - StatefulBaseRenderer::restore(); + mState.restore(); } void DisplayListRenderer::restoreToCount(int saveCount) { mRestoreSaveCount = saveCount; flushTranslate(); - StatefulBaseRenderer::restoreToCount(saveCount); + mState.restoreToCount(saveCount); } int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom, @@ -120,7 +121,7 @@ int DisplayListRenderer::saveLayer(float left, float top, float right, float bot paint = refPaint(paint); addStateOp(new (alloc()) SaveLayerOp(left, top, right, bottom, paint, flags)); - return StatefulBaseRenderer::save(flags); + return mState.save(flags); } void DisplayListRenderer::translate(float dx, float dy, float dz) { @@ -129,50 +130,50 @@ void DisplayListRenderer::translate(float dx, float dy, float dz) { mTranslateX += dx; mTranslateY += dy; flushRestoreToCount(); - StatefulBaseRenderer::translate(dx, dy, dz); + mState.translate(dx, dy, dz); } void DisplayListRenderer::rotate(float degrees) { addStateOp(new (alloc()) RotateOp(degrees)); - StatefulBaseRenderer::rotate(degrees); + mState.rotate(degrees); } void DisplayListRenderer::scale(float sx, float sy) { addStateOp(new (alloc()) ScaleOp(sx, sy)); - StatefulBaseRenderer::scale(sx, sy); + mState.scale(sx, sy); } void DisplayListRenderer::skew(float sx, float sy) { addStateOp(new (alloc()) SkewOp(sx, sy)); - StatefulBaseRenderer::skew(sx, sy); + mState.skew(sx, sy); } void DisplayListRenderer::setMatrix(const SkMatrix& matrix) { addStateOp(new (alloc()) SetMatrixOp(matrix)); - StatefulBaseRenderer::setMatrix(matrix); + mState.setMatrix(matrix); } void DisplayListRenderer::concatMatrix(const SkMatrix& matrix) { addStateOp(new (alloc()) ConcatMatrixOp(matrix)); - StatefulBaseRenderer::concatMatrix(matrix); + mState.concatMatrix(matrix); } bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { addStateOp(new (alloc()) ClipRectOp(left, top, right, bottom, op)); - return StatefulBaseRenderer::clipRect(left, top, right, bottom, op); + return mState.clipRect(left, top, right, bottom, op); } bool DisplayListRenderer::clipPath(const SkPath* path, SkRegion::Op op) { path = refPath(path); addStateOp(new (alloc()) ClipPathOp(path, op)); - return StatefulBaseRenderer::clipPath(path, op); + return mState.clipPath(path, op); } bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) { region = refRegion(region); addStateOp(new (alloc()) ClipRegionOp(region, op)); - return StatefulBaseRenderer::clipRegion(region, op); + return mState.clipRegion(region, op); } void DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) { @@ -180,7 +181,7 @@ void DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, in // dirty is an out parameter and should not be recorded, // it matters only when replaying the display list - DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform()); + DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *mState.currentTransform()); addRenderNodeOp(op); } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 34b0a1f..7dd788d 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -25,9 +25,11 @@ #include <SkTLazy.h> #include <cutils/compiler.h> +#include "CanvasState.h" #include "DisplayList.h" #include "DisplayListLogBuffer.h" -#include "StatefulBaseRenderer.h" +#include "RenderNode.h" +#include "Renderer.h" namespace android { namespace uirenderer { @@ -57,7 +59,7 @@ class StateOp; /** * Records drawing commands in a display list for later playback into an OpenGLRenderer. */ -class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer { +class ANDROID_API DisplayListRenderer: public Renderer, public CanvasStateClient { public: DisplayListRenderer(); virtual ~DisplayListRenderer(); @@ -70,6 +72,9 @@ public: // Frame state operations // ---------------------------------------------------------------------------- virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); + virtual void prepare(bool opaque) { + prepareDirty(0.0f, 0.0f, mState.getWidth(), mState.getHeight(), opaque); + } virtual bool finish(); virtual void interrupt(); virtual void resume(); @@ -77,7 +82,10 @@ public: // ---------------------------------------------------------------------------- // Canvas state operations // ---------------------------------------------------------------------------- + virtual void setViewport(int width, int height) { mState.setViewport(width, height); } + // Save (layer) + virtual int getSaveCount() const { return mState.getSaveCount(); } virtual int save(int flags); virtual void restore(); virtual void restoreToCount(int saveCount); @@ -85,6 +93,8 @@ public: const SkPaint* paint, int flags); // Matrix + virtual void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); } + virtual void translate(float dx, float dy, float dz = 0.0f); virtual void rotate(float degrees); virtual void scale(float sx, float sy); @@ -100,9 +110,14 @@ public: // Misc virtual void setDrawFilter(SkDrawFilter* filter); + virtual const Rect& getLocalClipBounds() const { return mState.getLocalClipBounds(); } + const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); } + virtual bool quickRejectConservative(float left, float top, float right, float bottom) const { + return mState.quickRejectConservative(left, top, right, bottom); + } bool isCurrentTransformSimple() { - return currentTransform()->isSimple(); + return mState.currentTransform()->isSimple(); } // ---------------------------------------------------------------------------- @@ -163,7 +178,18 @@ public: void setHighContrastText(bool highContrastText) { mHighContrastText = highContrastText; } + +// ---------------------------------------------------------------------------- +// CanvasState callbacks +// ---------------------------------------------------------------------------- + virtual void onViewportInitialized() { } + virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) { } + virtual GLuint onGetTargetFbo() const { return -1; } + private: + + CanvasState mState; + enum DeferredBarrierType { kBarrier_None, kBarrier_InOrder, diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 9306f13..268b9da 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -91,7 +91,7 @@ bool LayerRenderer::finish() { return retval; } -GLuint LayerRenderer::getTargetFbo() const { +GLuint LayerRenderer::onGetTargetFbo() const { return mLayer->getFbo(); } @@ -116,7 +116,7 @@ void LayerRenderer::ensureStencilBuffer() { /////////////////////////////////////////////////////////////////////////////// Region* LayerRenderer::getRegion() const { - if (currentSnapshot()->flags & Snapshot::kFlagFboTarget) { + if (mState.currentFlags() & Snapshot::kFlagFboTarget) { return OpenGLRenderer::getRegion(); } return &mLayer->region; diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index 47099bf..769ef49 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -68,7 +68,7 @@ protected: virtual void ensureStencilBuffer(); virtual bool hasLayer() const; virtual Region* getRegion() const; - virtual GLuint getTargetFbo() const; + virtual GLuint onGetTargetFbo() const; virtual bool suppressErrorChecks() const; private: diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 1ac9e7b..71b7c11 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -147,7 +147,8 @@ static inline T min(T a, T b) { /////////////////////////////////////////////////////////////////////////////// OpenGLRenderer::OpenGLRenderer(RenderState& renderState) - : mFrameStarted(false) + : mState(*this) + , mFrameStarted(false) , mCaches(Caches::getInstance()) , mExtensions(Extensions::getInstance()) , mRenderState(renderState) @@ -205,7 +206,7 @@ void OpenGLRenderer::onViewportInitialized() { void OpenGLRenderer::setupFrameState(float left, float top, float right, float bottom, bool opaque) { mCaches.clearGarbage(); - initializeSaveStack(left, top, right, bottom, mLightCenter); + mState.initializeSaveStack(left, top, right, bottom, mLightCenter); mOpaque = opaque; mTilingClip.set(left, top, right, bottom); } @@ -214,11 +215,11 @@ void OpenGLRenderer::startFrame() { if (mFrameStarted) return; mFrameStarted = true; - mDirtyClip = true; + mState.setDirtyClip(true); discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom); - mRenderState.setViewport(getWidth(), getHeight()); + mRenderState.setViewport(mState.getWidth(), mState.getHeight()); // Functors break the tiling extension in pretty spectacular ways // This ensures we don't use tiling when a functor is going to be @@ -257,8 +258,8 @@ void OpenGLRenderer::discardFramebuffer(float left, float top, float right, floa // perform a discard to let the driver know we don't need to preserve // the back buffer for this frame. if (mExtensions.hasDiscardFramebuffer() && - left <= 0.0f && top <= 0.0f && right >= getWidth() && bottom >= getHeight()) { - const bool isFbo = getTargetFbo() == 0; + left <= 0.0f && top <= 0.0f && right >= mState.getWidth() && bottom >= mState.getHeight()) { + const bool isFbo = onGetTargetFbo() == 0; const GLenum attachments[] = { isFbo ? (const GLenum) GL_COLOR_EXT : (const GLenum) GL_COLOR_ATTACHMENT0, isFbo ? (const GLenum) GL_STENCIL_EXT : (const GLenum) GL_STENCIL_ATTACHMENT }; @@ -329,7 +330,7 @@ bool OpenGLRenderer::finish() { // When finish() is invoked on FBO 0 we've reached the end // of the current frame - if (getTargetFbo() == 0) { + if (onGetTargetFbo() == 0) { mCaches.pathCache.trim(); mCaches.tessellationCache.trim(); } @@ -363,9 +364,9 @@ void OpenGLRenderer::resumeAfterLayer() { } void OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { - if (currentSnapshot()->isIgnored()) return; + if (mState.currentlyIgnored()) return; - Rect clip(*currentClipRect()); + Rect clip(*mState.currentClipRect()); clip.snapToPixelBoundaries(); // Since we don't know what the functor will draw, let's dirty @@ -384,9 +385,9 @@ void OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { info.height = getViewportHeight(); currentTransform()->copyTo(&info.transform[0]); - bool prevDirtyClip = mDirtyClip; + bool prevDirtyClip = mState.getDirtyClip(); // setup GL state for functor - if (mDirtyClip) { + if (mState.getDirtyClip()) { setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt() } if (mCaches.enableScissor() || prevDirtyClip) { @@ -436,11 +437,11 @@ void OpenGLRenderer::debugOverdraw(bool enable, bool clear) { } void OpenGLRenderer::renderOverdraw() { - if (mCaches.debugOverdraw && getTargetFbo() == 0) { + if (mCaches.debugOverdraw && onGetTargetFbo() == 0) { const Rect* clip = &mTilingClip; mCaches.enableScissor(); - mCaches.setScissor(clip->left, firstSnapshot()->getViewportHeight() - clip->bottom, + mCaches.setScissor(clip->left, mState.firstSnapshot()->getViewportHeight() - clip->bottom, clip->right - clip->left, clip->bottom - clip->top); // 1x overdraw @@ -519,7 +520,7 @@ void OpenGLRenderer::updateLayers() { if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { mLayerUpdates.clear(); - mRenderState.bindFramebuffer(getTargetFbo()); + mRenderState.bindFramebuffer(onGetTargetFbo()); } endMark(); } @@ -546,7 +547,7 @@ void OpenGLRenderer::flushLayers() { } mLayerUpdates.clear(); - mRenderState.bindFramebuffer(getTargetFbo()); + mRenderState.bindFramebuffer(onGetTargetFbo()); endMark(); } @@ -628,9 +629,9 @@ int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom, // force matrix/clip isolation for layer flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag; - const int count = saveSnapshot(flags); + const int count = mState.saveSnapshot(flags); - if (!currentSnapshot()->isIgnored()) { + if (!mState.currentlyIgnored()) { createLayer(left, top, right, bottom, paint, flags, convexMask); } @@ -643,7 +644,7 @@ void OpenGLRenderer::calculateLayerBoundsAndClip(Rect& bounds, Rect& clip, bool currentTransform()->mapRect(bounds); // Layers only make sense if they are in the framebuffer's bounds - if (bounds.intersect(*currentClipRect())) { + if (bounds.intersect(*mState.currentClipRect())) { // We cannot work with sub-pixels in this case bounds.snapToPixelBoundaries(); @@ -677,17 +678,17 @@ void OpenGLRenderer::updateSnapshotIgnoreForLayer(const Rect& bounds, const Rect if (bounds.isEmpty() || bounds.getWidth() > mCaches.maxTextureSize || bounds.getHeight() > mCaches.maxTextureSize || (fboLayer && clip.isEmpty())) { - mSnapshot->empty = fboLayer; + writableSnapshot()->empty = fboLayer; } else { - mSnapshot->invisible = mSnapshot->invisible || (alpha <= 0 && fboLayer); + writableSnapshot()->invisible = writableSnapshot()->invisible || (alpha <= 0 && fboLayer); } } int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float bottom, const SkPaint* paint, int flags) { - const int count = saveSnapshot(flags); + const int count = mState.saveSnapshot(flags); - if (!currentSnapshot()->isIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) { + if (!mState.currentlyIgnored() && (flags & SkCanvas::kClipToLayer_SaveFlag)) { // initialize the snapshot as though it almost represents an FBO layer so deferred draw // operations will be able to store and restore the current clip and transform info, and // quick rejection will be correct (for display lists) @@ -697,11 +698,11 @@ int OpenGLRenderer::saveLayerDeferred(float left, float top, float right, float calculateLayerBoundsAndClip(bounds, clip, true); updateSnapshotIgnoreForLayer(bounds, clip, true, getAlphaDirect(paint)); - if (!currentSnapshot()->isIgnored()) { - mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); - mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); - mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight()); - mSnapshot->roundRectClipState = NULL; + if (!mState.currentlyIgnored()) { + writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f); + writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom); + writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight()); + writableSnapshot()->roundRectClipState = NULL; } } @@ -773,7 +774,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto updateSnapshotIgnoreForLayer(bounds, clip, fboLayer, getAlphaDirect(paint)); // Bail out if we won't draw in this snapshot - if (currentSnapshot()->isIgnored()) { + if (mState.currentlyIgnored()) { return false; } @@ -793,8 +794,8 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache // Save the layer in the snapshot - mSnapshot->flags |= Snapshot::kFlagIsLayer; - mSnapshot->layer = layer; + writableSnapshot()->flags |= Snapshot::kFlagIsLayer; + writableSnapshot()->layer = layer; ATRACE_FORMAT_BEGIN("%ssaveLayer %ux%u", fboLayer ? "" : "unclipped ", @@ -832,13 +833,13 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) { layer->clipRect.set(clip); layer->setFbo(mCaches.fboCache.get()); - mSnapshot->region = &mSnapshot->layer->region; - mSnapshot->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer; - mSnapshot->fbo = layer->getFbo(); - mSnapshot->resetTransform(-bounds.left, -bounds.top, 0.0f); - mSnapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom); - mSnapshot->initializeViewport(bounds.getWidth(), bounds.getHeight()); - mSnapshot->roundRectClipState = NULL; + writableSnapshot()->region = &writableSnapshot()->layer->region; + writableSnapshot()->flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer; + writableSnapshot()->fbo = layer->getFbo(); + writableSnapshot()->resetTransform(-bounds.left, -bounds.top, 0.0f); + writableSnapshot()->resetClip(clip.left, clip.top, clip.right, clip.bottom); + writableSnapshot()->initializeViewport(bounds.getWidth(), bounds.getHeight()); + writableSnapshot()->roundRectClipState = NULL; endTiling(); debugOverdraw(false, false); @@ -885,7 +886,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto const bool fboLayer = removed.flags & Snapshot::kFlagIsFboLayer; bool clipRequired = false; - calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom, + mState.calculateQuickRejectForScissor(rect.left, rect.top, rect.right, rect.bottom, &clipRequired, NULL, false); // safely ignore return, should never be rejected mCaches.setScissorEnabled(mScissorOptimizationDisabled || clipRequired); @@ -930,7 +931,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto save(0); // the layer contains screen buffer content that shouldn't be alpha modulated // (and any necessary alpha modulation was handled drawing into the layer) - mSnapshot->alpha = 1.0f; + writableSnapshot()->alpha = 1.0f; composeLayerRect(layer, rect, true); restore(); } @@ -1038,13 +1039,13 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) * operations are correctly counted twice for overdraw. NOTE: assumes composeLayerRegion only used * by saveLayer's restore */ -#define DRAW_DOUBLE_STENCIL_IF(COND, DRAW_COMMAND) { \ - DRAW_COMMAND; \ - if (CC_UNLIKELY(mCaches.debugOverdraw && getTargetFbo() == 0 && COND)) { \ - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \ - DRAW_COMMAND; \ - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \ - } \ +#define DRAW_DOUBLE_STENCIL_IF(COND, DRAW_COMMAND) { \ + DRAW_COMMAND; \ + if (CC_UNLIKELY(mCaches.debugOverdraw && onGetTargetFbo() == 0 && COND)) { \ + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); \ + DRAW_COMMAND; \ + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); \ + } \ } #define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND) @@ -1273,7 +1274,7 @@ void OpenGLRenderer::dirtyLayer(const float left, const float top, } void OpenGLRenderer::dirtyLayerUnchecked(Rect& bounds, Region* region) { - if (bounds.intersect(*currentClipRect())) { + if (bounds.intersect(*mState.currentClipRect())) { bounds.snapToPixelBoundaries(); android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom); if (!dirty.isEmpty()) { @@ -1301,7 +1302,7 @@ void OpenGLRenderer::clearLayerRegions() { const size_t count = mLayers.size(); if (count == 0) return; - if (!currentSnapshot()->isIgnored()) { + if (!mState.currentlyIgnored()) { EVENT_LOGD("clearLayerRegions"); // Doing several glScissor/glClear here can negatively impact // GPUs with a tiler architecture, instead we draw quads with @@ -1357,7 +1358,7 @@ void OpenGLRenderer::clearLayerRegions() { /////////////////////////////////////////////////////////////////////////////// bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDeferFlags) { - const Rect* currentClip = currentClipRect(); + const Rect* currentClip = mState.currentClipRect(); const mat4* currentMatrix = currentTransform(); if (stateDeferFlags & kStateDeferFlag_Draw) { @@ -1410,12 +1411,12 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore) { setMatrix(state.mMatrix); - mSnapshot->alpha = state.mAlpha; + writableSnapshot()->alpha = state.mAlpha; mDrawModifiers = state.mDrawModifiers; - mSnapshot->roundRectClipState = state.mRoundRectClipState; + writableSnapshot()->roundRectClipState = state.mRoundRectClipState; if (state.mClipValid && !skipClipRestore) { - mSnapshot->setClip(state.mClip.left, state.mClip.top, + writableSnapshot()->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom); dirtyClip(); } @@ -1430,9 +1431,9 @@ void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state, bool */ void OpenGLRenderer::setupMergedMultiDraw(const Rect* clipRect) { if (clipRect != NULL) { - mSnapshot->setClip(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); + writableSnapshot()->setClip(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom); } else { - mSnapshot->setClip(0, 0, getWidth(), getHeight()); + writableSnapshot()->setClip(0, 0, mState.getWidth(), mState.getHeight()); } dirtyClip(); mCaches.setScissorEnabled(clipRect != NULL || mScissorOptimizationDisabled); @@ -1443,12 +1444,12 @@ void OpenGLRenderer::setupMergedMultiDraw(const Rect* clipRect) { /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setScissorFromClip() { - Rect clip(*currentClipRect()); + Rect clip(*mState.currentClipRect()); clip.snapToPixelBoundaries(); if (mCaches.setScissor(clip.left, getViewportHeight() - clip.bottom, clip.getWidth(), clip.getHeight())) { - mDirtyClip = false; + mState.setDirtyClip(false); } } @@ -1484,7 +1485,7 @@ void OpenGLRenderer::setStencilFromClip() { // NOTE: The order here is important, we must set dirtyClip to false // before any draw call to avoid calling back into this method - mDirtyClip = false; + mState.setDirtyClip(false); ensureStencilBuffer(); @@ -1553,7 +1554,7 @@ bool OpenGLRenderer::quickRejectSetupScissor(float left, float top, float right, bool clipRequired = false; bool roundRectClipRequired = false; - if (calculateQuickRejectForScissor(left, top, right, bottom, + if (mState.calculateQuickRejectForScissor(left, top, right, bottom, &clipRequired, &roundRectClipRequired, snapOut)) { return true; } @@ -1585,7 +1586,7 @@ void OpenGLRenderer::setupDraw(bool clearLayer) { if (clearLayer) clearLayerRegions(); // Make sure setScissor & setStencil happen at the beginning of // this method - if (mDirtyClip) { + if (mState.getDirtyClip()) { if (mCaches.scissorEnabled) { setScissorFromClip(); } @@ -1723,7 +1724,7 @@ void OpenGLRenderer::setupDrawProgram() { useProgram(mCaches.programCache.get(mDescription)); if (mDescription.hasRoundRectClip) { // TODO: avoid doing this repeatedly, stashing state pointer in program - const RoundRectClipState* state = mSnapshot->roundRectClipState; + const RoundRectClipState* state = writableSnapshot()->roundRectClipState; const Rect& innerRect = state->innerRect; glUniform4f(mCaches.currentProgram->getUniform("roundRectInnerRectLTRB"), innerRect.left, innerRect.top, @@ -1751,7 +1752,7 @@ void OpenGLRenderer::setupDrawModelView(ModelViewMode mode, bool offset, bool dirty = right - left > 0.0f && bottom - top > 0.0f; const Matrix4& transformMatrix = ignoreTransform ? Matrix4::identity() : *currentTransform(); - mCaches.currentProgram->set(mSnapshot->getOrthoMatrix(), mModelViewMatrix, transformMatrix, offset); + mCaches.currentProgram->set(writableSnapshot()->getOrthoMatrix(), mModelViewMatrix, transformMatrix, offset); if (dirty && mTrackDirtyRegions) { if (!ignoreTransform) { dirtyLayer(left, top, right, bottom, *currentTransform()); @@ -1942,7 +1943,7 @@ void OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t return; } - DeferredDisplayList deferredList(*currentClipRect()); + DeferredDisplayList deferredList(*mState.currentClipRect()); DeferStateStruct deferStruct(deferredList, *this, replayFlags); renderNode->defer(deferStruct, 0); @@ -2056,7 +2057,7 @@ void OpenGLRenderer::drawBitmapData(const SkBitmap* bitmap, const SkPaint* paint void OpenGLRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight, const float* vertices, const int* colors, const SkPaint* paint) { - if (!vertices || currentSnapshot()->isIgnored()) { + if (!vertices || mState.currentlyIgnored()) { return; } @@ -2369,7 +2370,7 @@ void OpenGLRenderer::drawVertexBuffer(float translateX, float translateY, setupDraw(); setupDrawNoTexture(); if (isAA) setupDrawVertexAlpha((displayFlags & kVertexBuffer_ShadowInterp)); - setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); + setupDrawColor(color, ((color >> 24) & 0xFF) * writableSnapshot()->alpha); setupDrawColorFilter(getColorFilter(paint)); setupDrawShader(getShader(paint)); setupDrawBlending(paint, isAA); @@ -2445,7 +2446,7 @@ void OpenGLRenderer::drawConvexPath(const SkPath& path, const SkPaint* paint) { * memory transfer by removing need for degenerate vertices. */ void OpenGLRenderer::drawLines(const float* points, int count, const SkPaint* paint) { - if (currentSnapshot()->isIgnored() || count < 4) return; + if (mState.currentlyIgnored() || count < 4) return; count &= ~0x3; // round down to nearest four @@ -2462,7 +2463,7 @@ void OpenGLRenderer::drawLines(const float* points, int count, const SkPaint* pa } void OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* paint) { - if (currentSnapshot()->isIgnored() || count < 2) return; + if (mState.currentlyIgnored() || count < 2) return; count &= ~0x1; // round down to nearest two @@ -2482,9 +2483,9 @@ void OpenGLRenderer::drawPoints(const float* points, int count, const SkPaint* p void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { // No need to check against the clip, we fill the clip region - if (currentSnapshot()->isIgnored()) return; + if (mState.currentlyIgnored()) return; - Rect clip(*currentClipRect()); + Rect clip(*mState.currentClipRect()); clip.snapToPixelBoundaries(); SkPaint paint; @@ -2511,7 +2512,7 @@ void OpenGLRenderer::drawShape(float left, float top, const PathTexture* texture void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, const SkPaint* p) { - if (currentSnapshot()->isIgnored() + if (mState.currentlyIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || paintWillNotDraw(*p)) { return; @@ -2530,7 +2531,7 @@ void OpenGLRenderer::drawRoundRect(float left, float top, float right, float bot } void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p) { - if (currentSnapshot()->isIgnored() + if (mState.currentlyIgnored() || quickRejectSetupScissor(x - radius, y - radius, x + radius, y + radius, p) || paintWillNotDraw(*p)) { return; @@ -2552,7 +2553,7 @@ void OpenGLRenderer::drawCircle(float x, float y, float radius, const SkPaint* p void OpenGLRenderer::drawOval(float left, float top, float right, float bottom, const SkPaint* p) { - if (currentSnapshot()->isIgnored() + if (mState.currentlyIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || paintWillNotDraw(*p)) { return; @@ -2575,7 +2576,7 @@ void OpenGLRenderer::drawOval(float left, float top, float right, float bottom, void OpenGLRenderer::drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool useCenter, const SkPaint* p) { - if (currentSnapshot()->isIgnored() + if (mState.currentlyIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || paintWillNotDraw(*p)) { return; @@ -2610,7 +2611,7 @@ void OpenGLRenderer::drawArc(float left, float top, float right, float bottom, void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) { - if (currentSnapshot()->isIgnored() + if (mState.currentlyIgnored() || quickRejectSetupScissor(left, top, right, bottom, p) || paintWillNotDraw(*p)) { return; @@ -2669,7 +2670,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, const float sx = x - shadow->left + textShadow.dx; const float sy = y - shadow->top + textShadow.dy; - const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * mSnapshot->alpha; + const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * writableSnapshot()->alpha; if (getShader(paint)) { textShadow.color = SK_ColorWHITE; } @@ -2693,13 +2694,13 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, } bool OpenGLRenderer::canSkipText(const SkPaint* paint) const { - float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * mSnapshot->alpha; + float alpha = (hasTextShadow(paint) ? 1.0f : paint->getAlpha()) * currentSnapshot()->alpha; return alpha == 0.0f && getXfermode(paint->getXfermode()) == SkXfermode::kSrcOver_Mode; } void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, const float* positions, const SkPaint* paint) { - if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) { + if (text == NULL || count == 0 || mState.currentlyIgnored() || canSkipText(paint)) { return; } @@ -2737,7 +2738,7 @@ void OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count, } fontRenderer.setTextureFiltering(linearFilter); - const Rect* clip = pureTranslate ? mSnapshot->clipRect : &mSnapshot->getLocalClip(); + const Rect* clip = pureTranslate ? writableSnapshot()->clipRect : &writableSnapshot()->getLocalClip(); Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); const bool hasActiveLayer = hasLayer(); @@ -2777,6 +2778,69 @@ bool OpenGLRenderer::findBestFontTransform(const mat4& transform, SkMatrix* outM return true; } +int OpenGLRenderer::getSaveCount() const { + return mState.getSaveCount(); +} + +int OpenGLRenderer::save(int flags) { + return mState.save(flags); +} + +void OpenGLRenderer::restore() { + return mState.restore(); +} + +void OpenGLRenderer::restoreToCount(int saveCount) { + return mState.restoreToCount(saveCount); +} + +void OpenGLRenderer::translate(float dx, float dy, float dz) { + return mState.translate(dx, dy, dz); +} + +void OpenGLRenderer::rotate(float degrees) { + return mState.rotate(degrees); +} + +void OpenGLRenderer::scale(float sx, float sy) { + return mState.scale(sx, sy); +} + +void OpenGLRenderer::skew(float sx, float sy) { + return mState.skew(sx, sy); +} + +void OpenGLRenderer::setMatrix(const Matrix4& matrix) { + mState.setMatrix(matrix); +} + +void OpenGLRenderer::concatMatrix(const Matrix4& matrix) { + mState.concatMatrix(matrix); +} + +bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { + return mState.clipRect(left, top, right, bottom, op); +} + +bool OpenGLRenderer::clipPath(const SkPath* path, SkRegion::Op op) { + return mState.clipPath(path, op); +} + +bool OpenGLRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) { + return mState.clipRegion(region, op); +} + +void OpenGLRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { + mState.setClippingOutline(allocator, outline); +} + +void OpenGLRenderer::setClippingRoundRect(LinearAllocator& allocator, + const Rect& rect, float radius, bool highPriority) { + mState.setClippingRoundRect(allocator, rect, radius, highPriority); +} + + + void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, const float* positions, const SkPaint* paint, float totalAdvance, const Rect& bounds, DrawOpMode drawOpMode) { @@ -2784,7 +2848,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float if (drawOpMode == kDrawOpMode_Immediate) { // The checks for corner-case ignorable text and quick rejection is only done for immediate // drawing as ops from DeferredDisplayList are already filtered for these - if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint) || + if (text == NULL || count == 0 || mState.currentlyIgnored() || canSkipText(paint) || quickRejectSetupScissor(bounds)) { return; } @@ -2834,7 +2898,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float fontRenderer.setTextureFiltering(linearFilter); // TODO: Implement better clipping for scaled/rotated text - const Rect* clip = !pureTranslate ? NULL : currentClipRect(); + const Rect* clip = !pureTranslate ? NULL : mState.currentClipRect(); Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); bool status; @@ -2866,7 +2930,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, const SkPath* path, float hOffset, float vOffset, const SkPaint* paint) { - if (text == NULL || count == 0 || currentSnapshot()->isIgnored() || canSkipText(paint)) { + if (text == NULL || count == 0 || mState.currentlyIgnored() || canSkipText(paint)) { return; } @@ -2882,7 +2946,7 @@ void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, getAlphaAndMode(paint, &alpha, &mode); TextSetupFunctor functor(this, 0.0f, 0.0f, false, alpha, mode, paint); - const Rect* clip = &mSnapshot->getLocalClip(); + const Rect* clip = &writableSnapshot()->getLocalClip(); Rect bounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); const bool hasActiveLayer = hasLayer(); @@ -2899,7 +2963,7 @@ void OpenGLRenderer::drawTextOnPath(const char* text, int bytesCount, int count, } void OpenGLRenderer::drawPath(const SkPath* path, const SkPaint* paint) { - if (currentSnapshot()->isIgnored()) return; + if (mState.currentlyIgnored()) return; mCaches.activeTexture(0); @@ -2929,7 +2993,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) { } bool clipRequired = false; - const bool rejected = calculateQuickRejectForScissor(x, y, + const bool rejected = mState.calculateQuickRejectForScissor(x, y, x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired, NULL, false); if (rejected) { @@ -3114,7 +3178,7 @@ void OpenGLRenderer::drawTextDecorations(float underlineWidth, float x, float y, } void OpenGLRenderer::drawRects(const float* rects, int count, const SkPaint* paint) { - if (currentSnapshot()->isIgnored()) { + if (mState.currentlyIgnored()) { return; } @@ -3131,7 +3195,7 @@ static void mapPointFakeZ(Vector3& point, const mat4& transformXY, const mat4& t void OpenGLRenderer::drawShadow(float casterAlpha, const VertexBuffer* ambientShadowVertexBuffer, const VertexBuffer* spotShadowVertexBuffer) { - if (currentSnapshot()->isIgnored()) return; + if (mState.currentlyIgnored()) return; // TODO: use quickRejectWithScissor. For now, always force enable scissor. mCaches.enableScissor(); @@ -3373,7 +3437,7 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, ProgramDescription& description, bool swapSrcDst) { - if (mSnapshot->roundRectClipState != NULL /*&& !mSkipOutlineClip*/) { + if (writableSnapshot()->roundRectClipState != NULL /*&& !mSkipOutlineClip*/) { blend = true; mDescription.hasRoundRectClip = true; } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 65d6deb..fde9e0f 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -38,13 +38,14 @@ #include <androidfw/ResourceTypes.h> +#include "CanvasState.h" #include "Debug.h" #include "Extensions.h" #include "Matrix.h" #include "Program.h" #include "Rect.h" +#include "Renderer.h" #include "Snapshot.h" -#include "StatefulBaseRenderer.h" #include "UvMapper.h" #include "Vertex.h" #include "Caches.h" @@ -116,7 +117,7 @@ enum ModelViewMode { /** * OpenGL Renderer implementation. */ -class OpenGLRenderer : public StatefulBaseRenderer { +class OpenGLRenderer : public Renderer, public CanvasStateClient { public: OpenGLRenderer(RenderState& renderState); virtual ~OpenGLRenderer(); @@ -125,8 +126,10 @@ public: void initLight(const Vector3& lightCenter, float lightRadius, uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha); - virtual void onViewportInitialized(); virtual void prepareDirty(float left, float top, float right, float bottom, bool opaque); + virtual void prepare(bool opaque) { + prepareDirty(0.0f, 0.0f, mState.getWidth(), mState.getHeight(), opaque); + } virtual bool finish(); virtual void callDrawGLFunction(Functor* functor, Rect& dirty); @@ -218,20 +221,16 @@ public: } // simple rect clip - bool isCurrentClipSimple() { - return mSnapshot->clipRegion->isEmpty(); - } + bool isCurrentClipSimple() { return mState.isCurrentClipSimple(); } - int getViewportWidth() { return currentSnapshot()->getViewportWidth(); } - int getViewportHeight() { return currentSnapshot()->getViewportHeight(); } + int getViewportWidth() { return mState.getViewportWidth(); } + int getViewportHeight() { return mState.getViewportHeight(); } /** * Scales the alpha on the current snapshot. This alpha value will be modulated * with other alpha values when drawing primitives. */ - void scaleAlpha(float alpha) { - mSnapshot->alpha *= alpha; - } + void scaleAlpha(float alpha) { mState.scaleAlpha(alpha); } /** * Inserts a named event marker in the stream of GL commands. @@ -328,11 +327,63 @@ public: } #endif - const Vector3& getLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); } + const Vector3& getLightCenter() const { return mState.currentLightCenter(); } float getLightRadius() const { return mLightRadius; } uint8_t getAmbientShadowAlpha() const { return mAmbientShadowAlpha; } uint8_t getSpotShadowAlpha() const { return mSpotShadowAlpha; } + /////////////////////////////////////////////////////////////////// + /// State manipulation + + virtual void setViewport(int width, int height) { mState.setViewport(width, height); } + + virtual int getSaveCount() const; + virtual int save(int flags); + virtual void restore(); + virtual void restoreToCount(int saveCount); + + virtual void getMatrix(SkMatrix* outMatrix) const { mState.getMatrix(outMatrix); } + virtual void setMatrix(const SkMatrix& matrix) { mState.setMatrix(matrix); } + virtual void concatMatrix(const SkMatrix& matrix) { mState.concatMatrix(matrix); } + + virtual void translate(float dx, float dy, float dz = 0.0f); + virtual void rotate(float degrees); + virtual void scale(float sx, float sy); + virtual void skew(float sx, float sy); + + void setMatrix(const Matrix4& matrix); // internal only convenience method + void concatMatrix(const Matrix4& matrix); // internal only convenience method + + virtual const Rect& getLocalClipBounds() const { return mState.getLocalClipBounds(); } + const Rect& getRenderTargetClipBounds() const { return mState.getRenderTargetClipBounds(); } + virtual bool quickRejectConservative(float left, float top, float right, float bottom) const { + return mState.quickRejectConservative(left, top, right, bottom); + } + + virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); + virtual bool clipPath(const SkPath* path, SkRegion::Op op); + virtual bool clipRegion(const SkRegion* region, SkRegion::Op op); + + /** + * Does not support different clipping Ops (that is, every call to setClippingOutline is + * effectively using SkRegion::kReplaceOp) + * + * The clipping outline is independent from the regular clip. + */ + void setClippingOutline(LinearAllocator& allocator, const Outline* outline); + void setClippingRoundRect(LinearAllocator& allocator, + const Rect& rect, float radius, bool highPriority = true); + + inline bool hasRectToRectTransform() const { return mState.hasRectToRectTransform(); } + inline const mat4* currentTransform() const { return mState.currentTransform(); } + + /////////////////////////////////////////////////////////////////// + /// CanvasStateClient interface + + virtual void onViewportInitialized(); + virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored); + virtual GLuint onGetTargetFbo() const { return 0; } + protected: /** * Perform the setup specific to a frame. This method does not @@ -396,22 +447,16 @@ protected: * Returns the region of the current layer. */ virtual Region* getRegion() const { - return mSnapshot->region; + return mState.currentRegion(); } /** * Indicates whether rendering is currently targeted at a layer. */ virtual bool hasLayer() const { - return (mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region; + return (mState.currentFlags() & Snapshot::kFlagFboTarget) && mState.currentRegion(); } - /** - * Returns the name of the FBO this renderer is rendering into. - */ - virtual GLuint getTargetFbo() const { - return 0; - } /** * Renders the specified layer as a textured quad. @@ -464,6 +509,8 @@ protected: inline RenderState& renderState() { return mRenderState; } + CanvasState mState; + private: /** * Discards the content of the framebuffer if supported by the driver. @@ -499,8 +546,6 @@ private: */ void endTiling(); - void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored); - /** * Sets the clipping rectangle using glScissor. The clip is defined by * the current snapshot's clipRect member. @@ -916,9 +961,7 @@ private: /** * Should be invoked every time the glScissor is modified. */ - inline void dirtyClip() { - mDirtyClip = true; - } + inline void dirtyClip() { mState.setDirtyClip(true); } inline const UvMapper& getMapper(const Texture* texture) { return texture && texture->uvMapper ? *texture->uvMapper : mUvMapper; @@ -932,6 +975,8 @@ private: Texture* getTexture(const SkBitmap* bitmap); bool reportAndClearDirty() { bool ret = mDirty; mDirty = false; return ret; } + inline Snapshot* writableSnapshot() { return mState.writableSnapshot(); } + inline const Snapshot* currentSnapshot() const { return mState.currentSnapshot(); } /** * Model-view matrix used to position/size objects diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h deleted file mode 100644 index 612992f..0000000 --- a/libs/hwui/StatefulBaseRenderer.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HWUI_STATEFUL_BASE_RENDERER_H -#define ANDROID_HWUI_STATEFUL_BASE_RENDERER_H - -#include <utils/RefBase.h> - -#include "Renderer.h" -#include "Snapshot.h" - -namespace android { -namespace uirenderer { - -/** - * Abstract Renderer subclass, which implements Canvas state methods. - * - * Manages the Snapshot stack, implementing matrix, save/restore, and clipping methods in the - * Renderer interface. Drawing and recording classes that extend StatefulBaseRenderer will have - * different use cases: - * - * Drawing subclasses (i.e. OpenGLRenderer) can query attributes (such as transform) or hook into - * changes (e.g. save/restore) with minimal surface area for manipulating the stack itself. - * - * Recording subclasses (i.e. DisplayListRenderer) can both record and pass through state operations - * to StatefulBaseRenderer, so that not only will querying operations work (getClip/Matrix), but so - * that quickRejection can also be used. - */ -class StatefulBaseRenderer : public Renderer { -public: - StatefulBaseRenderer(); - - virtual void prepare(bool opaque) { - prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque); - } - - /** - * Initialize the first snapshot, computing the projection matrix, and stores the dimensions of - * the render target. - */ - virtual void setViewport(int width, int height); - void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom, - const Vector3& lightCenter); - - // getters - bool hasRectToRectTransform() const { - return CC_LIKELY(currentTransform()->rectToRect()); - } - - // Save (layer) - virtual int getSaveCount() const { return mSaveCount; } - virtual int save(int flags); - virtual void restore(); - virtual void restoreToCount(int saveCount); - //virtual int saveLayer(float left, float top, float right, float bottom, - // int alpha, SkXfermode::Mode mode, int flags); - - // Matrix - virtual void getMatrix(SkMatrix* outMatrix) const; - virtual void translate(float dx, float dy, float dz = 0.0f); - virtual void rotate(float degrees); - virtual void scale(float sx, float sy); - virtual void skew(float sx, float sy); - - virtual void setMatrix(const SkMatrix& matrix); - void setMatrix(const Matrix4& matrix); // internal only convenience method - virtual void concatMatrix(const SkMatrix& matrix); - void concatMatrix(const Matrix4& matrix); // internal only convenience method - - // Clip - virtual const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); } - - virtual bool quickRejectConservative(float left, float top, float right, float bottom) const; - - virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op); - virtual bool clipPath(const SkPath* path, SkRegion::Op op); - virtual bool clipRegion(const SkRegion* region, SkRegion::Op op); - - /** - * Does not support different clipping Ops (that is, every call to setClippingOutline is - * effectively using SkRegion::kReplaceOp) - * - * The clipping outline is independent from the regular clip. - */ - void setClippingOutline(LinearAllocator& allocator, const Outline* outline); - void setClippingRoundRect(LinearAllocator& allocator, - const Rect& rect, float radius, bool highPriority = true); - - inline const mat4* currentTransform() const { - return mSnapshot->transform; - } - -protected: - const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); } - - int getWidth() { return mWidth; } - int getHeight() { return mHeight; } - - // Save - int saveSnapshot(int flags); - void restoreSnapshot(); - - // allows subclasses to control what value is stored in snapshot's fbo field in - // initializeSaveStack - virtual GLuint getTargetFbo() const { - return -1; - } - - // Clip - bool calculateQuickRejectForScissor(float left, float top, float right, float bottom, - bool* clipRequired, bool* roundRectClipRequired, bool snapOut) const; - - /** - * Called just after a restore has occurred. The 'removed' snapshot popped from the stack, - * 'restored' snapshot has become the top/current. - * - * Subclasses can override this method to handle layer restoration - */ - virtual void onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}; - - virtual void onViewportInitialized() {}; - - inline const Rect* currentClipRect() const { - return mSnapshot->clipRect; - } - - inline const Snapshot* currentSnapshot() const { - return mSnapshot != NULL ? mSnapshot.get() : mFirstSnapshot.get(); - } - - inline const Snapshot* firstSnapshot() const { - return mFirstSnapshot.get(); - } - - // indicites that the clip has been changed since the last time it was consumed - bool mDirtyClip; - -private: - // Dimensions of the drawing surface - int mWidth, mHeight; - - // Number of saved states - int mSaveCount; - - // Base state - sp<Snapshot> mFirstSnapshot; - -protected: - // Current state - // TODO: should become private, once hooks needed by OpenGLRenderer are added - sp<Snapshot> mSnapshot; -}; // class StatefulBaseRenderer - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_STATEFUL_BASE_RENDERER_H |