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));