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
1710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "Readback.h"
1810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
1910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "Caches.h"
2010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "Image.h"
2110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "GlopBuilder.h"
2210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "renderstate/RenderState.h"
2310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "renderthread/EglManager.h"
2410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include "utils/GLUtils.h"
2510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
2610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include <GLES2/gl2.h>
2710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include <ui/Fence.h>
2810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck#include <ui/GraphicBuffer.h>
2910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
3010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Recknamespace android {
3110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Recknamespace uirenderer {
3210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
33e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John ReckCopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread,
3410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        Surface& surface, SkBitmap* bitmap) {
3510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // TODO: Clean this up and unify it with LayerRenderer::copyLayer,
3610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // of which most of this is copied from.
3710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    renderThread.eglManager().initialize();
3810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
3910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    Caches& caches = Caches::getInstance();
4010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    RenderState& renderState = renderThread.renderState();
4110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    int destWidth = bitmap->width();
4210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    int destHeight = bitmap->height();
4310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (destWidth > caches.maxTextureSize
4410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                || destHeight > caches.maxTextureSize) {
4510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGW("Can't copy surface into bitmap, %dx%d exceeds max texture size %d",
4610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                destWidth, destHeight, caches.maxTextureSize);
47e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::DestinationInvalid;
4810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
4910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLuint fbo = renderState.createFramebuffer();
5010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (!fbo) {
5110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGW("Could not obtain an FBO");
52e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
5310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
5410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
5510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    SkAutoLockPixels alp(*bitmap);
5610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
5710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLuint texture;
5810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
5910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLenum format;
6010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GLenum type;
6110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
6210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    switch (bitmap->colorType()) {
6310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kAlpha_8_SkColorType:
6410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_ALPHA;
6510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_BYTE;
6610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
6710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kRGB_565_SkColorType:
6810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGB;
6910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_SHORT_5_6_5;
7010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
7110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kARGB_4444_SkColorType:
7210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGBA;
7310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_SHORT_4_4_4_4;
7410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
7510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        case kN32_SkColorType:
7610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        default:
7710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            format = GL_RGBA;
7810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            type = GL_UNSIGNED_BYTE;
7910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            break;
8010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
8110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
8210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    renderState.bindFramebuffer(fbo);
8310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
8410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // TODO: Use layerPool or something to get this maybe? But since we
8510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // need explicit format control we can't currently.
8610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
8710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // Setup the rendertarget
8810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glGenTextures(1, &texture);
8910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    caches.textureState().activateTexture(0);
9010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    caches.textureState().bindTexture(texture);
9110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glPixelStorei(GL_PACK_ALIGNMENT, bitmap->bytesPerPixel());
9210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
9310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
9410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glTexImage2D(GL_TEXTURE_2D, 0, format, destWidth, destHeight,
9710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            0, format, type, nullptr);
9810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
9910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            GL_TEXTURE_2D, texture, 0);
10010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
10110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // Setup the source
10210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    sp<GraphicBuffer> sourceBuffer;
10310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    sp<Fence> sourceFence;
1042f69d6d4fdd4994912e5515016421625d1e1c4ecJohn Reck    Matrix4 texTransform;
1052f69d6d4fdd4994912e5515016421625d1e1c4ecJohn Reck    status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence,
1062f69d6d4fdd4994912e5515016421625d1e1c4ecJohn Reck            texTransform.data);
1072f69d6d4fdd4994912e5515016421625d1e1c4ecJohn Reck    texTransform.invalidateType();
1082f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    if (err != NO_ERROR) {
1092f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck        ALOGW("Failed to get last queued buffer, error = %d", err);
110e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
1112f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    }
11210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (!sourceBuffer.get()) {
11310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
114e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::SourceEmpty;
115e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck    }
116e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck    if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) {
117e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        ALOGW("Surface is protected, unable to copy from it");
118e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::SourceInvalid;
11910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
1202f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    err = sourceFence->wait(500 /* ms */);
12110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    if (err != NO_ERROR) {
12210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt");
123e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::Timeout;
12410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
1252f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
1262f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    // TODO: Can't use Image helper since it forces GL_TEXTURE_2D usage via
1272f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    // GL_OES_EGL_image, which doesn't work since we need samplerExternalOES
1282f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    // to be able to properly sample from the buffer.
1292f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
1302f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    // Create the EGLImage object that maps the GraphicBuffer
1312f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1322f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    EGLClientBuffer clientBuffer = (EGLClientBuffer) sourceBuffer->getNativeBuffer();
1332f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
1342f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
1352f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    EGLImageKHR sourceImage = eglCreateImageKHR(display, EGL_NO_CONTEXT,
1362f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck            EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
1372f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
1382f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    if (sourceImage == EGL_NO_IMAGE_KHR) {
1392f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck        ALOGW("Error creating image (%#x)", eglGetError());
140e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
1412f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    }
1422f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    GLuint sourceTexId;
1432f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    // Create a 2D texture to sample from the EGLImage
1442f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    glGenTextures(1, &sourceTexId);
1452f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    Caches::getInstance().textureState().bindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId);
1462f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, sourceImage);
1472f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
1482f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    GLenum status = GL_NO_ERROR;
1492f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    while ((status = glGetError()) != GL_NO_ERROR) {
1502f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck        ALOGW("Error creating image (%#x)", status);
151e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck        return CopyResult::UnknownError;
15210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
1532f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck
15410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    Texture sourceTexture(caches);
1552f78327cfcd4c7b23aae9bb0262e64050d093a64John Reck    sourceTexture.wrap(sourceTexId,
15610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck            sourceBuffer->getWidth(), sourceBuffer->getHeight(), 0 /* total lie */);
15710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
15810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    {
15910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        // Draw & readback
16010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        renderState.setViewport(destWidth, destHeight);
16110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        renderState.scissor().setEnabled(false);
16210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        renderState.blend().syncEnabled();
16310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        renderState.stencil().disable();
16410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
16510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        Rect destRect(destWidth, destHeight);
16610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        Glop glop;
16710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        GlopBuilder(renderState, caches, &glop)
16810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                .setRoundRectClipState(nullptr)
1692f69d6d4fdd4994912e5515016421625d1e1c4ecJohn Reck                .setMeshTexturedUnitQuad(nullptr)
1702f69d6d4fdd4994912e5515016421625d1e1c4ecJohn Reck                .setFillExternalTexture(sourceTexture, texTransform)
17110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                .setTransform(Matrix4::identity(), TransformFlags::None)
17210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                .setModelViewMapUnitToRect(destRect)
17310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                .build();
17410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        Matrix4 ortho;
17510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        ortho.loadOrtho(destWidth, destHeight);
17610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        renderState.render(glop, ortho);
17710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
17810dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck        glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
17910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck                type, bitmap->getPixels());
18010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    }
18110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
18210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    // Cleanup
18310dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    caches.textureState().deleteTexture(texture);
18410dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    renderState.deleteFramebuffer(fbo);
18510dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
18610dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck    GL_CHECKPOINT(MODERATE);
18710dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
188e94cbc76d560a157c0a0d47181b4ed2a0aadbeb1John Reck    return CopyResult::Success;
18910dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck}
19010dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck
19110dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck} // namespace uirenderer
19210dd0585c11dcedb5a271d54e645594f1d215d5cJohn Reck} // namespace android
193