Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71b257b5 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix Skia pipeline readback for non-portrait mode"

parents 5ebf55c9 df6520ef
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -85,11 +85,6 @@ CopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer,

    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 @@ CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage,
        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
+30 −16
Original line number Diff line number Diff line
@@ -60,37 +60,51 @@ CopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4
    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
        // 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 = bufferRect;
                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)) {