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