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

Commit 764045da authored by Chris Craik's avatar Chris Craik
Browse files

Unify readback Surface/TextureView copy mechanism

Removes last usage of old rendering pipeline.

Change-Id: Ia920dec9cd726ca221e11e888562c7df39a9761e
parent eecaafb9
Loading
Loading
Loading
Loading
+0 −110
Original line number Diff line number Diff line
@@ -351,115 +351,5 @@ void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
#endif
}

bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) {
    Caches& caches = Caches::getInstance();
    if (layer && layer->isRenderable()
            && bitmap->width() <= caches.maxTextureSize
            && bitmap->height() <= caches.maxTextureSize) {

        GLuint fbo = renderState.createFramebuffer();
        if (!fbo) {
            ALOGW("Could not obtain an FBO");
            return false;
        }

        SkAutoLockPixels alp(*bitmap);

        GLuint texture;
        GLuint previousFbo;
        GLsizei previousViewportWidth;
        GLsizei previousViewportHeight;

        GLenum format;
        GLenum type;

        bool status = false;

        switch (bitmap->colorType()) {
            case kAlpha_8_SkColorType:
                format = GL_ALPHA;
                type = GL_UNSIGNED_BYTE;
                break;
            case kRGB_565_SkColorType:
                format = GL_RGB;
                type = GL_UNSIGNED_SHORT_5_6_5;
                break;
            case kARGB_4444_SkColorType:
                format = GL_RGBA;
                type = GL_UNSIGNED_SHORT_4_4_4_4;
                break;
            case kN32_SkColorType:
            default:
                format = GL_RGBA;
                type = GL_UNSIGNED_BYTE;
                break;
        }

        float alpha = layer->getAlpha();
        SkXfermode::Mode mode = layer->getMode();
        GLuint previousLayerFbo = layer->getFbo();

        layer->setAlpha(255, SkXfermode::kSrc_Mode);
        layer->setFbo(fbo);

        previousFbo = renderState.getFramebuffer();
        renderState.getViewport(&previousViewportWidth, &previousViewportHeight);
        renderState.bindFramebuffer(fbo);

        glGenTextures(1, &texture);

        caches.textureState().activateTexture(0);
        caches.textureState().bindTexture(texture);

        glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glTexImage2D(GL_TEXTURE_2D, 0, format, bitmap->width(), bitmap->height(),
                0, format, type, nullptr);

        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                GL_TEXTURE_2D, texture, 0);

        {
            LayerRenderer renderer(renderState, layer);
            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());
            renderer.scale(1.0f, -1.0f);

            {
                Rect bounds;
                bounds.set(0.0f, 0.0f, bitmap->width(), bitmap->height());
                renderer.drawTextureLayer(layer, bounds);

                glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
                        type, bitmap->getPixels());

            }

            status = true;
        }

        renderState.bindFramebuffer(previousFbo);
        layer->setAlpha(alpha, mode);
        layer->setFbo(previousLayerFbo);
        caches.textureState().deleteTexture(texture);
        renderState.deleteFramebuffer(fbo);
        renderState.setViewport(previousViewportWidth, previousViewportHeight);

        GL_CHECKPOINT(MODERATE);

        return status;
    }
    return false;
}

}; // namespace uirenderer
}; // namespace android
+0 −1
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ public:
    static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
            bool isOpaque, bool forceFilter, GLenum renderTarget, const float* textureTransform);
    static void destroyLayer(Layer* layer);
    static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);

    static void flushLayer(RenderState& renderState, Layer* layer);

+48 −39
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "Caches.h"
#include "Image.h"
#include "GlopBuilder.h"
#include "Layer.h"
#include "renderstate/RenderState.h"
#include "renderthread/EglManager.h"
#include "utils/GLUtils.h"
@@ -30,14 +31,8 @@
namespace android {
namespace uirenderer {

CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
        Surface& surface, SkBitmap* bitmap) {
    // TODO: Clean this up and unify it with LayerRenderer::copyLayer,
    // of which most of this is copied from.
    renderThread.eglManager().initialize();

    Caches& caches = Caches::getInstance();
    RenderState& renderState = renderThread.renderState();
static CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
        Texture& sourceTexture, Matrix4& texTransform, SkBitmap* bitmap) {
    int destWidth = bitmap->width();
    int destHeight = bitmap->height();
    if (destWidth > caches.maxTextureSize
@@ -98,6 +93,44 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
            GL_TEXTURE_2D, texture, 0);

    {
        // Draw & readback
        renderState.setViewport(destWidth, destHeight);
        renderState.scissor().setEnabled(false);
        renderState.blend().syncEnabled();
        renderState.stencil().disable();

        Glop glop;
        GlopBuilder(renderState, caches, &glop)
                .setRoundRectClipState(nullptr)
                .setMeshTexturedUnitQuad(nullptr)
                .setFillExternalTexture(sourceTexture, texTransform)
                .setTransform(Matrix4::identity(), TransformFlags::None)
                .setModelViewMapUnitToRect(Rect(destWidth, destHeight))
                .build();
        Matrix4 ortho;
        ortho.loadOrtho(destWidth, destHeight);
        renderState.render(glop, ortho);

        glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
                type, bitmap->getPixels());
    }

