OpenGLReadback.cpp revision 912bebeb7488f498954282a1eb82a4b641e6418e
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"
22764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik#include "Layer.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
111c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger////////////////////////////////////////////////////////////////////////////////
112c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger////////////////////////////////////////////////////////////////////////////////
113c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
114c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergerinline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
115c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        Texture& sourceTexture, const Matrix4& texTransform, const Rect& srcRect,
1169580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        SkBitmap* bitmap) {
11710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    int destWidth = bitmap->width();
11810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    int destHeight = bitmap->height();
11910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (destWidth > caches.maxTextureSize
12010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                || destHeight > caches.maxTextureSize) {
12110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGW("Can't copy surface into bitmap, %dx%d exceeds max texture size %d",
12210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                destWidth, destHeight, caches.maxTextureSize);
123e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::DestinationInvalid;
12410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
12510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLuint fbo = renderState.createFramebuffer();
12610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (!fbo) {
12710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGW("Could not obtain an FBO");
128e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
12910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
13010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
13110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    SkAutoLockPixels alp(*bitmap);
13210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
13310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLuint texture;
13410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
13510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLenum format;
13610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLenum type;
13710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
13810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    switch (bitmap->colorType()) {
13910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kAlpha_8_SkColorType:
14010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_ALPHA;
14110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_BYTE;
14210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
14310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kRGB_565_SkColorType:
14410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGB;
14510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_SHORT_5_6_5;
14610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
14710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kARGB_4444_SkColorType:
14810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGBA;
14910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_SHORT_4_4_4_4;
15010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
15110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kN32_SkColorType:
15210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        default:
15310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGBA;
15410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_BYTE;
15510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
15610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
15710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
15810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    renderState.bindFramebuffer(fbo);
15910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
16010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // TODO: Use layerPool or something to get this maybe? But since we
16110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // need explicit format control we can't currently.
16210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
16310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // Setup the rendertarget
16410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glGenTextures(1, &texture);
16510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    caches.textureState().activateTexture(0);
16610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    caches.textureState().bindTexture(texture);
16710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
16810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
16910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
17010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
17110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
17210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexImage2D(GL_TEXTURE_2D, 0, format, destWidth, destHeight,
17310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            0, format, type, nullptr);
17410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
17510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            GL_TEXTURE_2D, texture, 0);
17610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
177764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    {
178764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        // Draw & readback
179764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.setViewport(destWidth, destHeight);
180764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.scissor().setEnabled(false);
181764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.blend().syncEnabled();
182764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.stencil().disable();
183764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
1849580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        Matrix4 croppedTexTransform(texTransform);
1859580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        if (!srcRect.isEmpty()) {
1869580146f5076aaa7c498f86bd3d724c00599f6f4John Reck            croppedTexTransform.loadTranslate(srcRect.left / sourceTexture.width(),
1879580146f5076aaa7c498f86bd3d724c00599f6f4John Reck                    srcRect.top / sourceTexture.height(), 0);
1889580146f5076aaa7c498f86bd3d724c00599f6f4John Reck            croppedTexTransform.scale(srcRect.getWidth() / sourceTexture.width(),
1899580146f5076aaa7c498f86bd3d724c00599f6f4John Reck                    srcRect.getHeight() / sourceTexture.height(), 1);
1909580146f5076aaa7c498f86bd3d724c00599f6f4John Reck            croppedTexTransform.multiply(texTransform);
1919580146f5076aaa7c498f86bd3d724c00599f6f4John Reck        }
192764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        Glop glop;
193764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        GlopBuilder(renderState, caches, &glop)
194764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setRoundRectClipState(nullptr)
195764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setMeshTexturedUnitQuad(nullptr)
1969580146f5076aaa7c498f86bd3d724c00599f6f4John Reck                .setFillExternalTexture(sourceTexture, croppedTexTransform)
197764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setTransform(Matrix4::identity(), TransformFlags::None)
198764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .setModelViewMapUnitToRect(Rect(destWidth, destHeight))
199764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                .build();
200764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        Matrix4 ortho;
201764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        ortho.loadOrtho(destWidth, destHeight);
202764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        renderState.render(glop, ortho);
203764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
204764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
205764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik                type, bitmap->getPixels());
206764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    }
207764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
208764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    // Cleanup
209764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    caches.textureState().deleteTexture(texture);
210764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    renderState.deleteFramebuffer(fbo);
211764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
212764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    GL_CHECKPOINT(MODERATE);
213764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
214764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    return CopyResult::Success;
215764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik}
216764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
217c4fbada76aa840105553b2c2bce2204e673d2983Derek SollenbergerCopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage,
218c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        const Matrix4& imgTransform, int imgWidth, int imgHeight, const Rect& srcRect,
219c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger        SkBitmap* bitmap) {
220764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik
221764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    Caches& caches = Caches::getInstance();
2222f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    GLuint sourceTexId;
2232f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    // Create a 2D texture to sample from the EGLImage
2242f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    glGenTextures(1, &sourceTexId);
225764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik    caches.textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
226c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage);
2272f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
2282f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    GLenum status = GL_NO_ERROR;
2292f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    while ((status = glGetError()) != GL_NO_ERROR) {
2308a29c0ec86a9411a07bb10018c3da69fffc0fe7dJohn Reck        ALOGW("glEGLImageTargetTexture2DOES failed (%#x)", status);
231e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
23210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
2332f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
23410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    Texture sourceTexture(caches);
235c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    sourceTexture.wrap(sourceTexId, imgWidth, imgHeight, 0, 0 /* total lie */,
236c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            GL_TEXTURE_EXTERNAL_OES);
23710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
238c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    CopyResult copyResult = copyTextureInto(caches, mRenderThread.renderState(),
239c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            sourceTexture, imgTransform, srcRect, bitmap);
2408a29c0ec86a9411a07bb10018c3da69fffc0fe7dJohn Reck    sourceTexture.deleteTexture();
2418a29c0ec86a9411a07bb10018c3da69fffc0fe7dJohn Reck    return copyResult;
242764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik}
24310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
244c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergerbool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread,
245764045da2ce980f1eee78171de5b4f09dfb601a7Chris Craik        Layer& layer, SkBitmap* bitmap) {
246c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger    return CopyResult::Success == copyTextureInto(Caches::getInstance(),
247c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            renderThread.renderState(), layer.getTexture(), layer.getTexTransform(),
248c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger            Rect(), bitmap);
24910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck}
25010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
251c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger
25210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck} // namespace uirenderer
25310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck} // namespace android
254