From 84a2afcbfbfbbc91cbaf83d55a8ebccc987e66f1 Mon Sep 17 00:00:00 2001 From: Leon Scroggins III <scroggo@google.com> Date: Sun, 19 Jan 2020 19:27:16 -0500 Subject: [PATCH] Update NDK methods for HARDWARE Bitmaps Bug: 135133301 Test: I2c1e58c41e49c72fb4bdbc64989da103885d34bf _getInfo now sets a bit in AndroidBitmapInfo.flags to indicate whether the Bitmap has Config.HARDWARE. For a HARDWARE Bitmap, its AHardwareBuffer can now be retrieved with AndroidBitmap_getHardwareBuffer. Call AHardwareBuffer_acquire on the buffer so it will not be deleted while the client is using it. Change-Id: I9240c1928c1478053ecf7c252443a33dbd6fd6db --- core/jni/android/graphics/Bitmap.cpp | 6 +++- core/jni/android/graphics/GraphicsJNI.h | 3 +- .../android/graphics/apex/android_bitmap.cpp | 30 +++++++++++++++---- .../apex/include/android/graphics/bitmap.h | 15 ++++++++++ native/graphics/jni/bitmap.cpp | 15 ++++++++++ native/graphics/jni/libjnigraphics.map.txt | 1 + 6 files changed, 62 insertions(+), 8 deletions(-) diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 593728350037..32a7cf32bc0a 100755 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -243,7 +243,8 @@ Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) { return localBitmap.valid() ? &localBitmap->bitmap() : nullptr; } -SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes) { +SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes, + bool* isHardware) { SkASSERT(env); SkASSERT(bitmap); SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class)); @@ -252,6 +253,9 @@ SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* ou if (outRowBytes) { *outRowBytes = localBitmap->rowBytes(); } + if (isHardware) { + *isHardware = localBitmap->isHardware(); + } return localBitmap->info(); } diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index 99034edaadf7..1e497654f18d 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -62,7 +62,8 @@ public: static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas); static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap); - static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes); + static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes, + bool* isHardware); static SkRegion* getNativeRegion(JNIEnv*, jobject region); /* diff --git a/core/jni/android/graphics/apex/android_bitmap.cpp b/core/jni/android/graphics/apex/android_bitmap.cpp index b8e04a7e9a2b..01a4d9b12d8c 100644 --- a/core/jni/android/graphics/apex/android_bitmap.cpp +++ b/core/jni/android/graphics/apex/android_bitmap.cpp @@ -78,7 +78,7 @@ static SkColorType getColorType(AndroidBitmapFormat format) { } } -static uint32_t getInfoFlags(const SkImageInfo& info) { +static uint32_t getAlphaFlags(const SkImageInfo& info) { switch (info.alphaType()) { case kUnknown_SkAlphaType: LOG_ALWAYS_FATAL("Bitmap has no alpha type"); @@ -92,6 +92,14 @@ static uint32_t getInfoFlags(const SkImageInfo& info) { } } +static uint32_t getInfoFlags(const SkImageInfo& info, bool isHardware) { + uint32_t flags = getAlphaFlags(info); + if (isHardware) { + flags |= ANDROID_BITMAP_FLAGS_IS_HARDWARE; + } + return flags; +} + ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) { SkColorType dstColorType = getColorType(dstFormat); if (srcBitmapHandle && dstColorType != kUnknown_SkColorType) { @@ -108,19 +116,19 @@ ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) { return nullptr; } -static AndroidBitmapInfo getInfo(const SkImageInfo& imageInfo, uint32_t rowBytes) { +static AndroidBitmapInfo getInfo(const SkImageInfo& imageInfo, uint32_t rowBytes, bool isHardware) { AndroidBitmapInfo info; info.width = imageInfo.width(); info.height = imageInfo.height(); info.stride = rowBytes; info.format = getFormat(imageInfo); - info.flags = getInfoFlags(imageInfo); + info.flags = getInfoFlags(imageInfo, isHardware); return info; } AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) { Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle); - return getInfo(bitmap->info(), bitmap->rowBytes()); + return getInfo(bitmap->info(), bitmap->rowBytes(), bitmap->isHardware()); } namespace { @@ -219,8 +227,9 @@ ADataSpace ABitmap_getDataSpace(ABitmap* bitmapHandle) { AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) { uint32_t rowBytes = 0; - SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes); - return getInfo(imageInfo, rowBytes); + bool isHardware = false; + SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes, &isHardware); + return getInfo(imageInfo, rowBytes, isHardware); } void* ABitmap_getPixels(ABitmap* bitmapHandle) { @@ -378,3 +387,12 @@ int ABitmap_compress(const AndroidBitmapInfo* info, ADataSpace dataSpace, const return ANDROID_BITMAP_RESULT_JNI_EXCEPTION; } } + +AHardwareBuffer* ABitmap_getHardwareBuffer(ABitmap* bitmapHandle) { + Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle); + AHardwareBuffer* buffer = bitmap->hardwareBuffer(); + if (buffer) { + AHardwareBuffer_acquire(buffer); + } + return buffer; +} diff --git a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h index 683851d09d93..02ec6554f522 100644 --- a/core/jni/android/graphics/apex/include/android/graphics/bitmap.h +++ b/core/jni/android/graphics/apex/include/android/graphics/bitmap.h @@ -21,6 +21,8 @@ #include <jni.h> #include <sys/cdefs.h> +struct AHardwareBuffer; + __BEGIN_DECLS /** @@ -62,6 +64,18 @@ jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat forma int ABitmap_compress(const AndroidBitmapInfo* info, ADataSpace dataSpace, const void* pixels, AndroidBitmapCompressFormat format, int32_t quality, void* userContext, AndroidBitmap_compress_write_fn); +/** + * Retrieve the native object associated with a HARDWARE Bitmap. + * + * Client must not modify it while a Bitmap is wrapping it. + * + * @param bitmap Handle to an android.graphics.Bitmap. + * @return on success, a pointer to the + * AHardwareBuffer associated with bitmap. This acquires + * a reference on the buffer, and the client must call + * AHardwareBuffer_release when finished with it. + */ +AHardwareBuffer* ABitmap_getHardwareBuffer(ABitmap* bitmap); __END_DECLS @@ -116,6 +130,7 @@ namespace graphics { ADataSpace getDataSpace() const { return ABitmap_getDataSpace(mBitmap); } void* getPixels() const { return ABitmap_getPixels(mBitmap); } void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); } + AHardwareBuffer* getHardwareBuffer() const { return ABitmap_getHardwareBuffer(mBitmap); } private: // takes ownership of the provided ABitmap diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp index ea8a521c9d5f..4f21ccba2419 100644 --- a/native/graphics/jni/bitmap.cpp +++ b/native/graphics/jni/bitmap.cpp @@ -76,6 +76,21 @@ int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap) { return ANDROID_BITMAP_RESULT_SUCCESS; } +int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject jbitmap, AHardwareBuffer** outBuffer) { + if (NULL == env || NULL == jbitmap || NULL == outBuffer) { + return ANDROID_BITMAP_RESULT_BAD_PARAMETER; + } + + android::graphics::Bitmap bitmap(env, jbitmap); + + if (!bitmap.isValid()) { + return ANDROID_BITMAP_RESULT_JNI_EXCEPTION; + } + + *outBuffer = bitmap.getHardwareBuffer(); + return *outBuffer == NULL ? ANDROID_BITMAP_RESULT_BAD_PARAMETER : ANDROID_BITMAP_RESULT_SUCCESS; +} + int AndroidBitmap_compress(const AndroidBitmapInfo* info, int32_t dataSpace, const void* pixels, diff --git a/native/graphics/jni/libjnigraphics.map.txt b/native/graphics/jni/libjnigraphics.map.txt index 6843e7a8552f..2e6c966b9d6b 100644 --- a/native/graphics/jni/libjnigraphics.map.txt +++ b/native/graphics/jni/libjnigraphics.map.txt @@ -22,6 +22,7 @@ LIBJNIGRAPHICS { AndroidBitmap_lockPixels; AndroidBitmap_unlockPixels; AndroidBitmap_compress; # introduced=30 + AndroidBitmap_getHardwareBuffer; #introduced=30 local: *; }; -- GitLab