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

Commit d928ad61 authored by John Reck's avatar John Reck Committed by android-build-merger
Browse files

Merge "PixelCopy fixes" into nyc-dev

am: a5bbbe55

* commit 'a5bbbe55':
  PixelCopy fixes

Change-Id: I0da1b908278f385010662678be6eea6de6910d03
parents eeec5889 a5bbbe55
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -471,6 +471,21 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
    return *this;
}

GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture) {
    TRIGGER_STAGE(kFillStage);
    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);

    mOutGlop->fill.texture = { &texture,
            GL_TEXTURE_EXTERNAL_OES, GL_LINEAR, GL_CLAMP_TO_EDGE,
            nullptr };

    setFill(SK_ColorWHITE, 1.0f, SkXfermode::kSrc_Mode, Blend::ModeOrderSwap::NoSwap,
            nullptr, nullptr);

    mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
    return *this;
}

////////////////////////////////////////////////////////////////////////////////
// Transform
////////////////////////////////////////////////////////////////////////////////
+4 −0
Original line number Diff line number Diff line
@@ -70,6 +70,10 @@ public:
    GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
            float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage);
    GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
    // TODO: Texture should probably know and own its target.
    // setFillLayer() forces it to GL_TEXTURE which isn't always correct.
    // Similarly setFillLayer normally forces its own wrap & filter mode
    GlopBuilder& setFillExternalTexture(Texture& texture);

    GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) {
        return setTransform(*snapshot.transform, transformFlags);
+35 −9
Original line number Diff line number Diff line
@@ -101,24 +101,51 @@ bool Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
    // Setup the source
    sp<GraphicBuffer> sourceBuffer;
    sp<Fence> sourceFence;
    // FIXME: Waiting on an API from libgui for this
    // surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence);
    status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence);
    if (err != NO_ERROR) {
        ALOGW("Failed to get last queued buffer, error = %d", err);
        return false;
    }
    if (!sourceBuffer.get()) {
        ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
        return false;
    }
    int err = sourceFence->wait(500 /* ms */);
    err = sourceFence->wait(500 /* ms */);
    if (err != NO_ERROR) {
        ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
        return false;
    }
    Image sourceImage(sourceBuffer);
    if (!sourceImage.getTexture()) {
        ALOGW("Failed to make an EGLImage from the GraphicBuffer");

    // 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();
    EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };

    EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT,
            EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);

    if (sourceImage == EGL_NO_IMAGE_KHR) {
        ALOGW("Error creating image (%#x)", eglGetError());
        return false;
    }
    GLuint sourceTexId;
    // Create a 2D texture to sample from the EGLImage
    glGenTextures(1, &sourceTexId);
    Caches::getInstance().textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, sourceImage);

    GLenum status = GL_NO_ERROR;
    while ((status = glGetError()) != GL_NO_ERROR) {
        ALOGW("Error creating image (%#x)", status);
        return false;
    }

    Texture sourceTexture(caches);
    sourceTexture.wrap(sourceImage.getTexture(),
    sourceTexture.wrap(sourceTexId,
            sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0 /* total lie */);

    {
@@ -133,8 +160,7 @@ bool Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
        GlopBuilder(renderState, caches, &glop)
                .setRoundRectClipState(nullptr)
                .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
                .setFillLayer(sourceTexture, nullptr, 1.0f, SkXfermode::kSrc_Mode,
                        Blend::ModeOrderSwap::NoSwap)
                .setFillExternalTexture(sourceTexture)
                .setTransform(Matrix4::identity(), TransformFlags::None)
                .setModelViewMapUnitToRect(destRect)
                .build();