Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71fae62f authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

Pass Bitmap's native instance to JNI where feasible

Test: CtsGraphicsTestCases, CtsUiRenderingTestCases,
      CtsRenderscriptTestCases

This is significantly faster than passing the Java object down and then
calling a JNI method to retrieve the pointer. See
https://buganizer.corp.google.com/issues/16656908#comment19

In some cases this changes what used to be native crashes (due to
android::BitmapWrapper:assertValid's LOG_ALWAYS_FATAL_IF) into
NullPointerExceptions (if a caller used a null Bitmap).

In addition:
- Remove unnecessary JNIEnv param from toBitmap(jlong)
- Change instances of toBitmap(JNIEnv*, jobject) to the above
- Replace calls to GraphicsJNI::getSkBitmap() to inline calls to
  toBitmap/getSkBitmap
- make Canvas#nInitRaster @FastNative (FIXME: Could these be
  @CriticalNative?)

Change-Id: I6194097be1b6e6952eba70e1e7052a5a250eed93
parent ca8aef63
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -230,8 +230,7 @@ Bitmap& toBitmap(JNIEnv* env, jobject bitmap) {
    return localBitmap->bitmap();
}

Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle) {
    SkASSERT(env);
Bitmap& toBitmap(jlong bitmapHandle) {
    LocalScopedBitmap localBitmap(bitmapHandle);
    return localBitmap->bitmap();
}
+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ jobject createBitmap(JNIEnv* env, Bitmap* bitmap,
void toSkBitmap(jlong bitmapHandle, SkBitmap* outBitmap);

Bitmap& toBitmap(JNIEnv* env, jobject bitmap);
Bitmap& toBitmap(JNIEnv* env, jlong bitmapHandle);
Bitmap& toBitmap(jlong bitmapHandle);

// NDK access
void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info);
+19 −16
Original line number Diff line number Diff line
@@ -180,7 +180,8 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize,
}

static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,
                        jobject padding, jobject options, jlong colorSpaceHandle) {
                        jobject padding, jobject options, jlong inBitmapHandle,
                        jlong colorSpaceHandle) {
    // Set default values for the options parameters.
    int sampleSize = 1;
    bool onlyDecodeSize = false;
@@ -323,8 +324,8 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,

    android::Bitmap* reuseBitmap = nullptr;
    unsigned int existingBufferSize = 0;
    if (javaBitmap != NULL) {
        reuseBitmap = &bitmap::toBitmap(env, javaBitmap);
    if (javaBitmap != nullptr) {
        reuseBitmap = &bitmap::toBitmap(inBitmapHandle);
        if (reuseBitmap->isImmutable()) {
            ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
            javaBitmap = nullptr;
@@ -513,7 +514,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,
}

static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
        jobject padding, jobject options, jlong colorSpaceHandle) {
        jobject padding, jobject options, jlong inBitmapHandle, jlong colorSpaceHandle) {

    jobject bitmap = NULL;
    std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage));
@@ -522,13 +523,14 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
        std::unique_ptr<SkStreamRewindable> bufferedStream(
                SkFrontBufferedStream::Make(std::move(stream), SkCodec::MinBufferedBytesNeeded()));
        SkASSERT(bufferedStream.get() != NULL);
        bitmap = doDecode(env, std::move(bufferedStream), padding, options, colorSpaceHandle);
        bitmap = doDecode(env, std::move(bufferedStream), padding, options, inBitmapHandle,
                          colorSpaceHandle);
    }
    return bitmap;
}

static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fileDescriptor,
        jobject padding, jobject bitmapFactoryOptions, jlong colorSpaceHandle) {
        jobject padding, jobject bitmapFactoryOptions, jlong inBitmapHandle, jlong colorSpaceHandle) {

    NPE_CHECK_RETURN_ZERO(env, fileDescriptor);

@@ -565,7 +567,7 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
    if (::lseek(descriptor, 0, SEEK_CUR) == 0) {
        assert(isSeekable(dupDescriptor));
        return doDecode(env, std::move(fileStream), padding, bitmapFactoryOptions,
                colorSpaceHandle);
                        inBitmapHandle, colorSpaceHandle);
    }

    // Use a buffered stream. Although an SkFILEStream can be rewound, this
@@ -574,25 +576,26 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
    std::unique_ptr<SkStreamRewindable> stream(SkFrontBufferedStream::Make(std::move(fileStream),
            SkCodec::MinBufferedBytesNeeded()));

    return doDecode(env, std::move(stream), padding, bitmapFactoryOptions, colorSpaceHandle);
    return doDecode(env, std::move(stream), padding, bitmapFactoryOptions, inBitmapHandle,
                    colorSpaceHandle);
}

