summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp4
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp3
-rw-r--r--libs/hwui/Android.bp3
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp1
-rw-r--r--libs/hwui/EglReadback.cpp95
-rw-r--r--libs/hwui/EglReadback.h50
-rw-r--r--libs/hwui/Layer.cpp3
-rw-r--r--libs/hwui/Layer.h13
-rw-r--r--libs/hwui/Readback.cpp287
-rw-r--r--libs/hwui/Readback.h22
-rw-r--r--libs/hwui/hwui/Bitmap.cpp2
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.cpp33
-rw-r--r--libs/hwui/pipeline/skia/LayerDrawable.h2
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp59
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h1
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp147
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLReadback.h37
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp5
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.h1
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanReadback.h44
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp4
-rw-r--r--libs/hwui/renderthread/CanvasContext.h1
-rw-r--r--libs/hwui/renderthread/IRenderPipeline.h1
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp12
-rw-r--r--libs/hwui/renderthread/RenderProxy.h2
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp16
26 files changed, 353 insertions, 495 deletions
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 8083a6a27da7..0a252716b69e 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1198,6 +1198,10 @@ static jobject Bitmap_copyPreserveInternalConfig(JNIEnv* env, jobject, jlong bit
static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphicBuffer) {
sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
+ // Bitmap::createFrom currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888
+ // format and SRGB color space.
+ // To support any color space, we need to pass an additional ColorSpace argument to
+ // java Bitmap.createHardwareBitmap.
sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
if (!bitmap.get()) {
ALOGW("failed to create hardware bitmap from graphic buffer");
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 4a1774279d28..3c59bd1e3856 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -1024,6 +1024,9 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(
// Continue I guess?
}
sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer);
+ // Bitmap::createFrom currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888
+ // format and SRGB color space.
+ // To support any color space, we could extract it from BufferItem and pass it to Bitmap.
return bitmap::createBitmap(env, bitmap.release(),
android::bitmap::kBitmapCreateFlag_Premultiplied);
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 2baacbf541dc..e063e0bd9c3e 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -170,7 +170,6 @@ cc_defaults {
"pipeline/skia/SkiaDisplayList.cpp",
"pipeline/skia/SkiaMemoryTracer.cpp",
"pipeline/skia/SkiaOpenGLPipeline.cpp",
- "pipeline/skia/SkiaOpenGLReadback.cpp",
"pipeline/skia/SkiaPipeline.cpp",
"pipeline/skia/SkiaProfileRenderer.cpp",
"pipeline/skia/SkiaRecordingCanvas.cpp",
@@ -217,13 +216,13 @@ cc_defaults {
"Layer.cpp",
"LayerUpdateQueue.cpp",
"Matrix.cpp",
- "EglReadback.cpp",
"PathParser.cpp",
"ProfileData.cpp",
"ProfileDataContainer.cpp",
"Properties.cpp",
"PropertyValuesAnimatorSet.cpp",
"PropertyValuesHolder.cpp",
+ "Readback.cpp",
"RecordingCanvas.cpp",
"RenderNode.cpp",
"RenderProperties.cpp",
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 00916559a9c2..837d5461d2a8 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -49,6 +49,7 @@ void DeferredLayerUpdater::destroyLayer() {
}
mLayer->postDecStrong();
+
mLayer = nullptr;
}
diff --git a/libs/hwui/EglReadback.cpp b/libs/hwui/EglReadback.cpp
deleted file mode 100644
index 65becf88b930..000000000000
--- a/libs/hwui/EglReadback.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "EglReadback.h"
-
-#include "renderthread/EglManager.h"
-
-#include <gui/Surface.h>
-#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-
-namespace android {
-namespace uirenderer {
-
-CopyResult EglReadback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) {
- ATRACE_CALL();
- // Setup the source
- sp<GraphicBuffer> sourceBuffer;
- sp<Fence> sourceFence;
- Matrix4 texTransform;
- status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data);
- texTransform.invalidateType();
- if (err != NO_ERROR) {
- ALOGW("Failed to get last queued buffer, error = %d", err);
- return CopyResult::UnknownError;
- }
- if (!sourceBuffer.get()) {
- ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
- return CopyResult::SourceEmpty;
- }
- if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) {
- ALOGW("Surface is protected, unable to copy from it");
- return CopyResult::SourceInvalid;
- }
- err = sourceFence->wait(500 /* ms */);
- if (err != NO_ERROR) {
- ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
- return CopyResult::Timeout;
- }
-
- return copyGraphicBufferInto(sourceBuffer.get(), texTransform, srcRect, bitmap);
-}
-
-CopyResult EglReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, Matrix4& texTransform,
- const Rect& srcRect, SkBitmap* bitmap) {
- mRenderThread.requireGlContext();
- // 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)graphicBuffer->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("eglCreateImageKHR failed (%#x)", eglGetError());
- return CopyResult::UnknownError;
- }
-
- uint32_t width = graphicBuffer->getWidth();
- uint32_t height = graphicBuffer->getHeight();
- CopyResult copyResult =
- copyImageInto(sourceImage, texTransform, width, height, srcRect, bitmap);
-
- eglDestroyImageKHR(display, sourceImage);
- return copyResult;
-}
-
-CopyResult EglReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) {
- Rect srcRect;
- Matrix4 transform;
- transform.loadScale(1, -1, 1);
- transform.translate(0, -1);
- return copyGraphicBufferInto(graphicBuffer, transform, srcRect, bitmap);
-}
-
-} // namespace uirenderer
-} // namespace android
diff --git a/libs/hwui/EglReadback.h b/libs/hwui/EglReadback.h
deleted file mode 100644
index e723169ad795..000000000000
--- a/libs/hwui/EglReadback.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "Readback.h"
-
-#include "Matrix.h"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-namespace android {
-namespace uirenderer {
-
-class EglReadback : public Readback {
-public:
- virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
- SkBitmap* bitmap) override;
- virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
- SkBitmap* bitmap) override;
-
-protected:
- explicit EglReadback(renderthread::RenderThread& thread) : Readback(thread) {}
- virtual ~EglReadback() {}
-
- 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);
-};
-
-} // namespace uirenderer
-} // namespace android
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index f59a2e6ee5c1..cc95051fc952 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -26,8 +26,7 @@ namespace uirenderer {
Layer::Layer(RenderState& renderState, sk_sp<SkColorFilter> colorFilter, int alpha,
SkBlendMode mode)
- : GpuMemoryTracker(GpuObjectType::Layer)
- , mRenderState(renderState)
+ : mRenderState(renderState)
, mColorFilter(colorFilter)
, alpha(alpha)
, mode(mode) {
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index c4e4c1c96ba6..6f07a43ceb58 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -16,7 +16,6 @@
#pragma once
-#include <GpuMemoryTracker.h>
#include <utils/RefBase.h>
#include <SkBlendMode.h>
@@ -39,21 +38,21 @@ class RenderState;
/**
* A layer has dimensions and is backed by a backend specific texture or framebuffer.
*/
-class Layer : public VirtualLightRefBase, GpuMemoryTracker {
+class Layer : public VirtualLightRefBase {
public:
Layer(RenderState& renderState, sk_sp<SkColorFilter>, int alpha, SkBlendMode mode);
~Layer();
- virtual uint32_t getWidth() const { return mWidth; }
+ uint32_t getWidth() const { return mWidth; }
- virtual uint32_t getHeight() const { return mHeight; }
+ uint32_t getHeight() const { return mHeight; }
- virtual void setSize(uint32_t width, uint32_t height) { mWidth = width; mHeight = height; }
+ void setSize(uint32_t width, uint32_t height) { mWidth = width; mHeight = height; }
- virtual void setBlend(bool blend) { mBlend = blend; }
+ void setBlend(bool blend) { mBlend = blend; }
- virtual bool isBlend() const { return mBlend; }
+ bool isBlend() const { return mBlend; }
inline void setForceFilter(bool forceFilter) { this->forceFilter = forceFilter; }
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
new file mode 100644
index 000000000000..80f2b5714659
--- /dev/null
+++ b/libs/hwui/Readback.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Readback.h"
+
+#include "pipeline/skia/LayerDrawable.h"
+#include "renderthread/EglManager.h"
+#include "renderthread/VulkanManager.h"
+
+#include <SkToSRGBColorFilter.h>
+#include <gui/Surface.h>
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
+#include "DeferredLayerUpdater.h"
+#include "Properties.h"
+#include "hwui/Bitmap.h"
+#include "utils/Color.h"
+#include "utils/MathUtils.h"
+
+using namespace android::uirenderer::renderthread;
+
+namespace android {
+namespace uirenderer {
+
+CopyResult Readback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) {
+ ATRACE_CALL();
+ // Setup the source
+ sp<GraphicBuffer> sourceBuffer;
+ sp<Fence> sourceFence;
+ Matrix4 texTransform;
+ status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data);
+ texTransform.invalidateType();
+ if (err != NO_ERROR) {
+ ALOGW("Failed to get last queued buffer, error = %d", err);
+ return CopyResult::UnknownError;
+ }
+ if (!sourceBuffer.get()) {
+ ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
+ return CopyResult::SourceEmpty;
+ }
+ if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) {
+ ALOGW("Surface is protected, unable to copy from it");
+ return CopyResult::SourceInvalid;
+ }
+ err = sourceFence->wait(500 /* ms */);
+ if (err != NO_ERROR) {
+ ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
+ return CopyResult::Timeout;
+ }
+ if (!sourceBuffer.get()) {
+ return CopyResult::UnknownError;
+ }
+
+ sk_sp<SkColorSpace> colorSpace =
+ DataSpaceToColorSpace(static_cast<android_dataspace>(surface.getBuffersDataSpace()));
+ sk_sp<SkColorFilter> colorSpaceFilter;
+ if (colorSpace && !colorSpace->isSRGB()) {
+ colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
+ }
+ sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
+ reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()), kPremul_SkAlphaType);
+ return copyImageInto(image, colorSpaceFilter, texTransform, srcRect, bitmap);
+}
+
+CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
+ LOG_ALWAYS_FATAL_IF(!hwBitmap->isHardware());
+
+ Rect srcRect;
+ Matrix4 transform;
+ transform.loadScale(1, -1, 1);
+ transform.translate(0, -1);
+
+ // TODO: Try to take and reuse the image inside HW bitmap with "hwBitmap->makeImage".
+ // TODO: When this was attempted, it resulted in instability.
+ sk_sp<SkColorFilter> colorSpaceFilter;
+ sk_sp<SkColorSpace> colorSpace = hwBitmap->info().refColorSpace();
+ if (colorSpace && !colorSpace->isSRGB()) {
+ colorSpaceFilter = SkToSRGBColorFilter::Make(colorSpace);
+ }
+ sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(
+ reinterpret_cast<AHardwareBuffer*>(hwBitmap->graphicBuffer()), kPremul_SkAlphaType);
+
+ // HW Bitmap currently can only attach to a GraphicBuffer with PIXEL_FORMAT_RGBA_8888 format
+ // and SRGB color space. ImageDecoder can create a new HW Bitmap with non-SRGB color space: for
+ // example see android.graphics.cts.BitmapColorSpaceTest#testEncodeP3hardware test.
+ return copyImageInto(image, colorSpaceFilter, transform, srcRect, bitmap);
+}
+
+CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
+ if (!mRenderThread.getGrContext()) {
+ return CopyResult::UnknownError;
+ }
+
+ // acquire most recent buffer for drawing
+ deferredLayer->updateTexImage();
+ deferredLayer->apply();
+ const SkRect dstRect = SkRect::MakeIWH(bitmap->width(), bitmap->height());
+ CopyResult copyResult = CopyResult::UnknownError;
+ Layer* layer = deferredLayer->backingLayer();
+ if (layer) {
+ if (copyLayerInto(layer, nullptr, &dstRect, bitmap)) {
+ copyResult = CopyResult::Success;
+ }
+ }
+ return copyResult;
+}
+
+CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image,
+ sk_sp<SkColorFilter>& colorSpaceFilter, Matrix4& texTransform,
+ const Rect& srcRect, SkBitmap* bitmap) {
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) {
+ mRenderThread.requireGlContext();
+ } else {
+ mRenderThread.vulkanManager().initialize();
+ }
+ if (!image.get()) {
+ return CopyResult::UnknownError;
+ }
+ int imgWidth = image->width();
+ int imgHeight = image->height();
+ sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext());
+
+ if (bitmap->colorType() == kRGBA_F16_SkColorType &&
+ !grContext->colorTypeSupportedAsSurface(bitmap->colorType())) {
+ ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
+ return CopyResult::DestinationInvalid;
+ }
+
+ CopyResult copyResult = CopyResult::UnknownError;
+
+ int displayedWidth = imgWidth, displayedHeight = imgHeight;
+ // If this is a 90 or 270 degree rotation we need to swap width/height to get the device
+ // size.
+ if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) {
+ std::swap(displayedWidth, displayedHeight);
+ }
+ SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
+ SkRect skiaSrcRect = srcRect.toSkRect();
+ if (skiaSrcRect.isEmpty()) {
+ skiaSrcRect = SkRect::MakeIWH(displayedWidth, displayedHeight);
+ }
+ bool srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(displayedWidth, displayedHeight));
+ if (!srcNotEmpty) {
+ return copyResult;
+ }
+
+ // See Readback::copyLayerInto for an overview of color space conversion.
+ // HW Bitmap are allowed to be in a non-SRGB color space (for example coming from ImageDecoder).
+ // For Surface and HW Bitmap readback flows we pass colorSpaceFilter, which does the conversion.
+ // TextureView readback is using Layer::setDataSpace, which creates a SkColorFilter internally.
+ Layer layer(mRenderThread.renderState(), colorSpaceFilter, 255, SkBlendMode::kSrc);
+ bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width()) &&
+ MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
+ layer.setForceFilter(!disableFilter);
+ layer.setSize(displayedWidth, displayedHeight);
+ texTransform.copyTo(layer.getTexTransform());
+ layer.setImage(image);
+ if (copyLayerInto(&layer, &skiaSrcRect, &skiaDestRect, bitmap)) {
+ copyResult = CopyResult::Success;
+ }
+
+ return copyResult;
+}
+
+bool Readback::copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
+ SkBitmap* bitmap) {
+ /*
+ * In the past only TextureView readback was setting the temporary surface color space to null.
+ * Now all 3 readback flows are drawing into a SkSurface with null color space.
+ * At readback there are 3 options to convert the source image color space to the destination
+ * color space requested in "bitmap->info().colorSpace()":
+ * 1. Set color space for temporary surface render target to null (disables color management),
+ * colorspace tag from source SkImage is ignored by Skia,
+ * convert SkImage to SRGB at draw time with SkColorFilter/SkToSRGBColorFilter,
+ * do a readback from temporary SkSurface to a temporary SRGB SkBitmap "bitmap2",
+ * read back from SRGB "bitmap2" into non-SRGB "bitmap" which will do a CPU color conversion.
+ *
+ * 2. Set color space for temporary surface render target to SRGB (not nullptr),
+ * colorspace tag on the source SkImage is used by Skia to enable conversion,
+ * convert SkImage to SRGB at draw time with drawImage (no filters),
+ * do a readback from temporary SkSurface, which will do a color conversion from SRGB to
+ * bitmap->info().colorSpace() on the CPU.
+ *
+ * 3. Set color space for temporary surface render target to bitmap->info().colorSpace(),
+ * colorspace tag on the source SkImage is used by Skia to enable conversion,
+ * convert SkImage to bitmap->info().colorSpace() at draw time with drawImage (no filters),
+ * do a readback from SkSurface, which will not do any color conversion, because
+ * surface was created with the same color space as the "bitmap".
+ *
+ * Option 1 is used for all readback flows.
+ * Options 2 and 3 are new, because skia added support for non-SRGB render targets without
+ * linear blending.
+ * TODO: evaluate if options 2 or 3 for color space conversion are better.
+ */
+
+ // drop the colorSpace from the temporary surface.
+ SkImageInfo surfaceInfo = bitmap->info().makeColorSpace(nullptr);
+
+ /* This intermediate surface is present to work around a bug in SwiftShader that
+ * prevents us from reading the contents of the layer's texture directly. The
+ * workaround involves first rendering that texture into an intermediate buffer and
+ * then reading from the intermediate buffer into the bitmap.
+ * Another reason to render in an offscreen buffer is to scale and to avoid an issue b/62262733
+ * with reading incorrect data from EGLImage backed SkImage (likely a driver bug).
+ */
+ sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
+ SkBudgeted::kYes, surfaceInfo);
+
+ if (!tmpSurface.get()) {
+ surfaceInfo = surfaceInfo.makeColorType(SkColorType::kN32_SkColorType);
+ tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
+ surfaceInfo);
+ if (!tmpSurface.get()) {
+ ALOGW("Unable to readback GPU contents into the provided bitmap");
+ return false;
+ }
+ }
+
+ if (skiapipeline::LayerDrawable::DrawLayer(mRenderThread.getGrContext(),
+ tmpSurface->getCanvas(), layer, srcRect, dstRect,
+ false)) {
+ // If bitmap->info().colorSpace() is non-SRGB, convert the data from SRGB to non-SRGB on
+ // CPU. We can't just pass bitmap->info() to SkSurface::readPixels, because "tmpSurface" has
+ // disabled color conversion.
+ SkColorSpace* destColorSpace = bitmap->info().colorSpace();
+ SkBitmap tempSRGBBitmap;
+ SkBitmap tmpN32Bitmap;
+ SkBitmap* bitmapInSRGB;
+ if (destColorSpace && !destColorSpace->isSRGB()) {
+ tempSRGBBitmap.allocPixels(bitmap->info().makeColorSpace(SkColorSpace::MakeSRGB()));
+ bitmapInSRGB = &tempSRGBBitmap; // Need to convert latter from SRGB to non-SRGB.
+ } else {
+ bitmapInSRGB = bitmap; // No need for color conversion - write directly into output.
+ }
+ bool success = false;
+
+ // TODO: does any of the readbacks below clamp F16 exSRGB?
+ // Readback into a SRGB SkBitmap.
+ if (tmpSurface->readPixels(bitmapInSRGB->info(), bitmapInSRGB->getPixels(),
+ bitmapInSRGB->rowBytes(), 0, 0)) {
+ success = true;
+ } else {
+ // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into
+ // 8888 and then convert that into the destination format before giving up.
+ SkImageInfo bitmapInfo =
+ SkImageInfo::MakeN32(bitmap->width(), bitmap->height(), bitmap->alphaType(),
+ SkColorSpace::MakeSRGB());
+ if (tmpN32Bitmap.tryAllocPixels(bitmapInfo) &&
+ tmpSurface->readPixels(bitmapInfo, tmpN32Bitmap.getPixels(),
+ tmpN32Bitmap.rowBytes(), 0, 0)) {
+ success = true;
+ bitmapInSRGB = &tmpN32Bitmap;
+ }
+ }
+
+ if (success) {
+ if (bitmapInSRGB != bitmap) {
+ // Convert from SRGB to non-SRGB color space if needed. Convert from N32 to
+ // destination bitmap color format if needed.
+ if (!bitmapInSRGB->readPixels(bitmap->info(), bitmap->getPixels(),
+ bitmap->rowBytes(), 0, 0)) {
+ return false;
+ }
+ }
+ bitmap->notifyPixelsChanged();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/Readback.h b/libs/hwui/Readback.h
index ad3a8b690617..d9e10cedc0e8 100644
--- a/libs/hwui/Readback.h
+++ b/libs/hwui/Readback.h
@@ -16,16 +16,21 @@
#pragma once
+#include "Matrix.h"
#include "Rect.h"
#include "renderthread/RenderThread.h"
#include <SkBitmap.h>
namespace android {
+class Bitmap;
class GraphicBuffer;
class Surface;
namespace uirenderer {
+class DeferredLayerUpdater;
+class Layer;
+
// Keep in sync with PixelCopy.java codes
enum class CopyResult {
Success = 0,
@@ -38,15 +43,22 @@ enum class CopyResult {
class Readback {
public:
+ explicit Readback(renderthread::RenderThread& thread) : mRenderThread(thread) {}
/**
* Copies the surface's most recently queued buffer into the provided bitmap.
*/
- virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) = 0;
- virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) = 0;
+ CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap);
-protected:
- explicit Readback(renderthread::RenderThread& thread) : mRenderThread(thread) {}
- virtual ~Readback() {}
+ CopyResult copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap);
+
+ CopyResult copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
+
+private:
+ CopyResult copyImageInto(const sk_sp<SkImage>& image, sk_sp<SkColorFilter>& colorSpaceFilter,
+ Matrix4& texTransform, const Rect& srcRect, SkBitmap* bitmap);
+
+ bool copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect,
+ SkBitmap* bitmap);
renderthread::RenderThread& mRenderThread;
};
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 3939696692d2..440620a6a417 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -290,7 +290,7 @@ void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
if (isHardware()) {
outBitmap->allocPixels(SkImageInfo::Make(info().width(), info().height(),
info().colorType(), info().alphaType(), nullptr));
- uirenderer::renderthread::RenderProxy::copyGraphicBufferInto(graphicBuffer(), outBitmap);
+ uirenderer::renderthread::RenderProxy::copyHWBitmapInto(this, outBitmap);
if (mInfo.colorSpace()) {
sk_sp<SkPixelRef> pixelRef = sk_ref_sp(outBitmap->pixelRef());
outBitmap->setInfo(mInfo);
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index b6cd4b08e5fe..3ca0f8139c02 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -28,12 +28,13 @@ namespace skiapipeline {
void LayerDrawable::onDraw(SkCanvas* canvas) {
Layer* layer = mLayerUpdater->backingLayer();
if (layer) {
- DrawLayer(canvas->getGrContext(), canvas, layer);
+ DrawLayer(canvas->getGrContext(), canvas, layer, nullptr, nullptr, true);
}
}
bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
- const SkRect* dstRect) {
+ const SkRect* srcRect, const SkRect* dstRect,
+ bool useLayerTransform) {
if (context == nullptr) {
SkDEBUGF(("Attempting to draw LayerDrawable into an unsupported surface"));
return false;
@@ -60,12 +61,10 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer
}
SkMatrix matrix;
- if (dstRect) {
- // Destination rectangle is set only when we are trying to read back the content
- // of the layer. In this case we don't want to apply layer transform.
- matrix = textureMatrix;
- } else {
+ if (useLayerTransform) {
matrix = SkMatrix::Concat(layerTransform, textureMatrix);
+ } else {
+ matrix = textureMatrix;
}
SkPaint paint;
@@ -81,16 +80,26 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer
canvas->save();
canvas->concat(matrix);
}
- if (dstRect) {
+ if (dstRect || srcRect) {
SkMatrix matrixInv;
if (!matrix.invert(&matrixInv)) {
matrixInv = matrix;
}
- SkRect srcRect = SkRect::MakeIWH(layerWidth, layerHeight);
- matrixInv.mapRect(&srcRect);
- SkRect skiaDestRect = *dstRect;
+ SkRect skiaSrcRect;
+ if (srcRect) {
+ skiaSrcRect = *srcRect;
+ } else {
+ skiaSrcRect = SkRect::MakeIWH(layerWidth, layerHeight);
+ }
+ matrixInv.mapRect(&skiaSrcRect);
+ SkRect skiaDestRect;
+ if (dstRect) {
+ skiaDestRect = *dstRect;
+ } else {
+ skiaDestRect = SkRect::MakeIWH(layerWidth, layerHeight);
+ }
matrixInv.mapRect(&skiaDestRect);
- canvas->drawImageRect(layerImage.get(), srcRect, skiaDestRect, &paint,
+ canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, &paint,
SkCanvas::kFast_SrcRectConstraint);
} else {
canvas->drawImage(layerImage.get(), 0, 0, &paint);
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.h b/libs/hwui/pipeline/skia/LayerDrawable.h
index 18d118405a39..5c125908ffb2 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.h
+++ b/libs/hwui/pipeline/skia/LayerDrawable.h
@@ -33,7 +33,7 @@ public:
explicit LayerDrawable(DeferredLayerUpdater* layerUpdater) : mLayerUpdater(layerUpdater) {}
static bool DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer,
- const SkRect* dstRect = nullptr);
+ const SkRect* srcRect, const SkRect* dstRect, bool useLayerTransform);
protected:
virtual SkRect onGetBounds() override {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 2ae37233098e..d58b59e83380 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -127,65 +127,6 @@ bool SkiaOpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect
return *requireSwap;
}
-bool SkiaOpenGLPipeline::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) {
- if (!mRenderThread.getGrContext()) {
- return false;
- }
-
- // acquire most recent buffer for drawing
- deferredLayer->updateTexImage();
- deferredLayer->apply();
-
- // drop the colorSpace as we only support readback into sRGB or extended sRGB
- SkImageInfo surfaceInfo = bitmap->info().makeColorSpace(nullptr);
-
- /* This intermediate surface is present to work around a bug in SwiftShader that
- * prevents us from reading the contents of the layer's texture directly. The
- * workaround involves first rendering that texture into an intermediate buffer and
- * then reading from the intermediate buffer into the bitmap.
- */
- sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(),
- SkBudgeted::kYes, surfaceInfo);
-
- if (!tmpSurface.get()) {
- surfaceInfo = surfaceInfo.makeColorType(SkColorType::kN32_SkColorType);
- tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes,
- surfaceInfo);
- if (!tmpSurface.get()) {
- ALOGW("Unable to readback GPU contents into the provided bitmap");
- return false;
- }
- }
-
- Layer* layer = deferredLayer->backingLayer();
- const SkRect dstRect = SkRect::MakeIWH(bitmap->width(), bitmap->height());
- if (LayerDrawable::DrawLayer(mRenderThread.getGrContext(), tmpSurface->getCanvas(), layer,
- &dstRect)) {
- sk_sp<SkImage> tmpImage = tmpSurface->makeImageSnapshot();
- if (tmpImage->readPixels(surfaceInfo, bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
- bitmap->notifyPixelsChanged();
- return true;
- }
-
- // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into 8888
- // and then draw that into the destination format before giving up.
- SkBitmap tmpBitmap;
- SkImageInfo bitmapInfo =
- SkImageInfo::MakeN32(bitmap->width(), bitmap->height(), bitmap->alphaType());
- if (tmpBitmap.tryAllocPixels(bitmapInfo) &&
- tmpImage->readPixels(bitmapInfo, tmpBitmap.getPixels(), tmpBitmap.rowBytes(), 0, 0)) {
- SkCanvas canvas(*bitmap);
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- canvas.drawBitmap(tmpBitmap, 0, 0, &paint);
- bitmap->notifyPixelsChanged();
- return true;
- }
- }
-
- return false;
-}
-
DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
mRenderThread.requireGlContext();
return new DeferredLayerUpdater(mRenderThread.renderState());
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index 2e2e1522b717..808685ad4460 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -40,7 +40,6 @@ public:
FrameInfoVisualizer* profiler) override;
bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
FrameInfo* currentFrameInfo, bool* requireSwap) override;
- bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
renderthread::ColorMode colorMode) override;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
deleted file mode 100644
index f2f5056bb195..000000000000
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SkiaOpenGLReadback.h"
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GrBackendSurface.h>
-#include <SkCanvas.h>
-#include <SkSurface.h>
-#include <gl/GrGLInterface.h>
-#include <gl/GrGLTypes.h>
-#include "DeviceInfo.h"
-#include "Matrix.h"
-#include "Properties.h"
-#include "utils/MathUtils.h"
-
-using namespace android::uirenderer::renderthread;
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
- int imgWidth, int imgHeight, const Rect& srcRect,
- SkBitmap* bitmap) {
- GLuint sourceTexId;
- glGenTextures(1, &sourceTexId);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
- glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);
-
- sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext());
- if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
- LOG_ALWAYS_FATAL_IF(!glInterface.get());
- grContext = GrContext::MakeGL(std::move(glInterface));
- } else {
- grContext->resetContext();
- }
-
- if (bitmap->colorType() == kRGBA_F16_SkColorType &&
- !grContext->colorTypeSupportedAsSurface(bitmap->colorType())) {
- ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
- return CopyResult::DestinationInvalid;
- }
-
- GrGLTextureInfo externalTexture;
- externalTexture.fTarget = GL_TEXTURE_EXTERNAL_OES;
- externalTexture.fID = sourceTexId;
- switch (bitmap->colorType()) {
- case kRGBA_F16_SkColorType:
- externalTexture.fFormat = GL_RGBA16F;
- break;
- case kN32_SkColorType:
- default:
- externalTexture.fFormat = GL_RGBA8;
- break;
- }
-
- GrBackendTexture backendTexture(imgWidth, imgHeight, GrMipMapped::kNo, externalTexture);
-
- CopyResult copyResult = CopyResult::UnknownError;
- sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), backendTexture,
- kTopLeft_GrSurfaceOrigin,
- bitmap->colorType()));
- if (image) {
- int displayedWidth = imgWidth, displayedHeight = imgHeight;
- // If this is a 90 or 270 degree rotation we need to swap width/height to get the device
- // size.
- if (imgTransform[Matrix4::kSkewX] >= 0.5f || imgTransform[Matrix4::kSkewX] <= -0.5f) {
- std::swap(displayedWidth, displayedHeight);
- }
- SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
- SkRect skiaSrcRect = srcRect.toSkRect();
- if (skiaSrcRect.isEmpty()) {
- skiaSrcRect = SkRect::MakeIWH(displayedWidth, displayedHeight);
- }
- bool srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(displayedWidth, displayedHeight));
-
- if (srcNotEmpty) {
- SkMatrix textureMatrixInv;
- imgTransform.copyTo(textureMatrixInv);
- // TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed
- // use bottom left origin and remove flipV and invert transformations.
- SkMatrix flipV;
- flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1);
- textureMatrixInv.preConcat(flipV);
- textureMatrixInv.preScale(1.0f / displayedWidth, 1.0f / displayedHeight);
- textureMatrixInv.postScale(imgWidth, imgHeight);
- SkMatrix textureMatrix;
- if (!textureMatrixInv.invert(&textureMatrix)) {
- textureMatrix = textureMatrixInv;
- }
-
- textureMatrixInv.mapRect(&skiaSrcRect);
- textureMatrixInv.mapRect(&skiaDestRect);
-
- // we render in an offscreen buffer to scale and to avoid an issue b/62262733
- // with reading incorrect data from EGLImage backed SkImage (likely a driver bug)
- sk_sp<SkSurface> scaledSurface =
- SkSurface::MakeRenderTarget(grContext.get(), SkBudgeted::kYes, bitmap->info());
- SkPaint paint;
- paint.setBlendMode(SkBlendMode::kSrc);
- // Apply a filter, which is matching OpenGL pipeline readback behaviour. Filter usage
- // is codified by tests using golden images like DecodeAccuracyTest.
- bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width())
- && MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height());
- if (!disableFilter) {
- paint.setFilterQuality(kLow_SkFilterQuality);
- }
- scaledSurface->getCanvas()->concat(textureMatrix);
- scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint,
- SkCanvas::kFast_SrcRectConstraint);
-
- image = scaledSurface->makeImageSnapshot();
-
- if (image->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
- bitmap->notifyPixelsChanged();
- copyResult = CopyResult::Success;
- }
- }
- }
-
- // make sure that we have deleted the texture (in the SkImage) before we
- // destroy the EGLImage that it was created from
- image.reset();
- glFinish();
-
- return copyResult;
-}
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h
deleted file mode 100644
index 1ce4773e7d67..000000000000
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "EglReadback.h"
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-class SkiaOpenGLReadback : public EglReadback {
-public:
- SkiaOpenGLReadback(renderthread::RenderThread& thread) : EglReadback(thread) {}
-
-protected:
- virtual CopyResult copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform,
- int imgWidth, int imgHeight, const Rect& srcRect,
- SkBitmap* bitmap) override;
-};
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 5f2eee4523fc..611a34c069d4 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -108,11 +108,6 @@ bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect
return *requireSwap;
}
-bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
- // TODO: implement copyLayerInto for vulkan.
- return false;
-}
-
DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
mVkManager.initialize();
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 7806b42e03dc..900b054e35bd 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -38,7 +38,6 @@ public:
FrameInfoVisualizer* profiler) override;
bool swapBuffers(const renderthread::Frame& frame, bool drew, const SkRect& screenDirty,
FrameInfo* currentFrameInfo, bool* requireSwap) override;
- bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) override;
DeferredLayerUpdater* createTextureLayer() override;
bool setSurface(Surface* window, renderthread::SwapBehavior swapBehavior,
renderthread::ColorMode colorMode) override;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanReadback.h b/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
deleted file mode 100644
index 65b89d617f7b..000000000000
--- a/libs/hwui/pipeline/skia/SkiaVulkanReadback.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "Readback.h"
-
-namespace android {
-namespace uirenderer {
-namespace skiapipeline {
-
-class SkiaVulkanReadback : public Readback {
-public:
- SkiaVulkanReadback(renderthread::RenderThread& thread) : Readback(thread) {}
-
- virtual CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect,
- SkBitmap* bitmap) override {
- //TODO: implement Vulkan readback.
- return CopyResult::UnknownError;
- }
-
- virtual CopyResult copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
- SkBitmap* bitmap) override {
- //TODO: implement Vulkan readback.
- return CopyResult::UnknownError;
- }
-};
-
-} /* namespace skiapipeline */
-} /* namespace uirenderer */
-} /* namespace android */
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8b07d1dadeb6..727cef3035f5 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -562,10 +562,6 @@ void CanvasContext::buildLayer(RenderNode* node) {
mPrefetchedLayers.insert(node);
}
-bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
- return mRenderPipeline->copyLayerInto(layer, bitmap);
-}
-
void CanvasContext::destroyHardwareResources() {
stopDrawing();
if (mRenderPipeline->isContextReady()) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 8ca54af13baa..02ee72f05f04 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -135,7 +135,6 @@ public:
void prepareAndDraw(RenderNode* node);
void buildLayer(RenderNode* node);
- bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
void markLayerInUse(RenderNode* node);
void destroyHardwareResources();
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index b94a7588a507..b7b7853e6ed7 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -60,7 +60,6 @@ public:
FrameInfoVisualizer* profiler) = 0;
virtual bool swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
FrameInfo* currentFrameInfo, bool* requireSwap) = 0;
- virtual bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) = 0;
virtual DeferredLayerUpdater* createTextureLayer() = 0;
virtual bool setSurface(Surface* window, SwapBehavior swapBehavior, ColorMode colorMode) = 0;
virtual void onStop() = 0;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index e3807e634890..7a5348ac85d9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -160,8 +160,10 @@ void RenderProxy::buildLayer(RenderNode* node) {
}
bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
- return mRenderThread.queue().runSync(
- [&]() -> bool { return mContext->copyLayerInto(layer, &bitmap); });
+ auto& thread = RenderThread::getInstance();
+ return thread.queue().runSync(
+ [&]() -> bool { return thread.readback().copyLayerInto(layer, &bitmap)
+ == CopyResult::Success; });
}
void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
@@ -331,14 +333,14 @@ void RenderProxy::prepareToDraw(Bitmap& bitmap) {
}
}
-int RenderProxy::copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap) {
+int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
RenderThread& thread = RenderThread::getInstance();
if (gettid() == thread.getTid()) {
// TODO: fix everything that hits this. We should never be triggering a readback ourselves.
- return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
+ return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap);
} else {
return thread.queue().runSync([&]() -> int {
- return (int)thread.readback().copyGraphicBufferInto(buffer, bitmap);
+ return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap);
});
}
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index c2964a4e3515..969ad00d7443 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -125,7 +125,7 @@ public:
int bottom, SkBitmap* bitmap);
ANDROID_API static void prepareToDraw(Bitmap& bitmap);
- static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
+ static int copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap);
static void onBitmapDestroyed(uint32_t pixelRefId);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 2322fbf21f27..7258a0aa4f02 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -19,13 +19,12 @@
#include "CanvasContext.h"
#include "DeviceInfo.h"
#include "EglManager.h"
+#include "Readback.h"
#include "RenderProxy.h"
#include "VulkanManager.h"
#include "hwui/Bitmap.h"
#include "pipeline/skia/SkiaOpenGLPipeline.h"
-#include "pipeline/skia/SkiaOpenGLReadback.h"
#include "pipeline/skia/SkiaVulkanPipeline.h"
-#include "pipeline/skia/SkiaVulkanReadback.h"
#include "renderstate/RenderState.h"
#include "utils/FatVector.h"
#include "utils/TimeUtils.h"
@@ -235,18 +234,7 @@ void RenderThread::dumpGraphicsMemory(int fd) {
Readback& RenderThread::readback() {
if (!mReadback) {
- auto renderType = Properties::getRenderPipelineType();
- switch (renderType) {
- case RenderPipelineType::SkiaGL:
- mReadback = new skiapipeline::SkiaOpenGLReadback(*this);
- break;
- case RenderPipelineType::SkiaVulkan:
- mReadback = new skiapipeline::SkiaVulkanReadback(*this);
- break;
- default:
- LOG_ALWAYS_FATAL("canvas context type %d not supported", (int32_t)renderType);
- break;
- }
+ mReadback = new Readback(*this);
}
return *mReadback;