1c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger/* 2c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * Copyright (C) 2016 The Android Open Source Project 3c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * 4c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * Licensed under the Apache License, Version 2.0 (the "License"); 5c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * you may not use this file except in compliance with the License. 6c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * You may obtain a copy of the License at 7c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * 8c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * http://www.apache.org/licenses/LICENSE-2.0 9c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * 10c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * Unless required by applicable law or agreed to in writing, software 11c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * distributed under the License is distributed on an "AS IS" BASIS, 12c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * See the License for the specific language governing permissions and 14c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger * limitations under the License. 15c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger */ 16c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 17c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include "SkiaOpenGLReadback.h" 18c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 19c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include "Matrix.h" 20c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include "Properties.h" 21c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include <SkCanvas.h> 22c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include <SkSurface.h> 23c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include <gl/GrGLInterface.h> 24c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include <gl/GrGLTypes.h> 25c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include <GLES2/gl2.h> 26c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger#include <GLES2/gl2ext.h> 27c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 28c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergerusing namespace android::uirenderer::renderthread; 29c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 30c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergernamespace android { 31c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergernamespace uirenderer { 32c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenbergernamespace skiapipeline { 33c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 34c4fbada76aa840105553b2c2bce2204e673d2983Derek SollenbergerCopyResult SkiaOpenGLReadback::copyImageInto(EGLImageKHR eglImage, const Matrix4& imgTransform, 35c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger int imgWidth, int imgHeight, const Rect& srcRect, SkBitmap* bitmap) { 36c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 37c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger GLuint sourceTexId; 38c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger glGenTextures(1, &sourceTexId); 39c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger glBindTexture(GL_TEXTURE_EXTERNAL_OES, sourceTexId); 40c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, eglImage); 41c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 42c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext()); 43c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { 44c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface()); 45c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger LOG_ALWAYS_FATAL_IF(!glInterface.get()); 46c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger grContext.reset(GrContext::Create(GrBackend::kOpenGL_GrBackend, 47c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger (GrBackendContext)glInterface.get())); 48c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger } else { 49c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger grContext->resetContext(); 50c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger } 51c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 52c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger GrGLTextureInfo externalTexture; 53c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger externalTexture.fTarget = GL_TEXTURE_EXTERNAL_OES; 54c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger externalTexture.fID = sourceTexId; 55c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 56c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger GrBackendTextureDesc textureDescription; 57c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger textureDescription.fWidth = imgWidth; 58c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger textureDescription.fHeight = imgHeight; 59c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger textureDescription.fConfig = kRGBA_8888_GrPixelConfig; 60c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger textureDescription.fOrigin = kTopLeft_GrSurfaceOrigin; 61c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger textureDescription.fTextureHandle = reinterpret_cast<GrBackendObject>(&externalTexture); 62c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 63c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger CopyResult copyResult = CopyResult::UnknownError; 64c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger sk_sp<SkImage> image(SkImage::MakeFromAdoptedTexture(grContext.get(), textureDescription)); 65c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger if (image) { 66c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger SkAutoLockPixels alp(*bitmap); 67c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 68c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // convert to Skia data structures 69c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger const SkRect bufferRect = SkRect::MakeIWH(imgWidth, imgHeight); 70c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger SkRect skiaSrcRect = srcRect.toSkRect(); 71c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger SkMatrix textureMatrix; 72c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger imgTransform.copyTo(textureMatrix); 73c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 74c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // remove the y-flip applied to the matrix so that we can scale the srcRect. 75c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // This flip is not needed as we specify the origin of the texture when we 76c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // wrap it as an SkImage. 77c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger SkMatrix yFlip = SkMatrix::MakeScale(1, -1); 78c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger yFlip.postTranslate(0,1); 79c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger textureMatrix.preConcat(yFlip); 80c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 81c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // copy the entire src if the rect is empty 82c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger if (skiaSrcRect.isEmpty()) { 83c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger skiaSrcRect = bufferRect; 84c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger } 85c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 86c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // since the y-flip has been removed we can simply scale & translate 87c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // the source rectangle 88c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger textureMatrix.mapRect(&skiaSrcRect); 89c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 90c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger if (skiaSrcRect.intersect(bufferRect)) { 91c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger SkPoint srcOrigin = SkPoint::Make(skiaSrcRect.fLeft, skiaSrcRect.fTop); 92c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 93c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // if we need to scale the result we must render to an offscreen buffer 94c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger if (bitmap->width() != skiaSrcRect.width() 95c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger || bitmap->height() != skiaSrcRect.height()) { 96c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger sk_sp<SkSurface> scaledSurface = SkSurface::MakeRenderTarget( 97c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger grContext.get(), SkBudgeted::kYes, bitmap->info()); 98c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger SkPaint paint; 99c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger paint.setBlendMode(SkBlendMode::kSrc); 100c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger scaledSurface->getCanvas()->drawImageRect(image, skiaSrcRect, 101c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger SkRect::MakeWH(bitmap->width(), bitmap->height()), &paint); 102c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger image = scaledSurface->makeImageSnapshot(); 103c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger srcOrigin.set(0,0); 104c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger } 105c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 106c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger if (image->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 107c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger srcOrigin.fX, srcOrigin.fY)) { 108c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger copyResult = CopyResult::Success; 109c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger } 110c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger } 111c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger } 112c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 113c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // make sure that we have deleted the texture (in the SkImage) before we 114c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger // destroy the EGLImage that it was created from 115c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger image.reset(); 116c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger return copyResult; 117c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger} 118c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger 119c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger} /* namespace skiapipeline */ 120c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger} /* namespace uirenderer */ 121c4fbada76aa840105553b2c2bce2204e673d2983Derek Sollenberger} /* namespace android */ 122