Loading libs/hwui/BakedOpRenderer.cpp +47 −22 Original line number Diff line number Diff line Loading @@ -60,10 +60,18 @@ void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const } void BakedOpRenderer::endLayer() { mRenderTarget.offscreenBuffer->updateMeshFromRegion(); mRenderTarget.offscreenBuffer = nullptr; if (mRenderTarget.stencil) { // if stencil was used for clipping, detach it and return it to pool glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "glfbrb endlayer failed"); mCaches.renderBufferCache.put(mRenderTarget.stencil); mRenderTarget.stencil = nullptr; } mRenderTarget.lastStencilClip = nullptr; mRenderTarget.offscreenBuffer->updateMeshFromRegion(); mRenderTarget.offscreenBuffer = nullptr; // It's in drawLayerOp's hands now. // Detach the texture from the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED"); Loading @@ -75,7 +83,6 @@ void BakedOpRenderer::startFrame(uint32_t width, uint32_t height, const Rect& re LOG_ALWAYS_FATAL_IF(mRenderTarget.frameBufferId != 0, "primary framebufferId must be 0"); mRenderState.bindFramebuffer(0); setViewport(width, height); mCaches.clearGarbage(); if (!mOpaque) { clearColorBuffer(repaintRect); Loading Loading @@ -113,6 +120,7 @@ void BakedOpRenderer::endFrame(const Rect& repaintRect) { mRenderState.stencil().disable(); } mCaches.clearGarbage(); mCaches.pathCache.trim(); mCaches.tessellationCache.trim(); Loading Loading @@ -232,17 +240,25 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli mRenderState.scissor().setEnabled(clip != nullptr); if (clip) { mRenderState.scissor().set(mRenderTarget.viewportHeight, clip->rect); } if (CC_LIKELY(!Properties::debugOverdraw)) { // only modify stencil mode and content when it's not used for overdraw visualization if (CC_UNLIKELY(clip->mode != ClipMode::Rectangle)) { if (CC_UNLIKELY(clip && clip->mode != ClipMode::Rectangle)) { // NOTE: this pointer check is only safe for non-rect clips, // since rect clips may be created on the stack if (mRenderTarget.lastStencilClip != clip) { // Stencil needed, but current stencil isn't up to date mRenderTarget.lastStencilClip = clip; if (mRenderTarget.offscreenBuffer) { LOG_ALWAYS_FATAL("prepare layer stencil"); if (mRenderTarget.frameBufferId != 0 && !mRenderTarget.stencil) { OffscreenBuffer* layer = mRenderTarget.offscreenBuffer; mRenderTarget.stencil = mCaches.renderBufferCache.get( Stencil::getLayerStencilFormat(), layer->texture.width, layer->texture.height); // stencil is bound + allocated - associate it with current FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mRenderTarget.stencil->getName()); } if (clip->mode == ClipMode::RectangleList) { Loading @@ -250,12 +266,21 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli } else { setupStencilRegion(clip); } } else { // stencil is up to date - just need to ensure it's enabled (since an unclipped // or scissor-only clipped op may have been drawn, disabling the stencil) int incrementThreshold = 0; if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) { auto&& rectList = reinterpret_cast<const ClipRectList*>(clip)->rectList; incrementThreshold = rectList.getTransformedRectanglesCount(); } mRenderState.stencil().enableTest(incrementThreshold); } } else { // either scissor or no clip, so disable stencil test mRenderState.stencil().disable(); } } } // dirty offscreenbuffer if (dirtyBounds && mRenderTarget.offscreenBuffer) { Loading libs/hwui/BakedOpRenderer.h +13 −1 Original line number Diff line number Diff line Loading @@ -95,12 +95,24 @@ private: // render target state - setup by start/end layer/frame // only valid to use in between start/end pairs. struct { // If not drawing to a layer: fbo = 0, offscreenBuffer = null, // Otherwise these refer to currently painting layer's state GLuint frameBufferId = 0; OffscreenBuffer* offscreenBuffer = nullptr; // Used when drawing to a layer and using stencil clipping. otherwise null. RenderBuffer* stencil = nullptr; // value representing the ClipRectList* or ClipRegion* currently stored in // the stencil of the current render target const ClipBase* lastStencilClip = nullptr; // Size of renderable region in current render target - for layers, may not match actual // bounds of FBO texture. offscreenBuffer->texture has this information. uint32_t viewportWidth = 0; uint32_t viewportHeight = 0; Matrix4 orthoMatrix; const ClipBase* lastStencilClip = nullptr; } mRenderTarget; const LightInfo mLightInfo; Loading libs/hwui/GlopBuilder.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementC mOutGlop->mesh.vertices = { vbo, VertexAttribFlags::TextureCoord, nullptr, nullptr, nullptr, nullptr, (const void*) kMeshTextureOffset, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = elementCount; return *this; Loading libs/hwui/RecordedOp.h +2 −2 Original line number Diff line number Diff line Loading @@ -391,9 +391,9 @@ struct LayerOp : RecordedOp { LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle) : SUPER_PAINTLESS(LayerOp) , layerHandle(layerHandle) , alpha(paint->getAlpha() / 255.0f) , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f) , mode(PaintUtils::getXfermodeDirect(paint)) , colorFilter(paint->getColorFilter()) , colorFilter(paint ? paint->getColorFilter() : nullptr) , destroy(true) {} LayerOp(RenderNode& node) Loading libs/hwui/tests/common/scenes/ClippingAnimation.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -30,8 +30,6 @@ public: sp<RenderNode> card; void createContent(int width, int height, TestCanvas& canvas) override { canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode); canvas.insertReorderBarrier(true); card = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, TestCanvas& canvas) { canvas.save(SkCanvas::kMatrixClip_SaveFlag); Loading @@ -53,10 +51,12 @@ public: canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode); } canvas.restore(); // put on a layer, to test stencil attachment props.mutateLayerProperties().setType(LayerType::RenderLayer); props.setAlpha(0.9f); }); canvas.drawRenderNode(card.get()); canvas.insertReorderBarrier(false); } void doFrame(int frameNr) override { int curFrame = frameNr % 150; Loading Loading
libs/hwui/BakedOpRenderer.cpp +47 −22 Original line number Diff line number Diff line Loading @@ -60,10 +60,18 @@ void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const } void BakedOpRenderer::endLayer() { mRenderTarget.offscreenBuffer->updateMeshFromRegion(); mRenderTarget.offscreenBuffer = nullptr; if (mRenderTarget.stencil) { // if stencil was used for clipping, detach it and return it to pool glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "glfbrb endlayer failed"); mCaches.renderBufferCache.put(mRenderTarget.stencil); mRenderTarget.stencil = nullptr; } mRenderTarget.lastStencilClip = nullptr; mRenderTarget.offscreenBuffer->updateMeshFromRegion(); mRenderTarget.offscreenBuffer = nullptr; // It's in drawLayerOp's hands now. // Detach the texture from the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "endLayer FAILED"); Loading @@ -75,7 +83,6 @@ void BakedOpRenderer::startFrame(uint32_t width, uint32_t height, const Rect& re LOG_ALWAYS_FATAL_IF(mRenderTarget.frameBufferId != 0, "primary framebufferId must be 0"); mRenderState.bindFramebuffer(0); setViewport(width, height); mCaches.clearGarbage(); if (!mOpaque) { clearColorBuffer(repaintRect); Loading Loading @@ -113,6 +120,7 @@ void BakedOpRenderer::endFrame(const Rect& repaintRect) { mRenderState.stencil().disable(); } mCaches.clearGarbage(); mCaches.pathCache.trim(); mCaches.tessellationCache.trim(); Loading Loading @@ -232,17 +240,25 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli mRenderState.scissor().setEnabled(clip != nullptr); if (clip) { mRenderState.scissor().set(mRenderTarget.viewportHeight, clip->rect); } if (CC_LIKELY(!Properties::debugOverdraw)) { // only modify stencil mode and content when it's not used for overdraw visualization if (CC_UNLIKELY(clip->mode != ClipMode::Rectangle)) { if (CC_UNLIKELY(clip && clip->mode != ClipMode::Rectangle)) { // NOTE: this pointer check is only safe for non-rect clips, // since rect clips may be created on the stack if (mRenderTarget.lastStencilClip != clip) { // Stencil needed, but current stencil isn't up to date mRenderTarget.lastStencilClip = clip; if (mRenderTarget.offscreenBuffer) { LOG_ALWAYS_FATAL("prepare layer stencil"); if (mRenderTarget.frameBufferId != 0 && !mRenderTarget.stencil) { OffscreenBuffer* layer = mRenderTarget.offscreenBuffer; mRenderTarget.stencil = mCaches.renderBufferCache.get( Stencil::getLayerStencilFormat(), layer->texture.width, layer->texture.height); // stencil is bound + allocated - associate it with current FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mRenderTarget.stencil->getName()); } if (clip->mode == ClipMode::RectangleList) { Loading @@ -250,12 +266,21 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli } else { setupStencilRegion(clip); } } else { // stencil is up to date - just need to ensure it's enabled (since an unclipped // or scissor-only clipped op may have been drawn, disabling the stencil) int incrementThreshold = 0; if (CC_LIKELY(clip->mode == ClipMode::RectangleList)) { auto&& rectList = reinterpret_cast<const ClipRectList*>(clip)->rectList; incrementThreshold = rectList.getTransformedRectanglesCount(); } mRenderState.stencil().enableTest(incrementThreshold); } } else { // either scissor or no clip, so disable stencil test mRenderState.stencil().disable(); } } } // dirty offscreenbuffer if (dirtyBounds && mRenderTarget.offscreenBuffer) { Loading
libs/hwui/BakedOpRenderer.h +13 −1 Original line number Diff line number Diff line Loading @@ -95,12 +95,24 @@ private: // render target state - setup by start/end layer/frame // only valid to use in between start/end pairs. struct { // If not drawing to a layer: fbo = 0, offscreenBuffer = null, // Otherwise these refer to currently painting layer's state GLuint frameBufferId = 0; OffscreenBuffer* offscreenBuffer = nullptr; // Used when drawing to a layer and using stencil clipping. otherwise null. RenderBuffer* stencil = nullptr; // value representing the ClipRectList* or ClipRegion* currently stored in // the stencil of the current render target const ClipBase* lastStencilClip = nullptr; // Size of renderable region in current render target - for layers, may not match actual // bounds of FBO texture. offscreenBuffer->texture has this information. uint32_t viewportWidth = 0; uint32_t viewportHeight = 0; Matrix4 orthoMatrix; const ClipBase* lastStencilClip = nullptr; } mRenderTarget; const LightInfo mLightInfo; Loading
libs/hwui/GlopBuilder.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -78,7 +78,7 @@ GlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementC mOutGlop->mesh.vertices = { vbo, VertexAttribFlags::TextureCoord, nullptr, nullptr, nullptr, nullptr, (const void*) kMeshTextureOffset, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = elementCount; return *this; Loading
libs/hwui/RecordedOp.h +2 −2 Original line number Diff line number Diff line Loading @@ -391,9 +391,9 @@ struct LayerOp : RecordedOp { LayerOp(BASE_PARAMS, OffscreenBuffer** layerHandle) : SUPER_PAINTLESS(LayerOp) , layerHandle(layerHandle) , alpha(paint->getAlpha() / 255.0f) , alpha(paint ? paint->getAlpha() / 255.0f : 1.0f) , mode(PaintUtils::getXfermodeDirect(paint)) , colorFilter(paint->getColorFilter()) , colorFilter(paint ? paint->getColorFilter() : nullptr) , destroy(true) {} LayerOp(RenderNode& node) Loading
libs/hwui/tests/common/scenes/ClippingAnimation.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -30,8 +30,6 @@ public: sp<RenderNode> card; void createContent(int width, int height, TestCanvas& canvas) override { canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode); canvas.insertReorderBarrier(true); card = TestUtils::createNode(0, 0, 200, 400, [](RenderProperties& props, TestCanvas& canvas) { canvas.save(SkCanvas::kMatrixClip_SaveFlag); Loading @@ -53,10 +51,12 @@ public: canvas.drawColor(Color::Red_500, SkXfermode::kSrcOver_Mode); } canvas.restore(); // put on a layer, to test stencil attachment props.mutateLayerProperties().setType(LayerType::RenderLayer); props.setAlpha(0.9f); }); canvas.drawRenderNode(card.get()); canvas.insertReorderBarrier(false); } void doFrame(int frameNr) override { int curFrame = frameNr % 150; Loading