Loading libs/hwui/BakedOpRenderer.cpp +69 −21 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "Glop.h" #include "GlopBuilder.h" #include "renderstate/RenderState.h" #include "utils/FatVector.h" #include "utils/GLUtils.h" namespace android { Loading @@ -29,12 +30,13 @@ namespace uirenderer { // OffscreenBuffer //////////////////////////////////////////////////////////////////////////////// OffscreenBuffer::OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t textureHeight, OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t textureWidth, uint32_t textureHeight, uint32_t viewportWidth, uint32_t viewportHeight) : viewportWidth(viewportWidth) : renderState(renderState) , viewportWidth(viewportWidth) , viewportHeight(viewportHeight) , texture(caches) , texCoords(0, viewportHeight / float(textureHeight), viewportWidth / float(textureWidth), 0) { , texture(caches) { texture.width = textureWidth; texture.height = textureHeight; Loading @@ -50,19 +52,58 @@ OffscreenBuffer::OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } void OffscreenBuffer::updateMeshFromRegion() { // avoid T-junctions as they cause artifacts in between the resultant // geometry when complex transforms occur. // TODO: generate the safeRegion only if necessary based on drawing transform Region safeRegion = Region::createTJunctionFreeRegion(region); size_t count; const android::Rect* rects = safeRegion.getArray(&count); const float texX = 1.0f / float(viewportWidth); const float texY = 1.0f / float(viewportHeight); FatVector<TextureVertex, 64> meshVector(count * 4); // uses heap if more than 64 vertices needed TextureVertex* mesh = &meshVector[0]; for (size_t i = 0; i < count; i++) { const android::Rect* r = &rects[i]; const float u1 = r->left * texX; const float v1 = (viewportHeight - r->top) * texY; const float u2 = r->right * texX; const float v2 = (viewportHeight - r->bottom) * texY; TextureVertex::set(mesh++, r->left, r->top, u1, v1); TextureVertex::set(mesh++, r->right, r->top, u2, v1); TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); } elementCount = count * 6; renderState.meshState().genOrUpdateMeshBuffer(&vbo, sizeof(TextureVertex) * count * 4, &meshVector[0], GL_DYNAMIC_DRAW); // TODO: GL_STATIC_DRAW if savelayer } OffscreenBuffer::~OffscreenBuffer() { texture.deleteTexture(); renderState.meshState().deleteMeshBuffer(vbo); elementCount = 0; vbo = 0; } //////////////////////////////////////////////////////////////////////////////// // BakedOpRenderer //////////////////////////////////////////////////////////////////////////////// OffscreenBuffer* BakedOpRenderer::createOffscreenBuffer(uint32_t width, uint32_t height) { OffscreenBuffer* BakedOpRenderer::createOffscreenBuffer(RenderState& renderState, uint32_t width, uint32_t height) { // TODO: get from cache! return new OffscreenBuffer(Caches::getInstance(), width, height, width, height); return new OffscreenBuffer(renderState, Caches::getInstance(), width, height, width, height); } void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) { // destroy and delete, since each clipped saveLayer is only drawn once. offscreenBuffer->texture.deleteTexture(); // TODO: return texture/offscreenbuffer to cache! delete offscreenBuffer; } Loading @@ -70,7 +111,7 @@ void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) { OffscreenBuffer* BakedOpRenderer::createLayer(uint32_t width, uint32_t height) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); OffscreenBuffer* buffer = createOffscreenBuffer(width, height); OffscreenBuffer* buffer = createOffscreenBuffer(mRenderState, width, height); startLayer(buffer); return buffer; } Loading Loading @@ -98,6 +139,7 @@ void BakedOpRenderer::startLayer(OffscreenBuffer* offscreenBuffer) { } void BakedOpRenderer::endLayer() { mRenderTarget.offscreenBuffer->updateMeshFromRegion(); mRenderTarget.offscreenBuffer = nullptr; // Detach the texture from the FBO Loading Loading @@ -162,6 +204,12 @@ void BakedOpRenderer::renderGlop(const BakedOpState& state, const Glop& glop) { mRenderState.scissor().set(clip.left, mRenderTarget.viewportHeight - clip.bottom, clip.getWidth(), clip.getHeight()); } if (mRenderTarget.offscreenBuffer) { // TODO: not with multi-draw // register layer damage to draw-back region const Rect& uiDirty = state.computedState.clippedBounds; android::Rect dirty(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom); mRenderTarget.offscreenBuffer->region.orSelf(dirty); } mRenderState.render(glop, mRenderTarget.orthoMatrix); mHasDrawn = true; } Loading @@ -174,6 +222,14 @@ void BakedOpDispatcher::onRenderNodeOp(BakedOpRenderer&, const RenderNodeOp&, co LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer& renderer, const BeginLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onEndLayerOp(BakedOpRenderer& renderer, const EndLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, const BakedOpState& state) { renderer.caches().textureState().activateTexture(0); // TODO: should this be automatic, and/or elsewhere? Texture* texture = renderer.getTexture(op.bitmap); Loading Loading @@ -217,28 +273,20 @@ void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleR renderer.renderGlop(state, glop); } void BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer& renderer, const BeginLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onEndLayerOp(BakedOpRenderer& renderer, const EndLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) { OffscreenBuffer* buffer = *op.layerHandle; // TODO: extend this to handle HW layers & paint properties which // reside in node.properties().layerProperties() float layerAlpha = op.alpha * state.alpha; const bool tryToSnap = state.computedState.transform.isPureTranslate(); Glop glop; GlopBuilder(renderer.renderState(), renderer.caches(), &glop) .setRoundRectClipState(state.roundRectClipState) .setMeshTexturedUvQuad(nullptr, buffer->texCoords) .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount) .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap) .setTransform(state.computedState.transform, TransformFlags::None) .setModelViewMapUnitToRectOptionalSnap(tryToSnap, op.unmappedBounds) .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top, Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight())) .build(); renderer.renderGlop(state, glop); Loading libs/hwui/BakedOpRenderer.h +15 −3 Original line number Diff line number Diff line Loading @@ -35,13 +35,24 @@ class RenderState; */ class OffscreenBuffer { public: OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t textureHeight, OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t textureWidth, uint32_t textureHeight, uint32_t viewportWidth, uint32_t viewportHeight); ~OffscreenBuffer(); // must be called prior to rendering, to construct/update vertex buffer void updateMeshFromRegion(); RenderState& renderState; uint32_t viewportWidth; uint32_t viewportHeight; Texture texture; Rect texCoords; // Portion of offscreen buffer that has been drawn to. Used to minimize drawing area when // drawing back to screen / parent FBO. Region region; GLsizei elementCount = 0; GLuint vbo = 0; }; /** Loading @@ -61,7 +72,8 @@ public: , mOpaque(opaque) { } static OffscreenBuffer* createOffscreenBuffer(uint32_t width, uint32_t height); static OffscreenBuffer* createOffscreenBuffer(RenderState& renderState, uint32_t width, uint32_t height); static void destroyOffscreenBuffer(OffscreenBuffer*); RenderState& renderState() { return mRenderState; } Loading libs/hwui/GlopBuilder.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,20 @@ GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop // Mesh //////////////////////////////////////////////////////////////////////////////// GlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount) { TRIGGER_STAGE(kMeshStage); mOutGlop->mesh.primitiveMode = GL_TRIANGLES; mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr }; mOutGlop->mesh.vertices = { vbo, VertexAttribFlags::TextureCoord, nullptr, nullptr, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = elementCount; return *this; } GlopBuilder& GlopBuilder::setMeshUnitQuad() { TRIGGER_STAGE(kMeshStage); Loading libs/hwui/GlopBuilder.h +1 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ class GlopBuilder { public: GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop); GlopBuilder& setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount); GlopBuilder& setMeshUnitQuad(); GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper); GlopBuilder& setMeshTexturedUvQuad(const UvMapper* uvMapper, const Rect uvs); Loading libs/hwui/RenderNode.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -250,7 +250,7 @@ void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) { layer_t* createLayer(RenderState& renderState, uint32_t width, uint32_t height) { #if HWUI_NEW_OPS return BakedOpRenderer::createOffscreenBuffer(width, height); return BakedOpRenderer::createOffscreenBuffer(renderState, width, height); #else return LayerRenderer::createRenderLayer(renderState, width, height); #endif Loading Loading
libs/hwui/BakedOpRenderer.cpp +69 −21 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include "Glop.h" #include "GlopBuilder.h" #include "renderstate/RenderState.h" #include "utils/FatVector.h" #include "utils/GLUtils.h" namespace android { Loading @@ -29,12 +30,13 @@ namespace uirenderer { // OffscreenBuffer //////////////////////////////////////////////////////////////////////////////// OffscreenBuffer::OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t textureHeight, OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t textureWidth, uint32_t textureHeight, uint32_t viewportWidth, uint32_t viewportHeight) : viewportWidth(viewportWidth) : renderState(renderState) , viewportWidth(viewportWidth) , viewportHeight(viewportHeight) , texture(caches) , texCoords(0, viewportHeight / float(textureHeight), viewportWidth / float(textureWidth), 0) { , texture(caches) { texture.width = textureWidth; texture.height = textureHeight; Loading @@ -50,19 +52,58 @@ OffscreenBuffer::OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } void OffscreenBuffer::updateMeshFromRegion() { // avoid T-junctions as they cause artifacts in between the resultant // geometry when complex transforms occur. // TODO: generate the safeRegion only if necessary based on drawing transform Region safeRegion = Region::createTJunctionFreeRegion(region); size_t count; const android::Rect* rects = safeRegion.getArray(&count); const float texX = 1.0f / float(viewportWidth); const float texY = 1.0f / float(viewportHeight); FatVector<TextureVertex, 64> meshVector(count * 4); // uses heap if more than 64 vertices needed TextureVertex* mesh = &meshVector[0]; for (size_t i = 0; i < count; i++) { const android::Rect* r = &rects[i]; const float u1 = r->left * texX; const float v1 = (viewportHeight - r->top) * texY; const float u2 = r->right * texX; const float v2 = (viewportHeight - r->bottom) * texY; TextureVertex::set(mesh++, r->left, r->top, u1, v1); TextureVertex::set(mesh++, r->right, r->top, u2, v1); TextureVertex::set(mesh++, r->left, r->bottom, u1, v2); TextureVertex::set(mesh++, r->right, r->bottom, u2, v2); } elementCount = count * 6; renderState.meshState().genOrUpdateMeshBuffer(&vbo, sizeof(TextureVertex) * count * 4, &meshVector[0], GL_DYNAMIC_DRAW); // TODO: GL_STATIC_DRAW if savelayer } OffscreenBuffer::~OffscreenBuffer() { texture.deleteTexture(); renderState.meshState().deleteMeshBuffer(vbo); elementCount = 0; vbo = 0; } //////////////////////////////////////////////////////////////////////////////// // BakedOpRenderer //////////////////////////////////////////////////////////////////////////////// OffscreenBuffer* BakedOpRenderer::createOffscreenBuffer(uint32_t width, uint32_t height) { OffscreenBuffer* BakedOpRenderer::createOffscreenBuffer(RenderState& renderState, uint32_t width, uint32_t height) { // TODO: get from cache! return new OffscreenBuffer(Caches::getInstance(), width, height, width, height); return new OffscreenBuffer(renderState, Caches::getInstance(), width, height, width, height); } void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) { // destroy and delete, since each clipped saveLayer is only drawn once. offscreenBuffer->texture.deleteTexture(); // TODO: return texture/offscreenbuffer to cache! delete offscreenBuffer; } Loading @@ -70,7 +111,7 @@ void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) { OffscreenBuffer* BakedOpRenderer::createLayer(uint32_t width, uint32_t height) { LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer..."); OffscreenBuffer* buffer = createOffscreenBuffer(width, height); OffscreenBuffer* buffer = createOffscreenBuffer(mRenderState, width, height); startLayer(buffer); return buffer; } Loading Loading @@ -98,6 +139,7 @@ void BakedOpRenderer::startLayer(OffscreenBuffer* offscreenBuffer) { } void BakedOpRenderer::endLayer() { mRenderTarget.offscreenBuffer->updateMeshFromRegion(); mRenderTarget.offscreenBuffer = nullptr; // Detach the texture from the FBO Loading Loading @@ -162,6 +204,12 @@ void BakedOpRenderer::renderGlop(const BakedOpState& state, const Glop& glop) { mRenderState.scissor().set(clip.left, mRenderTarget.viewportHeight - clip.bottom, clip.getWidth(), clip.getHeight()); } if (mRenderTarget.offscreenBuffer) { // TODO: not with multi-draw // register layer damage to draw-back region const Rect& uiDirty = state.computedState.clippedBounds; android::Rect dirty(uiDirty.left, uiDirty.top, uiDirty.right, uiDirty.bottom); mRenderTarget.offscreenBuffer->region.orSelf(dirty); } mRenderState.render(glop, mRenderTarget.orthoMatrix); mHasDrawn = true; } Loading @@ -174,6 +222,14 @@ void BakedOpDispatcher::onRenderNodeOp(BakedOpRenderer&, const RenderNodeOp&, co LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer& renderer, const BeginLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onEndLayerOp(BakedOpRenderer& renderer, const EndLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op, const BakedOpState& state) { renderer.caches().textureState().activateTexture(0); // TODO: should this be automatic, and/or elsewhere? Texture* texture = renderer.getTexture(op.bitmap); Loading Loading @@ -217,28 +273,20 @@ void BakedOpDispatcher::onSimpleRectsOp(BakedOpRenderer& renderer, const SimpleR renderer.renderGlop(state, glop); } void BakedOpDispatcher::onBeginLayerOp(BakedOpRenderer& renderer, const BeginLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onEndLayerOp(BakedOpRenderer& renderer, const EndLayerOp& op, const BakedOpState& state) { LOG_ALWAYS_FATAL("unsupported operation"); } void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op, const BakedOpState& state) { OffscreenBuffer* buffer = *op.layerHandle; // TODO: extend this to handle HW layers & paint properties which // reside in node.properties().layerProperties() float layerAlpha = op.alpha * state.alpha; const bool tryToSnap = state.computedState.transform.isPureTranslate(); Glop glop; GlopBuilder(renderer.renderState(), renderer.caches(), &glop) .setRoundRectClipState(state.roundRectClipState) .setMeshTexturedUvQuad(nullptr, buffer->texCoords) .setMeshTexturedIndexedVbo(buffer->vbo, buffer->elementCount) .setFillLayer(buffer->texture, op.colorFilter, layerAlpha, op.mode, Blend::ModeOrderSwap::NoSwap) .setTransform(state.computedState.transform, TransformFlags::None) .setModelViewMapUnitToRectOptionalSnap(tryToSnap, op.unmappedBounds) .setModelViewOffsetRectSnap(op.unmappedBounds.left, op.unmappedBounds.top, Rect(op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight())) .build(); renderer.renderGlop(state, glop); Loading
libs/hwui/BakedOpRenderer.h +15 −3 Original line number Diff line number Diff line Loading @@ -35,13 +35,24 @@ class RenderState; */ class OffscreenBuffer { public: OffscreenBuffer(Caches& caches, uint32_t textureWidth, uint32_t textureHeight, OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t textureWidth, uint32_t textureHeight, uint32_t viewportWidth, uint32_t viewportHeight); ~OffscreenBuffer(); // must be called prior to rendering, to construct/update vertex buffer void updateMeshFromRegion(); RenderState& renderState; uint32_t viewportWidth; uint32_t viewportHeight; Texture texture; Rect texCoords; // Portion of offscreen buffer that has been drawn to. Used to minimize drawing area when // drawing back to screen / parent FBO. Region region; GLsizei elementCount = 0; GLuint vbo = 0; }; /** Loading @@ -61,7 +72,8 @@ public: , mOpaque(opaque) { } static OffscreenBuffer* createOffscreenBuffer(uint32_t width, uint32_t height); static OffscreenBuffer* createOffscreenBuffer(RenderState& renderState, uint32_t width, uint32_t height); static void destroyOffscreenBuffer(OffscreenBuffer*); RenderState& renderState() { return mRenderState; } Loading
libs/hwui/GlopBuilder.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,20 @@ GlopBuilder::GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop // Mesh //////////////////////////////////////////////////////////////////////////////// GlopBuilder& GlopBuilder::setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount) { TRIGGER_STAGE(kMeshStage); mOutGlop->mesh.primitiveMode = GL_TRIANGLES; mOutGlop->mesh.indices = { mRenderState.meshState().getQuadListIBO(), nullptr }; mOutGlop->mesh.vertices = { vbo, VertexAttribFlags::TextureCoord, nullptr, nullptr, nullptr, kTextureVertexStride }; mOutGlop->mesh.elementCount = elementCount; return *this; } GlopBuilder& GlopBuilder::setMeshUnitQuad() { TRIGGER_STAGE(kMeshStage); Loading
libs/hwui/GlopBuilder.h +1 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ class GlopBuilder { public: GlopBuilder(RenderState& renderState, Caches& caches, Glop* outGlop); GlopBuilder& setMeshTexturedIndexedVbo(GLuint vbo, GLsizei elementCount); GlopBuilder& setMeshUnitQuad(); GlopBuilder& setMeshTexturedUnitQuad(const UvMapper* uvMapper); GlopBuilder& setMeshTexturedUvQuad(const UvMapper* uvMapper, const Rect uvs); Loading
libs/hwui/RenderNode.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -250,7 +250,7 @@ void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) { layer_t* createLayer(RenderState& renderState, uint32_t width, uint32_t height) { #if HWUI_NEW_OPS return BakedOpRenderer::createOffscreenBuffer(width, height); return BakedOpRenderer::createOffscreenBuffer(renderState, width, height); #else return LayerRenderer::createRenderLayer(renderState, width, height); #endif Loading