Merge "Fix Skia pipeline readback for non-portrait mode"
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index e798edf..025503b 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -85,11 +85,6 @@
uint32_t width = graphicBuffer->getWidth();
uint32_t height = graphicBuffer->getHeight();
- // If this is a 90 or 270 degree rotation we need to swap width/height
- // This is a fuzzy way of checking that.
- if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) {
- std::swap(width, height);
- }
CopyResult copyResult = copyImageInto(sourceImage, texTransform, width, height,
srcRect, bitmap);
@@ -254,6 +249,12 @@
const Matrix4& imgTransform, int imgWidth, int imgHeight, const Rect& srcRect,
SkBitmap* bitmap) {
+ // If this is a 90 or 270 degree rotation we need to swap width/height
+ // This is a fuzzy way of checking that.
+ if (imgTransform[Matrix4::kSkewX] >= 0.5f || imgTransform[Matrix4::kSkewX] <= -0.5f) {
+ std::swap(imgWidth, imgHeight);
+ }
+
Caches& caches = Caches::getInstance();
GLuint sourceTexId;
// Create a 2D texture to sample from the EGLImage
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
index 69b9c01fe..311419d 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLReadback.cpp
@@ -60,37 +60,51 @@
sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), backendTexture,
kTopLeft_GrSurfaceOrigin));
if (image) {
- // convert to Skia data structures
- const SkRect bufferRect = SkRect::MakeIWH(imgWidth, imgHeight);
- SkRect skiaSrcRect = srcRect.toSkRect();
SkMatrix textureMatrix;
imgTransform.copyTo(textureMatrix);
- // remove the y-flip applied to the matrix so that we can scale the srcRect.
- // This flip is not needed as we specify the origin of the texture when we
- // wrap it as an SkImage.
+ // remove the y-flip applied to the matrix
SkMatrix yFlip = SkMatrix::MakeScale(1, -1);
yFlip.postTranslate(0,1);
textureMatrix.preConcat(yFlip);
- // copy the entire src if the rect is empty
- if (skiaSrcRect.isEmpty()) {
- skiaSrcRect = bufferRect;
+ // multiply by image size, because textureMatrix maps to [0..1] range
+ textureMatrix[SkMatrix::kMTransX] *= imgWidth;
+ textureMatrix[SkMatrix::kMTransY] *= imgHeight;
+
+ // swap rotation and translation part of the matrix, because we convert from
+ // right-handed Cartesian to left-handed coordinate system.
+ std::swap(textureMatrix[SkMatrix::kMTransX], textureMatrix[SkMatrix::kMTransY]);
+ std::swap(textureMatrix[SkMatrix::kMSkewX], textureMatrix[SkMatrix::kMSkewY]);
+
+ // convert to Skia data structures
+ SkRect skiaSrcRect = srcRect.toSkRect();
+ SkMatrix textureMatrixInv;
+ SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height());
+ bool srcNotEmpty = false;
+ if (textureMatrix.invert(&textureMatrixInv)) {
+ if (skiaSrcRect.isEmpty()) {
+ skiaSrcRect = SkRect::MakeIWH(imgWidth, imgHeight);
+ srcNotEmpty = !skiaSrcRect.isEmpty();
+ } else {
+ // src and dest rectangles need to be converted into texture coordinates before the
+ // rotation matrix is applied (because drawImageRect preconcat its matrix).
+ textureMatrixInv.mapRect(&skiaSrcRect);
+ srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(imgWidth, imgHeight));
+ }
+ textureMatrixInv.mapRect(&skiaDestRect);
}
- // since the y-flip has been removed we can simply scale & translate
- // the source rectangle
- textureMatrix.mapRect(&skiaSrcRect);
-
- if (skiaSrcRect.intersect(bufferRect)) {
+ if (srcNotEmpty) {
// 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);
- scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect,
- SkRect::MakeWH(bitmap->width(), bitmap->height()), &paint);
+ scaledSurface->getCanvas()->concat(textureMatrix);
+ scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, skiaDestRect, &paint);
+
image = scaledSurface->makeImageSnapshot();
if (image->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {