Loading core/jni/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -234,6 +234,7 @@ cc_library_shared { "libui", "libgraphicsenv", "libgui", "libmediandk", "libsensor", "libinput", "libcamera_client", Loading Loading @@ -449,9 +450,10 @@ cc_library_static { ], shared_libs: [ "libandroidfw", "libEGL", "libmediandk", "libnativedisplay", "libnativewindow", "libgui", "libpdfium", ], static_libs: [ Loading core/jni/android_view_ThreadedRenderer.cpp +43 −33 Original line number Diff line number Diff line Loading @@ -23,10 +23,9 @@ #include <Properties.h> #include <RootRenderNode.h> #include <dlfcn.h> #include <gui/BufferItemConsumer.h> #include <gui/BufferQueue.h> #include <gui/Surface.h> #include <inttypes.h> #include <media/NdkImage.h> #include <media/NdkImageReader.h> #include <nativehelper/JNIHelp.h> #include <pipeline/skia/ShaderCache.h> #include <private/EGL/cache.h> Loading @@ -34,7 +33,6 @@ #include <renderthread/RenderProxy.h> #include <renderthread/RenderTask.h> #include <renderthread/RenderThread.h> #include <system/window.h> #include <utils/Color.h> #include <utils/RefBase.h> #include <utils/StrongPointer.h> Loading Loading @@ -481,24 +479,35 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode( uint32_t width = jwidth; uint32_t height = jheight; // TODO: should this be generated from an AImageReader? // Create a Surface wired up to a BufferItemConsumer sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> rawConsumer; BufferQueue::createBufferQueue(&producer, &rawConsumer); // We only need 1 buffer but some drivers have bugs so workaround it by setting max count to 2 rawConsumer->setMaxBufferCount(2); sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer, GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER); consumer->setDefaultBufferSize(width, height); sp<Surface> surface = new Surface(producer); // Create an ImageReader wired up to a BufferItemConsumer AImageReader* rawReader; media_status_t result = AImageReader_newWithUsage(width, height, AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE, 2, &rawReader); std::unique_ptr<AImageReader, decltype(&AImageReader_delete)> reader(rawReader, AImageReader_delete); if (result != AMEDIA_OK) { ALOGW("Error creating image reader!"); return nullptr; } // Note that ownership of this window is maintained by AImageReader, so we // shouldn't need to wrap around a smart pointer. ANativeWindow* window; result = AImageReader_getWindow(rawReader, &window); if (result != AMEDIA_OK) { ALOGW("Error retrieving the native window!"); return nullptr; } // Render into the surface { ContextFactory factory; RenderProxy proxy{true, renderNode, &factory}; proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer); proxy.setSurface(surface.get()); proxy.setSurface(window); // Shadows can't be used via this interface, so just set the light source // to all 0s. proxy.setLightAlpha(0, 0); Loading @@ -510,33 +519,34 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode( proxy.syncAndDrawFrame(); } // Yank out the GraphicBuffer BufferItem bufferItem; status_t err; if ((err = consumer->acquireBuffer(&bufferItem, 0, true)) != OK) { ALOGW("Failed to acquireBuffer, error %d (%s)", err, strerror(-err)); return nullptr; } sp<GraphicBuffer> buffer = bufferItem.mGraphicBuffer; // We don't really care if this fails or not since we're just going to destroy this anyway consumer->releaseBuffer(bufferItem); if (!buffer.get()) { ALOGW("GraphicBuffer is null?"); AImage* rawImage; result = AImageReader_acquireNextImage(rawReader, &rawImage); std::unique_ptr<AImage, decltype(&AImage_delete)> image(rawImage, AImage_delete); if (result != AMEDIA_OK) { ALOGW("Error reading image: %d!", result); return nullptr; } if (buffer->getWidth() != width || buffer->getHeight() != height) { ALOGW("GraphicBuffer size mismatch, got %dx%d expected %dx%d", buffer->getWidth(), buffer->getHeight(), width, height); AHardwareBuffer* buffer; result = AImage_getHardwareBuffer(rawImage, &buffer); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); if (desc.width != width || desc.height != height) { ALOGW("AHardwareBuffer size mismatch, got %dx%d expected %dx%d", desc.width, desc.height, width, height); // Continue I guess? } sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace(bufferItem.mDataSpace); sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace( static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window))); if (cs == nullptr) { // nullptr is treated as SRGB in Skia, thus explicitly use SRGB in order to make sure // the returned bitmap has a color space. cs = SkColorSpace::MakeSRGB(); } sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer->toAHardwareBuffer(), cs); sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, cs); return bitmap::createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_Premultiplied); } Loading Loading
core/jni/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -234,6 +234,7 @@ cc_library_shared { "libui", "libgraphicsenv", "libgui", "libmediandk", "libsensor", "libinput", "libcamera_client", Loading Loading @@ -449,9 +450,10 @@ cc_library_static { ], shared_libs: [ "libandroidfw", "libEGL", "libmediandk", "libnativedisplay", "libnativewindow", "libgui", "libpdfium", ], static_libs: [ Loading
core/jni/android_view_ThreadedRenderer.cpp +43 −33 Original line number Diff line number Diff line Loading @@ -23,10 +23,9 @@ #include <Properties.h> #include <RootRenderNode.h> #include <dlfcn.h> #include <gui/BufferItemConsumer.h> #include <gui/BufferQueue.h> #include <gui/Surface.h> #include <inttypes.h> #include <media/NdkImage.h> #include <media/NdkImageReader.h> #include <nativehelper/JNIHelp.h> #include <pipeline/skia/ShaderCache.h> #include <private/EGL/cache.h> Loading @@ -34,7 +33,6 @@ #include <renderthread/RenderProxy.h> #include <renderthread/RenderTask.h> #include <renderthread/RenderThread.h> #include <system/window.h> #include <utils/Color.h> #include <utils/RefBase.h> #include <utils/StrongPointer.h> Loading Loading @@ -481,24 +479,35 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode( uint32_t width = jwidth; uint32_t height = jheight; // TODO: should this be generated from an AImageReader? // Create a Surface wired up to a BufferItemConsumer sp<IGraphicBufferProducer> producer; sp<IGraphicBufferConsumer> rawConsumer; BufferQueue::createBufferQueue(&producer, &rawConsumer); // We only need 1 buffer but some drivers have bugs so workaround it by setting max count to 2 rawConsumer->setMaxBufferCount(2); sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer, GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER); consumer->setDefaultBufferSize(width, height); sp<Surface> surface = new Surface(producer); // Create an ImageReader wired up to a BufferItemConsumer AImageReader* rawReader; media_status_t result = AImageReader_newWithUsage(width, height, AIMAGE_FORMAT_RGBA_8888, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE, 2, &rawReader); std::unique_ptr<AImageReader, decltype(&AImageReader_delete)> reader(rawReader, AImageReader_delete); if (result != AMEDIA_OK) { ALOGW("Error creating image reader!"); return nullptr; } // Note that ownership of this window is maintained by AImageReader, so we // shouldn't need to wrap around a smart pointer. ANativeWindow* window; result = AImageReader_getWindow(rawReader, &window); if (result != AMEDIA_OK) { ALOGW("Error retrieving the native window!"); return nullptr; } // Render into the surface { ContextFactory factory; RenderProxy proxy{true, renderNode, &factory}; proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer); proxy.setSurface(surface.get()); proxy.setSurface(window); // Shadows can't be used via this interface, so just set the light source // to all 0s. proxy.setLightAlpha(0, 0); Loading @@ -510,33 +519,34 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode( proxy.syncAndDrawFrame(); } // Yank out the GraphicBuffer BufferItem bufferItem; status_t err; if ((err = consumer->acquireBuffer(&bufferItem, 0, true)) != OK) { ALOGW("Failed to acquireBuffer, error %d (%s)", err, strerror(-err)); return nullptr; } sp<GraphicBuffer> buffer = bufferItem.mGraphicBuffer; // We don't really care if this fails or not since we're just going to destroy this anyway consumer->releaseBuffer(bufferItem); if (!buffer.get()) { ALOGW("GraphicBuffer is null?"); AImage* rawImage; result = AImageReader_acquireNextImage(rawReader, &rawImage); std::unique_ptr<AImage, decltype(&AImage_delete)> image(rawImage, AImage_delete); if (result != AMEDIA_OK) { ALOGW("Error reading image: %d!", result); return nullptr; } if (buffer->getWidth() != width || buffer->getHeight() != height) { ALOGW("GraphicBuffer size mismatch, got %dx%d expected %dx%d", buffer->getWidth(), buffer->getHeight(), width, height); AHardwareBuffer* buffer; result = AImage_getHardwareBuffer(rawImage, &buffer); AHardwareBuffer_Desc desc; AHardwareBuffer_describe(buffer, &desc); if (desc.width != width || desc.height != height) { ALOGW("AHardwareBuffer size mismatch, got %dx%d expected %dx%d", desc.width, desc.height, width, height); // Continue I guess? } sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace(bufferItem.mDataSpace); sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace( static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(window))); if (cs == nullptr) { // nullptr is treated as SRGB in Skia, thus explicitly use SRGB in order to make sure // the returned bitmap has a color space. cs = SkColorSpace::MakeSRGB(); } sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer->toAHardwareBuffer(), cs); sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, cs); return bitmap::createBitmap(env, bitmap.release(), android::bitmap::kBitmapCreateFlag_Premultiplied); } Loading