From 64e445bf74bee2098781d608cedfd723d8cc88d3 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Wed, 2 Sep 2015 14:23:49 -0700 Subject: [PATCH] CanvasState frame init refactor bug:23760482 Change-Id: Idc0802b4b8a6a3cebd20797350f4eb01bcc3fe77 --- libs/hwui/CanvasState.cpp | 29 ++++++++++------------------- libs/hwui/CanvasState.h | 15 ++++----------- libs/hwui/DisplayListCanvas.cpp | 4 ++-- libs/hwui/Layer.cpp | 13 +++++-------- libs/hwui/LayerRenderer.cpp | 12 ++++++------ libs/hwui/LayerRenderer.h | 4 ++-- libs/hwui/OpenGLRenderer.cpp | 13 +++++++------ libs/hwui/OpenGLRenderer.h | 29 ++++------------------------- libs/hwui/renderthread/CanvasContext.cpp | 6 +++--- libs/hwui/unit_tests/CanvasStateTests.cpp | 22 +++++++++++----------- 10 files changed, 54 insertions(+), 93 deletions(-) diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp index e307ad91885f..c128ca775155 100644 --- a/libs/hwui/CanvasState.cpp +++ b/libs/hwui/CanvasState.cpp @@ -34,12 +34,17 @@ CanvasState::CanvasState(CanvasStateClient& renderer) } -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 @@ void CanvasState::initializeSaveStack(float clipLeft, float clipTop, 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 b35db28eaf82..f0fb9ba8b324 100644 --- a/libs/hwui/CanvasState.h +++ b/libs/hwui/CanvasState.h @@ -71,20 +71,18 @@ public: * (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 @@ public: 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 506bfad08c1b..77bde863af51 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -54,8 +54,8 @@ void DisplayListCanvas::reset(int width, int height) { "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 e7482211b399..8d8528961794 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -236,8 +236,7 @@ void Layer::defer(const OpenGLRenderer& rootRenderer) { 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 @@ void Layer::flush() { 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 @@ void Layer::render(const OpenGLRenderer& rootRenderer) { 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 d8e6392bd07e..c63b5597f284 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -43,8 +43,8 @@ LayerRenderer::LayerRenderer(RenderState& renderState, Layer* layer) 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 @@ void LayerRenderer::prepareDirty(float left, float top, float right, float botto } 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 @@ bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* { 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 47ded7e7e0bf..e4a54b0a0520 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -50,8 +50,8 @@ public: 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 5692d7e120ff..e06e34849a91 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -113,10 +113,11 @@ void OpenGLRenderer::onViewportInitialized() { 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 @@ void OpenGLRenderer::startFrame() { 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 af85e8c72619..910af5705705 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -119,15 +119,6 @@ public: 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 @@ public: * 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 @@ protected: * 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 167380205e67..b74b5088c14f 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -248,7 +248,7 @@ void CanvasContext::draw() { 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 @@ void CanvasContext::draw() { 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 79852bebdd08..dfbf6d358ce5 100644 --- a/libs/hwui/unit_tests/CanvasStateTests.cpp +++ b/libs/hwui/unit_tests/CanvasStateTests.cpp @@ -47,8 +47,8 @@ static bool approxEqual(const Matrix4& a, const Matrix4& b) { 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, gettersAndSetters) { 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, simpleClipping) { 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, complexClipping) { 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, saveAndRestore) { 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)); -- 2.11.0