static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jlong native_asset,
        jobject padding, jobject options, jlong colorSpaceHandle) {
        jobject padding, jobject options, jlong inBitmapHandle, jlong colorSpaceHandle) {

    Asset* asset = reinterpret_cast<Asset*>(native_asset);
    // since we know we'll be done with the asset when we return, we can
    // just use a simple wrapper
    return doDecode(env, skstd::make_unique<AssetStreamAdaptor>(asset), padding, options,
            colorSpaceHandle);
                    inBitmapHandle, colorSpaceHandle);
}

static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
        jint offset, jint length, jobject options, jlong colorSpaceHandle) {
        jint offset, jint length, jobject options, jlong inBitmapHandle, jlong colorSpaceHandle) {

    AutoJavaByteArray ar(env, byteArray);
    return doDecode(env, skstd::make_unique<SkMemoryStream>(ar.ptr() + offset, length, false),
                    nullptr, options, colorSpaceHandle);
                    nullptr, options, inBitmapHandle, colorSpaceHandle);
}

static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
@@ -604,22 +607,22 @@ static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {

static const JNINativeMethod gMethods[] = {
    {   "nativeDecodeStream",
        "(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;",
        "(Ljava/io/InputStream;[BLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;",
        (void*)nativeDecodeStream
    },

    {   "nativeDecodeFileDescriptor",
        "(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;",
        "(Ljava/io/FileDescriptor;Landroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;",
        (void*)nativeDecodeFileDescriptor
    },

    {   "nativeDecodeAsset",
        "(JLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;",
        "(JLandroid/graphics/Rect;Landroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;",
        (void*)nativeDecodeAsset
    },

    {   "nativeDecodeByteArray",
        "([BIILandroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;",
        "([BIILandroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;",
        (void*)nativeDecodeByteArray
    },

+5 −4
Original line number Diff line number Diff line
@@ -125,13 +125,14 @@ static jobject nativeNewInstanceFromAsset(JNIEnv* env, jobject clazz,
 * reportSizeToVM not supported
 */
static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint inputX,
        jint inputY, jint inputWidth, jint inputHeight, jobject options, jlong colorSpaceHandle) {
        jint inputY, jint inputWidth, jint inputHeight, jobject options, jlong inBitmapHandle,
        jlong colorSpaceHandle) {

    // Set default options.
    int sampleSize = 1;
    SkColorType colorType = kN32_SkColorType;
    bool requireUnpremul = false;
    jobject javaBitmap = NULL;
    jobject javaBitmap = nullptr;
    bool isHardware = false;
    sk_sp<SkColorSpace> colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
    // Update the default options with any options supplied by the client.
@@ -158,7 +159,7 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
    android::Bitmap* recycledBitmap = nullptr;
    size_t recycledBytes = 0;
    if (javaBitmap) {
        recycledBitmap = &bitmap::toBitmap(env, javaBitmap);
        recycledBitmap = &bitmap::toBitmap(inBitmapHandle);
        if (recycledBitmap->isImmutable()) {
            ALOGW("Warning: Reusing an immutable bitmap as an image decoder target.");
        }
@@ -258,7 +259,7 @@ static void nativeClean(JNIEnv* env, jobject, jlong brdHandle) {

static const JNINativeMethod gBitmapRegionDecoderMethods[] = {
    {   "nativeDecodeRegion",
        "(JIIIILandroid/graphics/BitmapFactory$Options;J)Landroid/graphics/Bitmap;",
        "(JIIIILandroid/graphics/BitmapFactory$Options;JJ)Landroid/graphics/Bitmap;",
        (void*)nativeDecodeRegion},

    {   "nativeGetHeight", "(J)I", (void*)nativeGetHeight},
+3 −3
Original line number Diff line number Diff line
@@ -84,13 +84,13 @@ public:
        delete[] patch;
    }

    static jlong getTransparentRegion(JNIEnv* env, jobject, jobject jbitmap,
    static jlong getTransparentRegion(JNIEnv* env, jobject, jlong bitmapPtr,
            jlong chunkHandle, jobject dstRect) {
        Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
        SkASSERT(chunk);

        SkBitmap bitmap;
        GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
        bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
        SkRect dst;
        GraphicsJNI::jrect_to_rect(env, dstRect, &dst);

@@ -156,7 +156,7 @@ static const JNINativeMethod gNinePatchMethods[] = {
    { "validateNinePatchChunk", "([B)J",
            (void*) SkNinePatchGlue::validateNinePatchChunk },
    { "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize },
    { "nativeGetTransparentRegion", "(Landroid/graphics/Bitmap;JLandroid/graphics/Rect;)J",
    { "nativeGetTransparentRegion", "(JJLandroid/graphics/Rect;)J",
            (void*) SkNinePatchGlue::getTransparentRegion }
};

Loading