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