    // Cleanup
    caches.textureState().deleteTexture(texture);
    renderState.deleteFramebuffer(fbo);

    GL_CHECKPOINT(MODERATE);

    return CopyResult::Success;
}

CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
        Surface& surface, SkBitmap* bitmap) {
    renderThread.eglManager().initialize();

    Caches& caches = Caches::getInstance();

    // Setup the source
    sp<GraphicBuffer> sourceBuffer;
    sp<Fence> sourceFence;
@@ -142,7 +175,7 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
    GLuint sourceTexId;
    // Create a 2D texture to sample from the EGLImage
    glGenTextures(1, &sourceTexId);
    Caches::getInstance().textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
    caches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, sourceImage);

    GLenum status = GL_NO_ERROR;
@@ -155,37 +188,13 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
    sourceTexture.wrap(sourceTexId,
            sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0 /* total lie */);

    {
        // Draw & readback
        renderState.setViewport(destWidth, destHeight);
        renderState.scissor().setEnabled(false);
        renderState.blend().syncEnabled();
        renderState.stencil().disable();

        Rect destRect(destWidth, destHeight);
        Glop glop;
        GlopBuilder(renderState, caches, &glop)
                .setRoundRectClipState(nullptr)
                .setMeshTexturedUnitQuad(nullptr)
                .setFillExternalTexture(sourceTexture, texTransform)
                .setTransform(Matrix4::identity(), TransformFlags::None)
                .setModelViewMapUnitToRect(destRect)
                .build();
        Matrix4 ortho;
        ortho.loadOrtho(destWidth, destHeight);
        renderState.render(glop, ortho);

        glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
                type, bitmap->getPixels());
    return copyTextureInto(caches, renderThread.renderState(), sourceTexture, texTransform, bitmap);
}

    // Cleanup
    caches.textureState().deleteTexture(texture);
    renderState.deleteFramebuffer(fbo);

    GL_CHECKPOINT(MODERATE);

    return CopyResult::Success;
CopyResult Readback::copyTextureLayerInto(renderthread::RenderThread& renderThread,
        Layer& layer, SkBitmap* bitmap) {
    return copyTextureInto(Caches::getInstance(), renderThread.renderState(),
            layer.getTexture(), layer.getTexTransform(), bitmap);
}

} // namespace uirenderer
+12 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
namespace android {
namespace uirenderer {

class Layer;

// Keep in sync with PixelCopy.java codes
enum class CopyResult {
    Success = 0,
@@ -36,8 +38,18 @@ enum class CopyResult {

class Readback {
public:
    /**
     * Copies the surface's most recently queued buffer into the provided bitmap.
     */
    static CopyResult copySurfaceInto(renderthread::RenderThread& renderThread,
            Surface& surface, SkBitmap* bitmap);

    /**
     * Copies the TextureLayer's texture content (thus, the currently rendering buffer) into the
     * provided bitmap.
     */
    static CopyResult copyTextureLayerInto(renderthread::RenderThread& renderThread,
            Layer& layer, SkBitmap* bitmap);
};

} // namespace uirenderer
+3 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include "LayerRenderer.h"
#include "OpenGLRenderer.h"
#include "Properties.h"
#include "Readback.h"
#include "RenderThread.h"
#include "hwui/Canvas.h"
#include "renderstate/RenderState.h"
@@ -648,7 +649,8 @@ void CanvasContext::buildLayer(RenderNode* node, TreeObserver* observer) {

bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
    layer->apply();
    return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
    return Readback::copyTextureLayerInto(mRenderThread, *(layer->backingLayer()), bitmap)
            == CopyResult::Success;
}

void CanvasContext::destroyHardwareResources(TreeObserver* observer) {