1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "Readback.h" 18 19 #include "pipeline/skia/LayerDrawable.h" 20 #include "renderthread/EglManager.h" 21 #include "renderthread/VulkanManager.h" 22 23 #include <gui/Surface.h> 24 #include <ui/Fence.h> 25 #include <ui/GraphicBuffer.h> 26 #include "DeferredLayerUpdater.h" 27 #include "Properties.h" 28 #include "hwui/Bitmap.h" 29 #include "utils/Color.h" 30 #include "utils/MathUtils.h" 31 #include "utils/TraceUtils.h" 32 33 using namespace android::uirenderer::renderthread; 34 35 namespace android { 36 namespace uirenderer { 37 38 CopyResult Readback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) { 39 ATRACE_CALL(); 40 // Setup the source 41 sp<GraphicBuffer> sourceBuffer; 42 sp<Fence> sourceFence; 43 Matrix4 texTransform; 44 status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data); 45 texTransform.invalidateType(); 46 if (err != NO_ERROR) { 47 ALOGW("Failed to get last queued buffer, error = %d", err); 48 return CopyResult::UnknownError; 49 } 50 if (!sourceBuffer.get()) { 51 ALOGW("Surface doesn't have any previously queued frames, nothing to readback from"); 52 return CopyResult::SourceEmpty; 53 } 54 if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) { 55 ALOGW("Surface is protected, unable to copy from it"); 56 return CopyResult::SourceInvalid; 57 } 58 err = sourceFence->wait(500 /* ms */); 59 if (err != NO_ERROR) { 60 ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt"); 61 return CopyResult::Timeout; 62 } 63 if (!sourceBuffer.get()) { 64 return CopyResult::UnknownError; 65 } 66 67 sk_sp<SkColorSpace> colorSpace = 68 DataSpaceToColorSpace(static_cast<android_dataspace>(surface.getBuffersDataSpace())); 69 sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer( 70 reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()), 71 kPremul_SkAlphaType, colorSpace); 72 return copyImageInto(image, texTransform, srcRect, bitmap); 73 } 74 75 CopyResult Readback::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) { 76 LOG_ALWAYS_FATAL_IF(!hwBitmap->isHardware()); 77 78 Rect srcRect; 79 Matrix4 transform; 80 transform.loadScale(1, -1, 1); 81 transform.translate(0, -1); 82 83 return copyImageInto(hwBitmap->makeImage(), transform, srcRect, bitmap); 84 } 85 86 CopyResult Readback::copyLayerInto(DeferredLayerUpdater* deferredLayer, SkBitmap* bitmap) { 87 ATRACE_CALL(); 88 if (!mRenderThread.getGrContext()) { 89 return CopyResult::UnknownError; 90 } 91 92 // acquire most recent buffer for drawing 93 deferredLayer->updateTexImage(); 94 deferredLayer->apply(); 95 const SkRect dstRect = SkRect::MakeIWH(bitmap->width(), bitmap->height()); 96 CopyResult copyResult = CopyResult::UnknownError; 97 Layer* layer = deferredLayer->backingLayer(); 98 if (layer) { 99 if (copyLayerInto(layer, nullptr, &dstRect, bitmap)) { 100 copyResult = CopyResult::Success; 101 } 102 } 103 return copyResult; 104 } 105 106 CopyResult Readback::copyImageInto(const sk_sp<SkImage>& image, Matrix4& texTransform, 107 const Rect& srcRect, SkBitmap* bitmap) { 108 ATRACE_CALL(); 109 if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaGL) { 110 mRenderThread.requireGlContext(); 111 } else { 112 mRenderThread.requireVkContext(); 113 } 114 if (!image.get()) { 115 return CopyResult::UnknownError; 116 } 117 int imgWidth = image->width(); 118 int imgHeight = image->height(); 119 sk_sp<GrContext> grContext = sk_ref_sp(mRenderThread.getGrContext()); 120 121 if (bitmap->colorType() == kRGBA_F16_SkColorType && 122 !grContext->colorTypeSupportedAsSurface(bitmap->colorType())) { 123 ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported"); 124 return CopyResult::DestinationInvalid; 125 } 126 127 CopyResult copyResult = CopyResult::UnknownError; 128 129 int displayedWidth = imgWidth, displayedHeight = imgHeight; 130 // If this is a 90 or 270 degree rotation we need to swap width/height to get the device 131 // size. 132 if (texTransform[Matrix4::kSkewX] >= 0.5f || texTransform[Matrix4::kSkewX] <= -0.5f) { 133 std::swap(displayedWidth, displayedHeight); 134 } 135 SkRect skiaDestRect = SkRect::MakeWH(bitmap->width(), bitmap->height()); 136 SkRect skiaSrcRect = srcRect.toSkRect(); 137 if (skiaSrcRect.isEmpty()) { 138 skiaSrcRect = SkRect::MakeIWH(displayedWidth, displayedHeight); 139 } 140 bool srcNotEmpty = skiaSrcRect.intersect(SkRect::MakeIWH(displayedWidth, displayedHeight)); 141 if (!srcNotEmpty) { 142 return copyResult; 143 } 144 145 Layer layer(mRenderThread.renderState(), nullptr, 255, SkBlendMode::kSrc); 146 bool disableFilter = MathUtils::areEqual(skiaSrcRect.width(), skiaDestRect.width()) && 147 MathUtils::areEqual(skiaSrcRect.height(), skiaDestRect.height()); 148 layer.setForceFilter(!disableFilter); 149 layer.setSize(displayedWidth, displayedHeight); 150 texTransform.copyTo(layer.getTexTransform()); 151 layer.setImage(image); 152 if (copyLayerInto(&layer, &skiaSrcRect, &skiaDestRect, bitmap)) { 153 copyResult = CopyResult::Success; 154 } 155 156 return copyResult; 157 } 158 159 bool Readback::copyLayerInto(Layer* layer, const SkRect* srcRect, const SkRect* dstRect, 160 SkBitmap* bitmap) { 161 /* This intermediate surface is present to work around a bug in SwiftShader that 162 * prevents us from reading the contents of the layer's texture directly. The 163 * workaround involves first rendering that texture into an intermediate buffer and 164 * then reading from the intermediate buffer into the bitmap. 165 * Another reason to render in an offscreen buffer is to scale and to avoid an issue b/62262733 166 * with reading incorrect data from EGLImage backed SkImage (likely a driver bug). 167 */ 168 sk_sp<SkSurface> tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), 169 SkBudgeted::kYes, bitmap->info(), 0, 170 kTopLeft_GrSurfaceOrigin, nullptr); 171 172 // if we can't generate a GPU surface that matches the destination bitmap (e.g. 565) then we 173 // attempt to do the intermediate rendering step in 8888 174 if (!tmpSurface.get()) { 175 SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType); 176 tmpSurface = SkSurface::MakeRenderTarget(mRenderThread.getGrContext(), SkBudgeted::kYes, 177 tmpInfo, 0, kTopLeft_GrSurfaceOrigin, nullptr); 178 if (!tmpSurface.get()) { 179 ALOGW("Unable to generate GPU buffer in a format compatible with the provided bitmap"); 180 return false; 181 } 182 } 183 184 if (!skiapipeline::LayerDrawable::DrawLayer(mRenderThread.getGrContext(), 185 tmpSurface->getCanvas(), layer, srcRect, dstRect, 186 false)) { 187 ALOGW("Unable to draw content from GPU into the provided bitmap"); 188 return false; 189 } 190 191 if (!tmpSurface->readPixels(*bitmap, 0, 0)) { 192 // if we fail to readback from the GPU directly (e.g. 565) then we attempt to read into 193 // 8888 and then convert that into the destination format before giving up. 194 SkBitmap tmpBitmap; 195 SkImageInfo tmpInfo = bitmap->info().makeColorType(SkColorType::kN32_SkColorType); 196 if (bitmap->info().colorType() == SkColorType::kN32_SkColorType || 197 !tmpBitmap.tryAllocPixels(tmpInfo) || 198 !tmpSurface->readPixels(tmpBitmap, 0, 0) || 199 !tmpBitmap.readPixels(bitmap->info(), bitmap->getPixels(), 200 bitmap->rowBytes(), 0, 0)) { 201 ALOGW("Unable to convert content into the provided bitmap"); 202 return false; 203 } 204 } 205 206 bitmap->notifyPixelsChanged(); 207 return true; 208 } 209 210 } /* namespace uirenderer */ 211 } /* namespace android */ 212