summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tom Hudson <tomhudson@google.com> 2014-10-10 13:38:16 -0400
committer Tom Hudson <tomhudson@google.com> 2014-11-04 17:16:36 -0500
commit984162fb7e4010b6e2908352dbff17ed47eecf06 (patch)
tree0b15f1e5bdd1485862dd1f9098e4c94bc033df77
parenta5545d24c7289c25707ffa8704b57a37cea6535a (diff)
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
-rw-r--r--libs/hwui/Android.mk8
-rw-r--r--libs/hwui/CanvasState.cpp (renamed from libs/hwui/StatefulBaseRenderer.cpp)89
-rw-r--r--libs/hwui/CanvasState.h196
-rw-r--r--libs/hwui/DisplayListRenderer.cpp35
-rw-r--r--libs/hwui/DisplayListRenderer.h32
-rw-r--r--libs/hwui/LayerRenderer.cpp4
-rw-r--r--libs/hwui/LayerRenderer.h2
-rwxr-xr-xlibs/hwui/OpenGLRenderer.cpp236
-rwxr-xr-xlibs/hwui/OpenGLRenderer.h95
-rw-r--r--libs/hwui/StatefulBaseRenderer.h170
10 files changed, 511 insertions, 356 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 5b74addb3e89..51f257f3d933 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 88d6f6802909..20cc17e9b5f2 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 000000000000..b15698e24281
--- /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 ab9ca1f19ef6..c0b8a5698bfe 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 34b0a1f9f5ae..7dd788d5825e 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 9306f135aa3f..268b9da8334e 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 47099bffc200..769ef4937e9a 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 1ac9e7bdf0ba..71b7c11ed9eb 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 65d6debe864e..fde9e0fb20ff 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 612992f0779f..000000000000
--- 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