110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck/*
210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * Copyright (C) 2016 The Android Open Source Project
310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck *
410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * Licensed under the Apache License, Version 2.0 (the "License");
510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * you may not use this file except in compliance with the License.
610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * You may obtain a copy of the License at
710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck *
810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck *      http://www.apache.org/licenses/LICENSE-2.0
910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck *
1010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * Unless required by applicable law or agreed to in writing, software
1110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * distributed under the License is distributed on an "AS IS" BASIS,
1210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * See the License for the specific language governing permissions and
1410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck * limitations under the License.
1510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck */
1610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
17c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include "OpenGLReadback.h"
1810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
1910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "Caches.h"
2010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "Image.h"
2110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "GlopBuilder.h"
228cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel#include "GlLayer.h"
2310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "renderstate/RenderState.h"
2410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "renderthread/EglManager.h"
2510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "utils/GLUtils.h"
2610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
2710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include <GLES2/gl2.h>
2810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include <ui/Fence.h>
2910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include <ui/GraphicBuffer.h>
3010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
3110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Recknamespace android {
3210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Recknamespace uirenderer {
3310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
34c4fbada76aa840105553b2c2bce2204e673d2983Derek SollenbergerCopyResult OpenGLReadback::copySurfaceInto(Surface& surface, const Rect& srcRect,
35c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        SkBitmap* bitmap) {
36c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    ATRACE_CALL();
37c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // Setup the source
38c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    sp<GraphicBuffer> sourceBuffer;
39c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    sp<Fence> sourceFence;
40c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    Matrix4 texTransform;
41c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence,
42c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            texTransform.data);
43c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    texTransform.invalidateType();
44c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    if (err != NO_ERROR) {
45c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        ALOGW("Failed to get last queued buffer, error = %d", err);
46c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        return CopyResult::UnknownError;
47c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    }
48c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    if (!sourceBuffer.get()) {
49c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
50c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        return CopyResult::SourceEmpty;
51c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    }
52c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) {
53c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        ALOGW("Surface is protected, unable to copy from it");
54c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        return CopyResult::SourceInvalid;
55c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    }
56c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    err = sourceFence->wait(500 /* ms */);
57c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    if (err != NO_ERROR) {
58c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
59c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        return CopyResult::Timeout;
60c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    }
61c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
6259eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    return copyGraphicBufferInto(sourceBuffer.get(), texTransform, srcRect, bitmap);
6359eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv}
6459eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv
6559eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyvCopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer,
6659eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv        Matrix4& texTransform, const Rect& srcRect, SkBitmap* bitmap) {
6759eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    mRenderThread.eglManager().initialize();
68c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via
69c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // GL_OES_EGL_image, which doesn't work since we need samplerExternalOES
70c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // to be able to properly sample from the buffer.
71c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
72c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // Create the EGLImage object that maps the GraphicBuffer
73c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
7459eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    EGLClientBuffer clientBuffer = (EGLClientBuffer) graphicBuffer->getNativeBuffer();
75c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
76c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
77c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT,
78c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
79c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
80c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    if (sourceImage == EGL_NO_IMAGE_KHR) {
81c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        ALOGW("eglCreateImageKHR failed (%#x)", eglGetError());
82c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        return CopyResult::UnknownError;
83c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    }
84c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
85912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck    uint32_t width = graphicBuffer->getWidth();
86912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck    uint32_t height = graphicBuffer->getHeight();
87912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck    // If this is a 90 or 270 degree rotation we need to swap width/height
88912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck    // This is a fuzzy way of checking that.
89912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck    if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) {
90912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck        std::swap(width, height);
91912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck    }
92912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck    CopyResult copyResult = copyImageInto(sourceImage, texTransform, width, height,
93912bebeb7488f498954282a1eb82a4b641e6418eJohn Reck            srcRect, bitmap);
94c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
95c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // All we're flushing & finishing is the deletion of the texture since
96c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // copyImageInto already did a major flush & finish as an implicit
97c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    // part of glReadPixels, so this shouldn't pose any major stalls.
98c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    glFinish();
99c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    eglDestroyImageKHR(display, sourceImage);
100c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    return copyResult;
101c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger}
102c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
10359eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyvCopyResult OpenGLReadback::copyGraphicBufferInto(GraphicBuffer* graphicBuffer, SkBitmap* bitmap) {
10459eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    Rect srcRect;
10559eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    Matrix4 transform;
10659eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    transform.loadScale(1, -1, 1);
10759eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    transform.translate(0, -1);
10859eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv    return copyGraphicBufferInto(graphicBuffer, transform, srcRect, bitmap);
10959eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv}
11059eecb526adc5bd7041e7b6147bfcc40dd2c200esergeyv
111eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reckstatic float sFlipVInit[16] = {
112eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck    1, 0, 0, 0,
113eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck    0, -1, 0, 0,
114eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck    0, 0, 1, 0,
115eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck    0, 1, 0, 1,
116eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck};
117eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck
118eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reckstatic const Matrix4 sFlipV(sFlipVInit);
119eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck
120c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger////////////////////////////////////////////////////////////////////////////////
121c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger////////////////////////////////////////////////////////////////////////////////
122c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
123c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergerinline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
124c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        Texture& sourceTexture, const Matrix4& texTransform, const Rect& srcRect,
1259580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        SkBitmap* bitmap) {
12610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    int destWidth = bitmap->width();
12710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    int destHeight = bitmap->height();
12810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (destWidth > caches.maxTextureSize
12910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                || destHeight > caches.maxTextureSize) {
13010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGW("Can't copy surface into bitmap, %dx%d exceeds max texture size %d",
13110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                destWidth, destHeight, caches.maxTextureSize);
132e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::DestinationInvalid;
13310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
1349505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
1359505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    // TODO: Add support for RGBA_F16 destinations
1369505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    if (bitmap->colorType() == kRGBA_F16_SkColorType) {
1379505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
1389505a6552764461c22ce48f1ac13d025d23e1579Romain Guy        return CopyResult::DestinationInvalid;
1399505a6552764461c22ce48f1ac13d025d23e1579Romain Guy    }
1409505a6552764461c22ce48f1ac13d025d23e1579Romain Guy
14110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLuint fbo = renderState.createFramebuffer();
14210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (!fbo) {
14310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGW("Could not obtain an FBO");
144e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
14510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
14610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
14710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    SkAutoLockPixels alp(*bitmap);
14810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
14910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLuint texture;
15010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
15110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLenum format;
15210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLenum type;
15310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
15410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    switch (bitmap->colorType()) {
15510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kAlpha_8_SkColorType:
15610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_ALPHA;
15710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_BYTE;
15810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
15910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kRGB_565_SkColorType:
16010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGB;
16110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_SHORT_5_6_5;
16210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
16310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kARGB_4444_SkColorType:
16410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGBA;
16510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_SHORT_4_4_4_4;
16610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
16710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kN32_SkColorType:
16810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        default:
16910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGBA;
17010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_BYTE;
17110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
17210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
17310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
17410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    renderState.bindFramebuffer(fbo);
17510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
17610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // TODO: Use layerPool or something to get this maybe? But since we
17710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // need explicit format control we can't currently.
17810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
17910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // Setup the rendertarget
18010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glGenTextures(1, &texture);
18110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    caches.textureState().activateTexture(0);
18210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    caches.textureState().bindTexture(texture);
18310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
18410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
18510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
18610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
18710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
18810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexImage2D(GL_TEXTURE_2D, 0, format, destWidth, destHeight,
18910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            0, format, type, nullptr);
19010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
19110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            GL_TEXTURE_2D, texture, 0);
19210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
193764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    {
1945462b79d9fd787ab189bcd29b591ca72f900220fJohn Reck        bool requiresFilter;
195764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        // Draw & readback
196764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.setViewport(destWidth, destHeight);
197764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.scissor().setEnabled(false);
198764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.blend().syncEnabled();
199764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.stencil().disable();
200764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
2019580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        Matrix4 croppedTexTransform(texTransform);
2029580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        if (!srcRect.isEmpty()) {
203eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck            // We flipV to convert to 0,0 top-left for the srcRect
204eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck            // coordinates then flip back to 0,0 bottom-left for
205eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck            // GLES coordinates.
206eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck            croppedTexTransform.multiply(sFlipV);
207eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck            croppedTexTransform.translate(srcRect.left / sourceTexture.width(),
2089580146f5076aaa7c498f86bd3d724c00599f6f4John Reck                    srcRect.top / sourceTexture.height(), 0);
2099580146f5076aaa7c498f86bd3d724c00599f6f4John Reck            croppedTexTransform.scale(srcRect.getWidth() / sourceTexture.width(),
2109580146f5076aaa7c498f86bd3d724c00599f6f4John Reck                    srcRect.getHeight() / sourceTexture.height(), 1);
211eb418edae488c0c13edcc10e829bbb0e21eb23acJohn Reck            croppedTexTransform.multiply(sFlipV);
2125462b79d9fd787ab189bcd29b591ca72f900220fJohn Reck            requiresFilter = srcRect.getWidth() != (float) destWidth
2135462b79d9fd787ab189bcd29b591ca72f900220fJohn Reck                    || srcRect.getHeight() != (float) destHeight;
2145462b79d9fd787ab189bcd29b591ca72f900220fJohn Reck        } else {
2155462b79d9fd787ab189bcd29b591ca72f900220fJohn Reck            requiresFilter = sourceTexture.width() != (uint32_t) destWidth
2165462b79d9fd787ab189bcd29b591ca72f900220fJohn Reck                    || sourceTexture.height() != (uint32_t) destHeight;
2179580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        }
218764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        Glop glop;
219764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        GlopBuilder(renderState, caches, &glop)
220764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setRoundRectClipState(nullptr)
221764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setMeshTexturedUnitQuad(nullptr)
2225462b79d9fd787ab189bcd29b591ca72f900220fJohn Reck                .setFillExternalTexture(sourceTexture, croppedTexTransform, requiresFilter)
223764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setTransform(Matrix4::identity(), TransformFlags::None)
224764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setModelViewMapUnitToRect(Rect(destWidth, destHeight))
225764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .build();
226764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        Matrix4 ortho;
227764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        ortho.loadOrtho(destWidth, destHeight);
228764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.render(glop, ortho);
229764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
230764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
231764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                type, bitmap->getPixels());
232764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    }
233764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
234764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    // Cleanup
235764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    caches.textureState().deleteTexture(texture);
236764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    renderState.deleteFramebuffer(fbo);
237764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
238764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    GL_CHECKPOINT(MODERATE);
239764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
240764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    return CopyResult::Success;
241764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik}
242764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
243c4fbada76aa840105553b2c2bce2204e673d2983Derek SollenbergerCopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage,
244c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        const Matrix4& imgTransform, int imgWidth, int imgHeight, const Rect& srcRect,
245c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        SkBitmap* bitmap) {
246764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
247764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    Caches& caches = Caches::getInstance();
2482f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    GLuint sourceTexId;
2492f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    // Create a 2D texture to sample from the EGLImage
2502f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    glGenTextures(1, &sourceTexId);
251764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    caches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
252c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);
2532f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
2542f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    GLenum status = GL_NO_ERROR;
2552f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    while ((status = glGetError()) != GL_NO_ERROR) {
2568a29c0ec86a9411a07bb10018c3da69fffc0fe7dJohn Reck        ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status);
257e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
25810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
2592f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
26010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    Texture sourceTexture(caches);
261c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    sourceTexture.wrap(sourceTexId, imgWidth, imgHeight, 0, 0 /* total lie */,
262c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            GL_TEXTURE_EXTERNAL_OES);
26310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
264c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    CopyResult copyResult = copyTextureInto(caches, mRenderThread.renderState(),
265c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            sourceTexture, imgTransform, srcRect, bitmap);
2668a29c0ec86a9411a07bb10018c3da69fffc0fe7dJohn Reck    sourceTexture.deleteTexture();
2678a29c0ec86a9411a07bb10018c3da69fffc0fe7dJohn Reck    return copyResult;
268764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik}
26910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
270c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergerbool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread,
2718cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel        GlLayer& layer, SkBitmap* bitmap) {
272c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    return CopyResult::Success == copyTextureInto(Caches::getInstance(),
273c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            renderThread.renderState(), layer.getTexture(), layer.getTexTransform(),
274c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            Rect(), bitmap);
27510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck}
27610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
277c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
27810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck} // namespace uirenderer
27910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck} // namespace android
280