Consolidate NDK and APEX implementations

the NDK APIs are implemented in terms of the APEX APIs to
reduce the number of different implementations serving the
same fundamental purpose.

Bug: 137655431
Test: CtsGraphicsTestCases
Change-Id: Idc7b85403a7e546843b9c1d822acc0a1e740059a
This commit is contained in:
Derek Sollenberger
2019-11-08 08:50:58 -05:00
parent 17c36347cc
commit 6c41ab13d0
7 changed files with 106 additions and 120 deletions

View File

@@ -223,97 +223,11 @@ void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap) {
bitmap->getSkBitmap(outBitmap);
}
Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
LocalScopedBitmap localBitmap(bitmapHandle);
return localBitmap->bitmap();
}
Bitmap& toBitmap(jlong bitmapHandle) {
LocalScopedBitmap localBitmap(bitmapHandle);
return localBitmap->bitmap();
}
void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
LocalScopedBitmap localBitmap(bitmapHandle);
const SkImageInfo& imageInfo = localBitmap->info();
info->width = imageInfo.width();
info->height = imageInfo.height();
info->stride = localBitmap->rowBytes();
info->flags = 0;
switch (imageInfo.colorType()) {
case kN32_SkColorType:
info->format = ANDROID_BITMAP_FORMAT_RGBA_8888;
break;
case kRGB_565_SkColorType:
info->format = ANDROID_BITMAP_FORMAT_RGB_565;
break;
case kARGB_4444_SkColorType:
info->format = ANDROID_BITMAP_FORMAT_RGBA_4444;
break;
case kAlpha_8_SkColorType:
info->format = ANDROID_BITMAP_FORMAT_A_8;
break;
case kRGBA_F16_SkColorType:
info->format = ANDROID_BITMAP_FORMAT_RGBA_F16;
break;
default:
info->format = ANDROID_BITMAP_FORMAT_NONE;
break;
}
switch (imageInfo.alphaType()) {
case kUnknown_SkAlphaType:
LOG_ALWAYS_FATAL("Bitmap has no alpha type");
break;
case kOpaque_SkAlphaType:
info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
break;
case kPremul_SkAlphaType:
info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
break;
case kUnpremul_SkAlphaType:
info->flags |= ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
break;
}
}
void* lockPixels(JNIEnv* env, jobject bitmap) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
LocalScopedBitmap localBitmap(bitmapHandle);
if (!localBitmap->valid()) return nullptr;
SkPixelRef& pixelRef = localBitmap->bitmap();
if (!pixelRef.pixels()) {
return nullptr;
}
pixelRef.ref();
return pixelRef.pixels();
}
bool unlockPixels(JNIEnv* env, jobject bitmap) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
LocalScopedBitmap localBitmap(bitmapHandle);
if (!localBitmap->valid()) return false;
SkPixelRef& pixelRef = localBitmap->bitmap();
pixelRef.notifyPixelsChanged();
pixelRef.unref();
return true;
}
} // namespace bitmap
} // namespace android
@@ -321,6 +235,27 @@ bool unlockPixels(JNIEnv* env, jobject bitmap) {
using namespace android;
using namespace android::bitmap;
Bitmap* GraphicsJNI::getNativeBitmap(JNIEnv* env, jobject bitmap) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
LocalScopedBitmap localBitmap(bitmapHandle);
return localBitmap.valid() ? &localBitmap->bitmap() : nullptr;
}
SkImageInfo GraphicsJNI::getBitmapInfo(JNIEnv* env, jobject bitmap, uint32_t* outRowBytes) {
SkASSERT(env);
SkASSERT(bitmap);
SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
LocalScopedBitmap localBitmap(bitmapHandle);
if (outRowBytes) {
*outRowBytes = localBitmap->rowBytes();
}
return localBitmap->info();
}
bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
int x, int y, int width, int height, SkBitmap* dstBitmap) {
const jint* array = env->GetIntArrayElements(srcColors, NULL);

View File

@@ -38,17 +38,8 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
int bitmapCreateFlags, jbyteArray ninePatchChunk = nullptr,
jobject ninePatchInsets = nullptr, int density = -1);
Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
Bitmap& toBitmap(jlong bitmapHandle);
// NDK access
void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info);
// Returns a pointer to the pixels or nullptr if the bitmap is not valid
void* lockPixels(JNIEnv* env, jobject bitmap);
// Returns true if unlocked, false if the bitmap is no longer valid (destroyed)
bool unlockPixels(JNIEnv* env, jobject bitmap);
/** Reinitialize a bitmap. bitmap must already have its SkAlphaType set in
sync with isPremultiplied
*/

