diff options
-rw-r--r-- | libs/hwui/GlopBuilder.cpp | 15 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.h | 4 | ||||
-rw-r--r-- | libs/hwui/Readback.cpp | 44 |
3 files changed, 54 insertions, 9 deletions
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 7d4f4100313f..fdbe76a5e459 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -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 //////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index 6e5797d1434b..b6c186d85e76 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -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); diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index d7df77c2f3ed..4a325897d4ec 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -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(); |