Replace StatefulBaseRenderer inheritance with CanvasState member
Incrementally disentangles DisplayListRenderer and OpenGLRenderer.
Introduces abstract CanvasStateClient class to share three functions
between the two.
Design doc at https://docs.google.com/a/google.com/document/d/1PY1JF7AfPEF2UOUAnETS5j_4_tnJShTAMExvpCJfP8o/edit?usp=sharing.
BUG:15672762
R=djsollen@google.com,ccraik@google.com,jreck@google.com
Change-Id: Ic9fdffe18808e7d921ad06d01ea1ca25b2ad6f23
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 @@
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 @@
DrawProfiler.cpp \
Extensions.cpp \
FboCache.cpp \
+ FontRenderer.cpp \
+ GammaFontRenderer.cpp \
GradientCache.cpp \
Image.cpp \
Interpolator.cpp \
@@ -62,7 +63,6 @@
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
similarity index 71%
rename from libs/hwui/StatefulBaseRenderer.cpp
rename to 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 @@
///////////////////////////////////////////////////////////////////////////////
/**
- * 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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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::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 @@
* @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 @@
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 @@
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 uirenderer {
DisplayListRenderer::DisplayListRenderer()
- : mCaches(Caches::getInstance())
+ : mState(*this)
+ , mCaches(Caches::getInstance())
, mDisplayListData(NULL)
, mTranslateX(0.0f)
, mTranslateY(0.0f)
@@ -66,10 +67,10 @@
"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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
/**
* 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 @@
// 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 @@
// ----------------------------------------------------------------------------
// 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 @@
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 @@
// 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 @@
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 @@
return retval;
}
-GLuint LayerRenderer::getTargetFbo() const {
+GLuint LayerRenderer::onGetTargetFbo() const {
return mLayer->getFbo();
}
@@ -116,7 +116,7 @@
///////////////////////////////////////////////////////////////////////////////
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 @@
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 @@
///////////////////////////////////////////////////////////////////////////////
OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
- : mFrameStarted(false)
+ : mState(*this)
+ , mFrameStarted(false)
, mCaches(Caches::getInstance())
, mExtensions(Extensions::getInstance())
, mRenderState(renderState)
@@ -205,7 +206,7 @@
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 @@
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 @@
// 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 @@
// 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::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 @@
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::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 @@
if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
mLayerUpdates.clear();
- mRenderState.bindFramebuffer(getTargetFbo());
+ mRenderState.bindFramebuffer(onGetTargetFbo());
}
endMark();
}
@@ -546,7 +547,7 @@
}
mLayerUpdates.clear();
- mRenderState.bindFramebuffer(getTargetFbo());
+ mRenderState.bindFramebuffer(onGetTargetFbo());
endMark();
}
@@ -628,9 +629,9 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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::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 @@
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 @@
///////////////////////////////////////////////////////////////////////////////
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 @@
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::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::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 @@
// 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 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 @@
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 @@
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 @@
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 @@
return;
}
- DeferredDisplayList deferredList(*currentClipRect());
+ DeferredDisplayList deferredList(*mState.currentClipRect());
DeferStateStruct deferStruct(deferredList, *this, replayFlags);
renderNode->defer(deferStruct, 0);
@@ -2056,7 +2057,7 @@
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 @@
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 @@
* 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::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::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::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::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::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::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::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 @@
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 @@
}
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 @@
}
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 @@
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 @@
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 @@
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::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 @@
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::drawPath(const SkPath* path, const SkPaint* paint) {
- if (currentSnapshot()->isIgnored()) return;
+ if (mState.currentlyIgnored()) return;
mCaches.activeTexture(0);
@@ -2929,7 +2993,7 @@
}
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::drawRects(const float* rects, int count, const SkPaint* paint) {
- if (currentSnapshot()->isIgnored()) {
+ if (mState.currentlyIgnored()) {
return;
}
@@ -3131,7 +3195,7 @@
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::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 @@
/**
* OpenGL Renderer implementation.
*/
-class OpenGLRenderer : public StatefulBaseRenderer {
+class OpenGLRenderer : public Renderer, public CanvasStateClient {
public:
OpenGLRenderer(RenderState& renderState);
virtual ~OpenGLRenderer();
@@ -125,8 +126,10 @@
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 @@
}
// 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 @@
}
#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 @@
* 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 @@
inline RenderState& renderState() { return mRenderState; }
+ CanvasState mState;
+
private:
/**
* Discards the content of the framebuffer if supported by the driver.
@@ -499,8 +546,6 @@
*/
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 @@
/**
* 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 @@
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