View File

@@ -342,10 +342,6 @@ SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
return static_cast<SkColorType>(gConfig2ColorType[legacyConfig]);
}
void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
}
AndroidBitmapFormat GraphicsJNI::getFormatFromConfig(JNIEnv* env, jobject jconfig) {
ALOG_ASSERT(env);
if (NULL == jconfig) {

View File

@@ -61,7 +61,8 @@ public:
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
static android::Bitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
static SkImageInfo getBitmapInfo(JNIEnv*, jobject bitmap, uint32_t* outRowBytes);
static SkRegion* getNativeRegion(JNIEnv*, jobject region);
/*

View File

@@ -14,19 +14,25 @@
* limitations under the License.
*/
#define LOG_TAG "Bitmap"
#include <log/log.h>
#include "android/graphics/bitmap.h"
#include "Bitmap.h"
#include "TypeCast.h"
#include "GraphicsJNI.h"
#include <GraphicsJNI.h>
#include <hwui/Bitmap.h>
using namespace android;
ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj) {
Bitmap& bitmap = android::bitmap::toBitmap(env, bitmapObj);
bitmap.ref();
return TypeCast::toABitmap(&bitmap);
Bitmap* bitmap = GraphicsJNI::getNativeBitmap(env, bitmapObj);
if (bitmap) {
bitmap->ref();
return TypeCast::toABitmap(bitmap);
}
return nullptr;
}
void ABitmap_acquireRef(ABitmap* bitmap) {
@@ -37,8 +43,8 @@ void ABitmap_releaseRef(ABitmap* bitmap) {
SkSafeUnref(TypeCast::toBitmap(bitmap));
}
static AndroidBitmapFormat getFormat(Bitmap* bitmap) {
switch (bitmap->colorType()) {
static AndroidBitmapFormat getFormat(const SkImageInfo& info) {
switch (info.colorType()) {
case kN32_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_8888;
case kRGB_565_SkColorType:
@@ -71,6 +77,20 @@ static SkColorType getColorType(AndroidBitmapFormat format) {
}
}
static uint32_t getInfoFlags(const SkImageInfo& info) {
switch (info.alphaType()) {
case kUnknown_SkAlphaType:
LOG_ALWAYS_FATAL("Bitmap has no alpha type");
break;
case kOpaque_SkAlphaType:
return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
case kPremul_SkAlphaType:
return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
case kUnpremul_SkAlphaType:
return ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL;
}
}
ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) {
SkColorType dstColorType = getColorType(dstFormat);
if (srcBitmapHandle && dstColorType != kUnknown_SkColorType) {
@@ -87,15 +107,25 @@ ABitmap* ABitmap_copy(ABitmap* srcBitmapHandle, AndroidBitmapFormat dstFormat) {
return nullptr;
}
static AndroidBitmapInfo getInfo(const SkImageInfo& imageInfo, uint32_t rowBytes) {
AndroidBitmapInfo info;
info.width = imageInfo.width();
info.height = imageInfo.height();
info.stride = rowBytes;
info.format = getFormat(imageInfo);
info.flags = getInfoFlags(imageInfo);
return info;
}
AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmapHandle) {
Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
return getInfo(bitmap->info(), bitmap->rowBytes());
}
AndroidBitmapInfo info;
info.width = bitmap->width();
info.height = bitmap->height();
info.stride = bitmap->rowBytes();
info.format = getFormat(bitmap);
return info;
AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj) {
uint32_t rowBytes = 0;
SkImageInfo imageInfo = GraphicsJNI::getBitmapInfo(env, bitmapObj, &rowBytes);
return getInfo(imageInfo, rowBytes);
}
void* ABitmap_getPixels(ABitmap* bitmapHandle) {
@@ -107,9 +137,17 @@ void* ABitmap_getPixels(ABitmap* bitmapHandle) {
}
AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj) {
return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
return GraphicsJNI::getFormatFromConfig(env, bitmapConfigObj);
}
jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format) {
return GraphicsJNI::getConfigFromFormat(env, format);
return GraphicsJNI::getConfigFromFormat(env, format);
}
void ABitmap_notifyPixelsChanged(ABitmap* bitmapHandle) {
Bitmap* bitmap = TypeCast::toBitmap(bitmapHandle);
if (bitmap->isImmutable()) {
ALOGE("Attempting to modify an immutable Bitmap!");
}
return bitmap->notifyPixelsChanged();
}

View File

@@ -27,6 +27,20 @@ __BEGIN_DECLS
*/
typedef struct ABitmap ABitmap;
/**
* Retrieve bitmapInfo for the provided java bitmap even if it has been recycled. In the case of a
* recycled bitmap the values contained in the bitmap before it was recycled are returned.
*
* NOTE: This API does not need to remain as an APEX API if/when we pull libjnigraphics into the
* UI module.
*/
AndroidBitmapInfo ABitmap_getInfoFromJava(JNIEnv* env, jobject bitmapObj);
/**
*
* @return ptr to an opaque handle to the native bitmap or null if the java bitmap has been recycled
* or does not exist.
*/
ABitmap* ABitmap_acquireBitmapFromJava(JNIEnv* env, jobject bitmapObj);
ABitmap* ABitmap_copy(ABitmap* srcBitmap, AndroidBitmapFormat dstFormat);
@@ -37,6 +51,7 @@ void ABitmap_releaseRef(ABitmap* bitmap);
AndroidBitmapInfo ABitmap_getInfo(ABitmap* bitmap);
void* ABitmap_getPixels(ABitmap* bitmap);
void ABitmap_notifyPixelsChanged(ABitmap* bitmap);
AndroidBitmapFormat ABitmapConfig_getFormatFromConfig(JNIEnv* env, jobject bitmapConfigObj);
jobject ABitmapConfig_getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format);
@@ -88,10 +103,12 @@ namespace graphics {
mBitmap = nullptr;
}
const ABitmap* get() const { return mBitmap; }
ABitmap* get() const { return mBitmap; }
AndroidBitmapInfo getInfo() const { return ABitmap_getInfo(mBitmap); }
void* getPixels() const { return ABitmap_getPixels(mBitmap); }
void notifyPixelsChanged() const { ABitmap_notifyPixelsChanged(mBitmap); }
private:
// takes ownership of the provided ABitmap
Bitmap(ABitmap* bitmap) : mBitmap(bitmap) {}

View File

@@ -15,7 +15,7 @@
*/
#include <android/bitmap.h>
#include <android/graphics/Bitmap.h>
#include <android/graphics/bitmap.h>
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info) {
@@ -24,7 +24,7 @@ int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
}
if (info) {
android::bitmap::imageInfo(env, jbitmap, info);
*info = ABitmap_getInfoFromJava(env, jbitmap);
}
return ANDROID_BITMAP_RESULT_SUCCESS;
}
@@ -34,11 +34,15 @@ int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr) {
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
void* addr = android::bitmap::lockPixels(env, jbitmap);
android::graphics::Bitmap bitmap(env, jbitmap);
void* addr = bitmap.isValid() ? bitmap.getPixels() : nullptr;
if (!addr) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
ABitmap_acquireRef(bitmap.get());
if (addrPtr) {
*addrPtr = addr;
}
@@ -50,9 +54,13 @@ int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap) {
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
bool unlocked = android::bitmap::unlockPixels(env, jbitmap);
if (!unlocked) {
android::graphics::Bitmap bitmap(env, jbitmap);
if (!bitmap.isValid()) {
return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
}
bitmap.notifyPixelsChanged();
ABitmap_releaseRef(bitmap.get());
return ANDROID_BITMAP_RESULT_SUCCESS;
}