Unify readback Surface/TextureView copy mechanism
Removes last usage of old rendering pipeline.
Change-Id: Ia920dec9cd726ca221e11e888562c7df39a9761e
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 137316f..405165f 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -351,115 +351,5 @@
#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
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 38c3705..1fb6b14 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -61,7 +61,6 @@
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);
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 55f823d..60eadff 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -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 @@
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 @@
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 @@
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();
+ return copyTextureInto(caches, renderThread.renderState(), sourceTexture, texTransform, bitmap);
+}
- 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());
- }
-
- // 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
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index a112c42..bd73734 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -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 @@
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
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 0a48a0c..4a45071 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -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 @@
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) {