Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d70fc01e authored by Chris Craik's avatar Chris Craik Committed by Android (Google) Code Review
Browse files

Merge "Add region-tracking to OffscreenBuffers"

parents 2f40cdc5 8d2cf943
Loading
Loading
Loading
Loading
+69 −21
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include "Glop.h"
#include "GlopBuilder.h"
#include "renderstate/RenderState.h"
#include "utils/FatVector.h"
#include "utils/GLUtils.h"

namespace android {
@@ -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;

@@ -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;
}
@@ -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;
}
@@ -98,6 +139,7 @@ void BakedOpRenderer::startLayer(OffscreenBuffer* offscreenBuffer) {
}

void BakedOpRenderer::endLayer() {
    mRenderTarget.offscreenBuffer->updateMeshFromRegion();
    mRenderTarget.offscreenBuffer = nullptr;

    // Detach the texture from the FBO
@@ -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;
}
@@ -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);
@@ -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);

+15 −3
Original line number Diff line number Diff line
@@ -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;
};

/**
@@ -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; }
+14 −0
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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