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

Commit 57624d1f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Support readback from hardware bitmaps"

parents 76feb115 59eecb52
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -34,8 +34,6 @@ namespace uirenderer {
CopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect,
        SkBitmap* bitmap) {
    ATRACE_CALL();
    mRenderThread.eglManager().initialize();

    // Setup the source
    sp<GraphicBuffer> sourceBuffer;
    sp<Fence> sourceFence;
@@ -61,13 +59,19 @@ CopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect
        return CopyResult::Timeout;
    }

    return copyGraphicBufferInto(sourceBuffer.get(), texTransform, srcRect, bitmap);
}

CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
        Matrix4& texTransform, const Rect& srcRect, SkBitmap* bitmap) {
    mRenderThread.eglManager().initialize();
    // TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via
    // GL_OES_EGL_image, which doesn't work since we need samplerExternalOES
    // to be able to properly sample from the buffer.

    // Create the EGLImage object that maps the GraphicBuffer
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    EGLClientBuffer clientBuffer = (EGLClientBuffer) sourceBuffer->getNativeBuffer();
    EGLClientBuffer clientBuffer = (EGLClientBuffer) graphicBuffer->getNativeBuffer();
    EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };

    EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT,
@@ -78,8 +82,8 @@ CopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect
        return CopyResult::UnknownError;
    }

    CopyResult copyResult = copyImageInto(sourceImage, texTransform, sourceBuffer->getWidth(),
            sourceBuffer->getHeight(), srcRect, bitmap);
    CopyResult copyResult = copyImageInto(sourceImage, texTransform, graphicBuffer->getWidth(),
            graphicBuffer->getHeight(), srcRect, bitmap);

    // All we're flushing & finishing is the deletion of the texture since
    // copyImageInto already did a major flush & finish as an implicit
@@ -89,6 +93,14 @@ CopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect
    return copyResult;
}

CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) {
    Rect srcRect;
    Matrix4 transform;
    transform.loadScale(1, -1, 1);
    transform.translate(0, -1);
    return copyGraphicBufferInto(graphicBuffer, transform, srcRect, bitmap);
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

+5 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@ class OpenGLReadback : public Readback {
public:
    virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
            SkBitmap* bitmap) override;
    virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
            SkBitmap* bitmap) override;

protected:
    explicit OpenGLReadback(renderthread::RenderThread& thread) : Readback(thread) {}
@@ -35,6 +37,9 @@ protected:

    virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
            int imgWidth, int imgHeight, const Rect& srcRect, SkBitmap* bitmap) = 0;
private:
    CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer, Matrix4& texTransform,
            const Rect& srcRect, SkBitmap* bitmap);
};

class OpenGLReadbackImpl : public OpenGLReadback {
+2 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <gui/Surface.h>

namespace android {
class GraphicBuffer;
namespace uirenderer {

// Keep in sync with PixelCopy.java codes
@@ -42,6 +43,7 @@ public:
     */
    virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
            SkBitmap* bitmap) = 0;
    virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) = 0;

protected:
    explicit Readback(renderthread::RenderThread& thread) : mRenderThread(thread) {}
+4 −3
Original line number Diff line number Diff line
@@ -459,14 +459,15 @@ void Bitmap::setAlphaType(SkAlphaType alphaType) {
}

void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
    outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
    if (isHardware()) {
        //TODO: use readback to get pixels
        LOG_ALWAYS_FATAL("Not implemented");
        ALOGW("Warning: attempt to read pixels from hardware bitmap, which is very slow operation");
        outBitmap->allocPixels(info());
        uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
        return;
    }
    outBitmap->setInfo(info(), rowBytes());
    outBitmap->setPixelRef(this);
    outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
}

void Bitmap::getSkBitmapForShaders(SkBitmap* outBitmap) {
+14 −0
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#include "utils/Macros.h"
#include "utils/TimeUtils.h"

#include <ui/GraphicBuffer.h>

namespace android {
namespace uirenderer {
namespace renderthread {
@@ -663,6 +665,18 @@ sk_sp<Bitmap> RenderProxy::allocateHardwareBitmap(SkBitmap& bitmap) {
    return hardwareBitmap;
}

CREATE_BRIDGE3(copyGraphicBufferInto, RenderThread* thread, GraphicBuffer* buffer, SkBitmap* bitmap) {
    return (void*) args->thread->readback().copyGraphicBufferInto(args->buffer, args->bitmap);
}

int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) {
    SETUP_TASK(copyGraphicBufferInto);
    args->thread = &RenderThread::getInstance();
    args->bitmap = bitmap;
    args->buffer = buffer;
    return static_cast<int>(reinterpret_cast<intptr_t>(staticPostAndWait(task)));
}

void RenderProxy::post(RenderTask* task) {
    mRenderThread.queue(task);
}
Loading