Support readback of TextureView into 565 and extended sRGB.
Bug: 78906699
Test: CtsViewTestCases
Change-Id: I89e8544a883dcb3eb222c164ab57d20e55a073c3
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index d732a46..79bb534 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -28,6 +28,8 @@
#include "utils/TraceUtils.h"
#include <GrBackendSurface.h>
+#include <SkImageInfo.h>
+#include <SkBlendMode.h>
#include <cutils/properties.h>
#include <strings.h>
@@ -129,20 +131,49 @@
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, bitmap->info());
+ 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(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
+ 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;
}