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

Commit 9fded232 authored by Chris Craik's avatar Chris Craik
Browse files

Recycle OffscreenBuffers

Change-Id: Ia2e219026f211a5308ecf8209c5f986bb888aadd
parent 8b8be50c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ hwui_src_files := \
    font/Font.cpp \
    renderstate/Blend.cpp \
    renderstate/MeshState.cpp \
    renderstate/OffscreenBufferPool.cpp \
    renderstate/PixelBufferState.cpp \
    renderstate/RenderState.cpp \
    renderstate/Scissor.cpp \
@@ -216,6 +217,7 @@ LOCAL_SRC_FILES += \
    unit_tests/LayerUpdateQueueTests.cpp \
    unit_tests/LinearAllocatorTests.cpp \
    unit_tests/PathParserTests.cpp \
    unit_tests/OffscreenBufferPoolTests.cpp \
    unit_tests/StringUtilsTests.cpp

ifeq (true, $(HWUI_NEW_OPS))
+6 −82
Original line number Diff line number Diff line
@@ -19,98 +19,22 @@
#include "Caches.h"
#include "Glop.h"
#include "GlopBuilder.h"
#include "VertexBuffer.h"
#include "renderstate/OffscreenBufferPool.h"
#include "renderstate/RenderState.h"
#include "utils/FatVector.h"
#include "utils/GLUtils.h"
#include "VertexBuffer.h"

namespace android {
namespace uirenderer {

////////////////////////////////////////////////////////////////////////////////
// OffscreenBuffer
////////////////////////////////////////////////////////////////////////////////

OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches,
        uint32_t textureWidth, uint32_t textureHeight,
        uint32_t viewportWidth, uint32_t viewportHeight)
        : renderState(renderState)
        , viewportWidth(viewportWidth)
        , viewportHeight(viewportHeight)
        , texture(caches) {
    texture.width = textureWidth;
    texture.height = textureHeight;

    caches.textureState().activateTexture(0);
    glGenTextures(1, &texture.id);
    caches.textureState().bindTexture(GL_TEXTURE_2D, texture.id);

    texture.setWrap(GL_CLAMP_TO_EDGE, false, false, GL_TEXTURE_2D);
    // not setting filter on texture, since it's set when rendering, based on transform

    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0,
            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 rendering 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(RenderState& renderState,
        uint32_t width, uint32_t height) {
    // TODO: get from cache!
    return new OffscreenBuffer(renderState, Caches::getInstance(), width, height, width, height);
}

void BakedOpRenderer::destroyOffscreenBuffer(OffscreenBuffer* offscreenBuffer) {
    // TODO: return texture/offscreenbuffer to cache!
    delete offscreenBuffer;
}

OffscreenBuffer* BakedOpRenderer::startTemporaryLayer(uint32_t width, uint32_t height) {
    OffscreenBuffer* buffer = createOffscreenBuffer(mRenderState, width, height);
    LOG_ALWAYS_FATAL_IF(mRenderTarget.offscreenBuffer, "already has layer...");

    OffscreenBuffer* buffer = mRenderState.layerPool().get(mRenderState, width, height);
    startRepaintLayer(buffer);
    return buffer;
}
@@ -357,7 +281,7 @@ void BakedOpDispatcher::onLayerOp(BakedOpRenderer& renderer, const LayerOp& op,
    renderer.renderGlop(state, glop);

    if (op.destroy) {
        BakedOpRenderer::destroyOffscreenBuffer(buffer);
        renderer.renderState().layerPool().putOrDelete(buffer);
    }
}

+0 −31
Original line number Diff line number Diff line
@@ -28,33 +28,6 @@ struct Glop;
class Layer;
class RenderState;

/**
 * Lightweight alternative to Layer. Owns the persistent state of an offscreen render target, and
 * encompasses enough information to draw it back on screen (minus paint properties, which are held
 * by LayerOp).
 */
class OffscreenBuffer {
public:
    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;

    // 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;
};

/**
 * Main rendering manager for a collection of work - one frame + any contained FBOs.
 *
@@ -72,10 +45,6 @@ public:
            , mOpaque(opaque) {
    }

    static OffscreenBuffer* createOffscreenBuffer(RenderState& renderState,
            uint32_t width, uint32_t height);
    static void destroyOffscreenBuffer(OffscreenBuffer*);

    RenderState& renderState() { return mRenderState; }
    Caches& caches() { return mCaches; }

+9 −8
Original line number Diff line number Diff line
@@ -17,6 +17,14 @@
#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H

#include "Canvas.h"
#include "CanvasState.h"
#include "DisplayList.h"
#include "RenderNode.h"
#include "ResourceCache.h"
#include "SkiaCanvasProxy.h"
#include "utils/Macros.h"

#include <SkDrawFilter.h>
#include <SkMatrix.h>
#include <SkPaint.h>
@@ -25,13 +33,6 @@
#include <SkTLazy.h>
#include <cutils/compiler.h>

#include "Canvas.h"
#include "CanvasState.h"
#include "DisplayList.h"
#include "SkiaCanvasProxy.h"
#include "RenderNode.h"
#include "ResourceCache.h"

namespace android {
namespace uirenderer {

@@ -66,7 +67,7 @@ public:
    virtual ~DisplayListCanvas();

    void reset(int width, int height);
    __attribute__((warn_unused_result)) DisplayList* finishRecording();
    WARN_UNUSED_RESULT DisplayList* finishRecording();

// ----------------------------------------------------------------------------
// HWUI Canvas state operations
+8 −13
Original line number Diff line number Diff line
@@ -14,14 +14,15 @@
 * limitations under the License.
 */

#include <GLES2/gl2.h>

#include <utils/Log.h>
#include "LayerCache.h"

#include "Caches.h"
#include "LayerCache.h"
#include "Properties.h"

#include <utils/Log.h>

#include <GLES2/gl2.h>

namespace android {
namespace uirenderer {

@@ -29,15 +30,9 @@ namespace uirenderer {
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////

LayerCache::LayerCache(): mSize(0), mMaxSize(MB(DEFAULT_LAYER_CACHE_SIZE)) {
    char property[PROPERTY_VALUE_MAX];
    if (property_get(PROPERTY_LAYER_CACHE_SIZE, property, nullptr) > 0) {
        INIT_LOGD("  Setting layer cache size to %sMB", property);
        setMaxSize(MB(atof(property)));
    } else {
        INIT_LOGD("  Using default layer cache size of %.2fMB", DEFAULT_LAYER_CACHE_SIZE);
    }
}
LayerCache::LayerCache()
        : mSize(0)
        , mMaxSize(Properties::layerPoolSize) {}

LayerCache::~LayerCache() {
    clear();
Loading