Loading libs/hwui/LayerRenderer.cpp +0 −110 Original line number Diff line number Diff line Loading @@ -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 libs/hwui/LayerRenderer.h +0 −1 Original line number Diff line number Diff line Loading @@ -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); Loading libs/hwui/Readback.cpp +48 −39 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 Loading libs/hwui/Readback.h +12 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ namespace android { namespace uirenderer { class Layer; // Keep in sync with PixelCopy.java codes enum class CopyResult { Success = 0, Loading @@ -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 Loading libs/hwui/renderthread/CanvasContext.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -689,7 +690,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) { Loading Loading
libs/hwui/LayerRenderer.cpp +0 −110 Original line number Diff line number Diff line Loading @@ -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
libs/hwui/LayerRenderer.h +0 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
libs/hwui/Readback.cpp +48 −39 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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 Loading
libs/hwui/Readback.h +12 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ namespace android { namespace uirenderer { class Layer; // Keep in sync with PixelCopy.java codes enum class CopyResult { Success = 0, Loading @@ -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 Loading
libs/hwui/renderthread/CanvasContext.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -689,7 +690,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) { Loading