Loading libs/hwui/Readback.cpp +25 −22 Original line number Diff line number Diff line Loading @@ -16,16 +16,16 @@ #include "Readback.h" #include "pipeline/skia/LayerDrawable.h" #include "renderthread/EglManager.h" #include "renderthread/VulkanManager.h" #include <gui/Surface.h> #include <ui/Fence.h> #include <sync/sync.h> #include <system/window.h> #include <ui/GraphicBuffer.h> #include "DeferredLayerUpdater.h" #include "Properties.h" #include "hwui/Bitmap.h" #include "pipeline/skia/LayerDrawable.h" #include "renderthread/EglManager.h" #include "renderthread/VulkanManager.h" #include "utils/Color.h" #include "utils/MathUtils.h" #include "utils/TraceUtils.h" Loading @@ -35,40 +35,43 @@ using namespace android::uirenderer::renderthread; namespace android { namespace uirenderer { CopyResult Readback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) { CopyResult Readback::copySurfaceInto(ANativeWindow* window, const Rect& srcRect, SkBitmap* bitmap) { ATRACE_CALL(); // Setup the source sp<GraphicBuffer> sourceBuffer; sp<Fence> sourceFence; AHardwareBuffer* rawSourceBuffer; int rawSourceFence; Matrix4 texTransform; status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data); status_t err = ANativeWindow_getLastQueuedBuffer(window, &rawSourceBuffer, &rawSourceFence, texTransform.data); base::unique_fd sourceFence(rawSourceFence); texTransform.invalidateType(); if (err != NO_ERROR) { ALOGW("Failed to get last queued buffer, error = %d", err); return CopyResult::UnknownError; } if (!sourceBuffer.get()) { if (rawSourceBuffer == nullptr) { ALOGW("Surface doesn't have any previously queued frames, nothing to readback from"); return CopyResult::SourceEmpty; } if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) { std::unique_ptr<AHardwareBuffer, decltype(&AHardwareBuffer_release)> sourceBuffer( rawSourceBuffer, AHardwareBuffer_release); AHardwareBuffer_Desc description; AHardwareBuffer_describe(sourceBuffer.get(), &description); if (description.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) { ALOGW("Surface is protected, unable to copy from it"); return CopyResult::SourceInvalid; } err = sourceFence->wait(500 /* ms */); if (err != NO_ERROR) { if (sourceFence != -1 && sync_wait(sourceFence.get(), 500 /* ms */) != NO_ERROR) { ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt"); return CopyResult::Timeout; } if (!sourceBuffer.get()) { return CopyResult::UnknownError; } sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace(static_cast<android_dataspace>(surface.getBuffersDataSpace())); sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer( reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()), kPremul_SkAlphaType, colorSpace); sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace( static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window))); sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, colorSpace); return copyImageInto(image, texTransform, srcRect, bitmap); } Loading libs/hwui/Readback.h +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ public: /** * Copies the surface's most recently queued buffer into the provided bitmap. */ CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap); CopyResult copySurfaceInto(ANativeWindow* window, const Rect& srcRect, SkBitmap* bitmap); CopyResult copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap); Loading libs/hwui/renderthread/RenderProxy.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -317,8 +317,9 @@ void RenderProxy::setRenderAheadDepth(int renderAhead) { int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom, SkBitmap* bitmap) { auto& thread = RenderThread::getInstance(); ANativeWindow* window = surface.get(); return static_cast<int>(thread.queue().runSync([&]() -> auto { return thread.readback().copySurfaceInto(*surface, Rect(left, top, right, bottom), bitmap); return thread.readback().copySurfaceInto(window, Rect(left, top, right, bottom), bitmap); })); } Loading libs/hwui/renderthread/RenderProxy.h +4 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,10 @@ public: */ ANDROID_API void setRenderAheadDepth(int renderAhead); // TODO: This api will need to take in an ANativeWindow instead, but the // caller, ThreadedRenderer, doesn't have access to libandroid due to a // circular dependency, so it can't use the JNI ANativeWindow methods. Once // that is resolved then replace the surface type here. ANDROID_API static int copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom, SkBitmap* bitmap); ANDROID_API static void prepareToDraw(Bitmap& bitmap); Loading Loading
libs/hwui/Readback.cpp +25 −22 Original line number Diff line number Diff line Loading @@ -16,16 +16,16 @@ #include "Readback.h" #include "pipeline/skia/LayerDrawable.h" #include "renderthread/EglManager.h" #include "renderthread/VulkanManager.h" #include <gui/Surface.h> #include <ui/Fence.h> #include <sync/sync.h> #include <system/window.h> #include <ui/GraphicBuffer.h> #include "DeferredLayerUpdater.h" #include "Properties.h" #include "hwui/Bitmap.h" #include "pipeline/skia/LayerDrawable.h" #include "renderthread/EglManager.h" #include "renderthread/VulkanManager.h" #include "utils/Color.h" #include "utils/MathUtils.h" #include "utils/TraceUtils.h" Loading @@ -35,40 +35,43 @@ using namespace android::uirenderer::renderthread; namespace android { namespace uirenderer { CopyResult Readback::copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap) { CopyResult Readback::copySurfaceInto(ANativeWindow* window, const Rect& srcRect, SkBitmap* bitmap) { ATRACE_CALL(); // Setup the source sp<GraphicBuffer> sourceBuffer; sp<Fence> sourceFence; AHardwareBuffer* rawSourceBuffer; int rawSourceFence; Matrix4 texTransform; status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, texTransform.data); status_t err = ANativeWindow_getLastQueuedBuffer(window, &rawSourceBuffer, &rawSourceFence, texTransform.data); base::unique_fd sourceFence(rawSourceFence); texTransform.invalidateType(); if (err != NO_ERROR) { ALOGW("Failed to get last queued buffer, error = %d", err); return CopyResult::UnknownError; } if (!sourceBuffer.get()) { if (rawSourceBuffer == nullptr) { ALOGW("Surface doesn't have any previously queued frames, nothing to readback from"); return CopyResult::SourceEmpty; } if (sourceBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) { std::unique_ptr<AHardwareBuffer, decltype(&AHardwareBuffer_release)> sourceBuffer( rawSourceBuffer, AHardwareBuffer_release); AHardwareBuffer_Desc description; AHardwareBuffer_describe(sourceBuffer.get(), &description); if (description.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) { ALOGW("Surface is protected, unable to copy from it"); return CopyResult::SourceInvalid; } err = sourceFence->wait(500 /* ms */); if (err != NO_ERROR) { if (sourceFence != -1 && sync_wait(sourceFence.get(), 500 /* ms */) != NO_ERROR) { ALOGE("Timeout (500ms) exceeded waiting for buffer fence, abandoning readback attempt"); return CopyResult::Timeout; } if (!sourceBuffer.get()) { return CopyResult::UnknownError; } sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace(static_cast<android_dataspace>(surface.getBuffersDataSpace())); sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer( reinterpret_cast<AHardwareBuffer*>(sourceBuffer.get()), kPremul_SkAlphaType, colorSpace); sk_sp<SkColorSpace> colorSpace = DataSpaceToColorSpace( static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window))); sk_sp<SkImage> image = SkImage::MakeFromAHardwareBuffer(sourceBuffer.get(), kPremul_SkAlphaType, colorSpace); return copyImageInto(image, texTransform, srcRect, bitmap); } Loading
libs/hwui/Readback.h +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ public: /** * Copies the surface's most recently queued buffer into the provided bitmap. */ CopyResult copySurfaceInto(Surface& surface, const Rect& srcRect, SkBitmap* bitmap); CopyResult copySurfaceInto(ANativeWindow* window, const Rect& srcRect, SkBitmap* bitmap); CopyResult copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap); Loading
libs/hwui/renderthread/RenderProxy.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -317,8 +317,9 @@ void RenderProxy::setRenderAheadDepth(int renderAhead) { int RenderProxy::copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom, SkBitmap* bitmap) { auto& thread = RenderThread::getInstance(); ANativeWindow* window = surface.get(); return static_cast<int>(thread.queue().runSync([&]() -> auto { return thread.readback().copySurfaceInto(*surface, Rect(left, top, right, bottom), bitmap); return thread.readback().copySurfaceInto(window, Rect(left, top, right, bottom), bitmap); })); } Loading
libs/hwui/renderthread/RenderProxy.h +4 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,10 @@ public: */ ANDROID_API void setRenderAheadDepth(int renderAhead); // TODO: This api will need to take in an ANativeWindow instead, but the // caller, ThreadedRenderer, doesn't have access to libandroid due to a // circular dependency, so it can't use the JNI ANativeWindow methods. Once // that is resolved then replace the surface type here. ANDROID_API static int copySurfaceInto(sp<Surface>& surface, int left, int top, int right, int bottom, SkBitmap* bitmap); ANDROID_API static void prepareToDraw(Bitmap& bitmap); Loading