CanvasState frame init refactor
bug:23760482
Change-Id: Idc0802b4b8a6a3cebd20797350f4eb01bcc3fe77
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index e307ad9..c128ca7 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -34,12 +34,17 @@
}
-CanvasState::~CanvasState() {
-
-}
-
-void CanvasState::initializeSaveStack(float clipLeft, float clipTop,
+void CanvasState::initializeSaveStack(
+ int viewportWidth, int viewportHeight,
+ float clipLeft, float clipTop,
float clipRight, float clipBottom, const Vector3& lightCenter) {
+ if (mWidth != viewportWidth || mHeight != viewportHeight) {
+ mWidth = viewportWidth;
+ mHeight = viewportHeight;
+ mFirstSnapshot->initializeViewport(viewportWidth, viewportHeight);
+ mCanvas.onViewportInitialized();
+ }
+
mSnapshot = new Snapshot(mFirstSnapshot,
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom);
@@ -48,20 +53,6 @@
mSaveCount = 1;
}
-void CanvasState::setViewport(int width, int height) {
- mWidth = width;
- mHeight = height;
- mFirstSnapshot->initializeViewport(width, height);
- mCanvas.onViewportInitialized();
-
- // create a temporary 1st snapshot, so old snapshots are released,
- // and viewport can be queried safely.
- // TODO: remove, combine viewport + save stack initialization
- mSnapshot = new Snapshot(mFirstSnapshot,
- SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
- mSaveCount = 1;
-}
-
///////////////////////////////////////////////////////////////////////////////
// Save (layer)
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/CanvasState.h b/libs/hwui/CanvasState.h
index b35db28..f0fb9ba 100644
--- a/libs/hwui/CanvasState.h
+++ b/libs/hwui/CanvasState.h
@@ -71,20 +71,18 @@
* (getClip/Matrix), but so that quickRejection can also be used.
*/
-class ANDROID_API CanvasState {
+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,
+ void initializeSaveStack(int viewportWidth, int viewportHeight,
+ 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());
}
@@ -159,16 +157,11 @@
int getHeight() const { return mHeight; }
bool clipIsSimple() const { return currentSnapshot()->clipIsSimple(); }
- inline const Snapshot* currentSnapshot() const {
- return mSnapshot != nullptr ? mSnapshot.get() : mFirstSnapshot.get();
- }
+ inline const Snapshot* currentSnapshot() const { return mSnapshot.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;
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index 506bfad..77bde86 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -54,8 +54,8 @@
"prepareDirty called a second time during a recording!");
mDisplayListData = new DisplayListData();
- mState.setViewport(width, height);
- mState.initializeSaveStack(0, 0, mState.getWidth(), mState.getHeight(), Vector3());
+ mState.initializeSaveStack(width, height,
+ 0, 0, width, height, Vector3());
mDeferredBarrierType = kBarrier_InOrder;
mState.setDirtyClip(false);
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index e748221..8d85289 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -236,8 +236,7 @@
DeferStateStruct deferredState(*deferredList, *renderer,
RenderNode::kReplayFlag_ClipChildren);
- renderer->setViewport(width, height);
- renderer->setupFrameState(dirtyRect.left, dirtyRect.top,
+ renderer->setupFrameState(width, height, dirtyRect.left, dirtyRect.top,
dirtyRect.right, dirtyRect.bottom, !isBlend());
renderNode->computeOrdering();
@@ -258,9 +257,8 @@
ATRACE_LAYER_WORK("Issue");
renderer->startMark((renderNode.get() != nullptr) ? renderNode->getName() : "Layer");
- renderer->setViewport(layer.getWidth(), layer.getHeight());
- renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
- !isBlend());
+ renderer->prepareDirty(layer.getWidth(), layer.getHeight(),
+ dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, !isBlend());
deferredList->flush(*renderer, dirtyRect);
@@ -277,9 +275,8 @@
ATRACE_LAYER_WORK("Direct-Issue");
updateLightPosFromRenderer(rootRenderer);
- renderer->setViewport(layer.getWidth(), layer.getHeight());
- renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
- !isBlend());
+ renderer->prepareDirty(layer.getWidth(), layer.getHeight(),
+ dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom, !isBlend());
renderer->drawRenderNode(renderNode.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren);
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index d8e6392..c63b559 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -43,8 +43,8 @@
LayerRenderer::~LayerRenderer() {
}
-void LayerRenderer::prepareDirty(float left, float top, float right, float bottom,
- bool opaque) {
+void LayerRenderer::prepareDirty(int viewportWidth, int viewportHeight,
+ float left, float top, float right, float bottom, bool opaque) {
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
mRenderState.bindFramebuffer(mLayer->getFbo());
@@ -64,7 +64,8 @@
}
mLayer->clipRect.set(dirty);
- OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
+ OpenGLRenderer::prepareDirty(viewportWidth, viewportHeight,
+ dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
}
void LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
@@ -430,9 +431,8 @@
{
LayerRenderer renderer(renderState, layer);
- renderer.setViewport(bitmap->width(), bitmap->height());
- renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
- bitmap->width(), bitmap->height(), !layer->isBlend());
+ renderer.OpenGLRenderer::prepareDirty(bitmap->width(), bitmap->height(),
+ 0.0f, 0.0f, bitmap->width(), bitmap->height(), !layer->isBlend());
renderState.scissor().setEnabled(false);
renderer.translate(0.0f, bitmap->height());
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 47ded7e..e4a54b0 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -50,8 +50,8 @@
virtual ~LayerRenderer();
virtual void onViewportInitialized() override { /* do nothing */ }
- virtual void prepareDirty(float left, float top, float right, float bottom,
- bool opaque) override;
+ virtual void prepareDirty(int viewportWidth, int viewportHeight,
+ float left, float top, float right, float bottom, bool opaque) override;
virtual void clear(float left, float top, float right, float bottom, bool opaque) override;
virtual bool finish() override;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 5692d7e..e06e348 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -113,10 +113,11 @@
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
-void OpenGLRenderer::setupFrameState(float left, float top,
- float right, float bottom, bool opaque) {
+void OpenGLRenderer::setupFrameState(int viewportWidth, int viewportHeight,
+ float left, float top, float right, float bottom, bool opaque) {
mCaches.clearGarbage();
- mState.initializeSaveStack(left, top, right, bottom, mLightCenter);
+ mState.initializeSaveStack(viewportWidth, viewportHeight,
+ left, top, right, bottom, mLightCenter);
mOpaque = opaque;
mTilingClip.set(left, top, right, bottom);
}
@@ -137,10 +138,10 @@
mTilingClip.right, mTilingClip.bottom, mOpaque);
}
-void OpenGLRenderer::prepareDirty(float left, float top,
- float right, float bottom, bool opaque) {
+void OpenGLRenderer::prepareDirty(int viewportWidth, int viewportHeight,
+ float left, float top, float right, float bottom, bool opaque) {
- setupFrameState(left, top, right, bottom, opaque);
+ setupFrameState(viewportWidth, viewportHeight, left, top, right, bottom, opaque);
// Layer renderers will start the frame immediately
// The framebuffer renderer will first defer the display list
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index af85e8c..910af57 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -119,15 +119,6 @@
OpenGLRenderer(RenderState& renderState);
virtual ~OpenGLRenderer();
- /**
- * Sets the dimension of the underlying drawing surface. This method must
- * be called at least once every time the drawing surface changes size.
- *
- * @param width The width in pixels of the underlysing surface
- * @param height The height in pixels of the underlysing surface
- */
- void setViewport(int width, int height) { mState.setViewport(width, height); }
-
void initProperties();
void initLight(float lightRadius, uint8_t ambientShadowAlpha,
uint8_t spotShadowAlpha);
@@ -143,21 +134,8 @@
* and will not be cleared. If false, the target surface
* will be cleared
*/
- virtual void prepareDirty(float left, float top, float right, float bottom,
- bool opaque);
-
- /**
- * Prepares the renderer to draw a frame. This method must be invoked
- * at the beginning of each frame. When this method is invoked, the
- * entire drawing surface is assumed to be redrawn.
- *
- * @param opaque If true, the target surface is considered opaque
- * and will not be cleared. If false, the target surface
- * will be cleared
- */
- void prepare(bool opaque) {
- prepareDirty(0.0f, 0.0f, mState.getWidth(), mState.getHeight(), opaque);
- }
+ virtual void prepareDirty(int viewportWidth, int viewportHeight,
+ float left, float top, float right, float bottom, bool opaque);
/**
* Indicates the end of a frame. This method must be invoked whenever
@@ -430,7 +408,8 @@
* Perform the setup specific to a frame. This method does not
* issue any OpenGL commands.
*/
- void setupFrameState(float left, float top, float right, float bottom, bool opaque);
+ void setupFrameState(int viewportWidth, int viewportHeight,
+ float left, float top, float right, float bottom, bool opaque);
/**
* Indicates the start of rendering. This method will setup the
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 1673802..b74b508 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -248,7 +248,7 @@
Frame frame = mEglManager.beginFrame(mEglSurface);
if (frame.width() != mCanvas->getViewportWidth()
|| frame.height() != mCanvas->getViewportHeight()) {
- mCanvas->setViewport(frame.width(), frame.height());
+ // can't rely on prior content of window if viewport size changes
dirty.setEmpty();
} else if (mHaveNewSurface || frame.bufferAge() == 0) {
// New surface needs a full draw
@@ -295,8 +295,8 @@
mDamageHistory.next() = screenDirty;
mEglManager.damageFrame(frame, dirty);
- mCanvas->prepareDirty(dirty.fLeft, dirty.fTop,
- dirty.fRight, dirty.fBottom, mOpaque);
+ mCanvas->prepareDirty(frame.width(), frame.height(),
+ dirty.fLeft, dirty.fTop, dirty.fRight, dirty.fBottom, mOpaque);
Rect outBounds;
mCanvas->drawRenderNode(mRootRenderNode.get(), outBounds);
diff --git a/libs/hwui/unit_tests/CanvasStateTests.cpp b/libs/hwui/unit_tests/CanvasStateTests.cpp
index 79852be..dfbf6d3 100644
--- a/libs/hwui/unit_tests/CanvasStateTests.cpp
+++ b/libs/hwui/unit_tests/CanvasStateTests.cpp
@@ -47,8 +47,8 @@
TEST(CanvasState, gettersAndSetters) {
CanvasState state(sNullClient);
- state.setViewport(200, 200);
- state.initializeSaveStack(0, 0, state.getWidth(), state.getHeight(), Vector3());
+ state.initializeSaveStack(200, 200,
+ 0, 0, 200, 200, Vector3());
ASSERT_EQ(state.getWidth(), 200);
ASSERT_EQ(state.getHeight(), 200);
@@ -65,8 +65,8 @@
TEST(CanvasState, simpleClipping) {
CanvasState state(sNullClient);
- state.setViewport(200, 200);
- state.initializeSaveStack(0, 0, state.getWidth(), state.getHeight(), Vector3());
+ state.initializeSaveStack(200, 200,
+ 0, 0, 200, 200, Vector3());
state.clipRect(0, 0, 100, 100, SkRegion::kIntersect_Op);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 100, 100));
@@ -80,8 +80,8 @@
TEST(CanvasState, complexClipping) {
CanvasState state(sNullClient);
- state.setViewport(200, 200);
- state.initializeSaveStack(0, 0, state.getWidth(), state.getHeight(), Vector3());
+ state.initializeSaveStack(200, 200,
+ 0, 0, 200, 200, Vector3());
state.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
{
@@ -116,8 +116,8 @@
TEST(CanvasState, saveAndRestore) {
CanvasState state(sNullClient);
- state.setViewport(200, 200);
- state.initializeSaveStack(0, 0, state.getWidth(), state.getHeight(), Vector3());
+ state.initializeSaveStack(200, 200,
+ 0, 0, 200, 200, Vector3());
state.save(SkCanvas::kClip_SaveFlag);
{
@@ -140,10 +140,10 @@
TEST(CanvasState, saveAndRestoreButNotTooMuch) {
CanvasState state(sNullClient);
- state.setViewport(200, 200);
- state.initializeSaveStack(0, 0, state.getWidth(), state.getHeight(), Vector3());
+ state.initializeSaveStack(200, 200,
+ 0, 0, 200, 200, Vector3());
- state.save(SkCanvas::kMatrix_SaveFlag); // Note: clip not saved
+ state.save(SkCanvas::kMatrix_SaveFlag); // NOTE: clip not saved
{
state.clipRect(0, 0, 10, 10, SkRegion::kIntersect_Op);
ASSERT_EQ(state.getRenderTargetClipBounds(), Rect(0, 0, 10, 10));