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

Commit 0e443d16 authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

ColorSpaces have native SkColorSpaces

Bug: 120904891
Bug: 122844033
Bug: 122514935
Test: CtsGraphicsTestCases

Create an SkColorSpace when creating an android.graphics.ColorSpace.Rgb.
This allows simplifying getNativeColorSpace, so that each time we need
it, we do not need to call back up into Java or reconstruct the
SkColorSpace.

Funnel all ColorSpace.Rgb constructors into one, so we can set a final
mNativePtr in the base constructor. Update TransferParameters to also be
final.

Use the same TransferParameters as SRGB in EXTENDED_SRGB and DISPLAY_P3.

When passing a BitmapFactory.Options to native, call getNativeInstance()
(which may throw an Exception) and pass the result to native.

Move native ColorSpace code into its own file.

Make Paint methods @CriticalNative again, now that they do not need the
JNIEnv.

Remove unused decodeBitmap.

Change-Id: I60adbb060b87ab6f92559f1217bfefc0b9ea72e1
parent 61ae7ed2
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -61,8 +61,11 @@ cc_library_shared {
        "android_database_SQLiteConnection.cpp",
        "android_database_SQLiteGlobal.cpp",
        "android_database_SQLiteDebug.cpp",
        "android_graphics_Canvas.cpp",
        "android_graphics_ColorSpace.cpp",
        "android_graphics_drawable_AnimatedVectorDrawable.cpp",
        "android_graphics_drawable_VectorDrawable.cpp",
        "android_graphics_Picture.cpp",
        "android_view_DisplayEventReceiver.cpp",
        "android_view_DisplayListCanvas.cpp",
        "android_view_TextureLayer.cpp",
@@ -117,8 +120,6 @@ cc_library_shared {
        "android_util_StringBlock.cpp",
        "android_util_XmlBlock.cpp",
        "android_util_jar_StrictJarFile.cpp",
        "android_graphics_Canvas.cpp",
        "android_graphics_Picture.cpp",
        "android/graphics/AnimatedImageDrawable.cpp",
        "android/graphics/Bitmap.cpp",
        "android/graphics/BitmapFactory.cpp",
+4 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ extern int register_android_content_res_ApkAssets(JNIEnv* env);
extern int register_android_graphics_Canvas(JNIEnv* env);
extern int register_android_graphics_CanvasProperty(JNIEnv* env);
extern int register_android_graphics_ColorFilter(JNIEnv* env);
extern int register_android_graphics_ColorSpace(JNIEnv* env);
extern int register_android_graphics_DrawFilter(JNIEnv* env);
extern int register_android_graphics_FontFamily(JNIEnv* env);
extern int register_android_graphics_Matrix(JNIEnv* env);
@@ -1361,6 +1362,9 @@ static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_os_VintfRuntimeInfo),
    REG_JNI(register_android_nio_utils),
    REG_JNI(register_android_graphics_Canvas),
    // This needs to be before register_android_graphics_Graphics, or the latter
    // will not be able to find the jmethodID for ColorSpace.get().
    REG_JNI(register_android_graphics_ColorSpace),
    REG_JNI(register_android_graphics_Graphics),
    REG_JNI(register_android_view_DisplayEventReceiver),
    REG_JNI(register_android_view_RenderNode),
+12 −26
Original line number Diff line number Diff line
@@ -334,7 +334,7 @@ static int getPremulBitmapCreateFlags(bool isMutable) {
static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                              jint offset, jint stride, jint width, jint height,
                              jint configHandle, jboolean isMutable,
                              jfloatArray xyzD50, jobject transferParameters) {
                              jlong colorSpacePtr) {
    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
    if (NULL != jColors) {
        size_t n = env->GetArrayLength(jColors);
@@ -350,17 +350,8 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
    }

    SkBitmap bitmap;
    sk_sp<SkColorSpace> colorSpace;

    if (xyzD50 == nullptr || transferParameters == nullptr) {
        colorSpace = SkColorSpace::MakeSRGB();
    } else {
        skcms_TransferFunction p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
        skcms_Matrix3x3 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
        colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
    }

    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType, colorSpace));
    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
                GraphicsJNI::getNativeColorSpace(colorSpacePtr)));

    sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap);
    if (!nativeBitmap) {
@@ -582,16 +573,13 @@ static void Bitmap_erase(JNIEnv* env, jobject, jlong bitmapHandle, jint color) {
    bitmapErase(skBitmap, SkColor4f::FromColor(color), SkColorSpace::MakeSRGB());
}

static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle, jobject jColorSpace,
static void Bitmap_eraseLong(JNIEnv* env, jobject, jlong bitmapHandle, jlong colorSpaceHandle,
        jfloat r, jfloat g, jfloat b, jfloat a) {
    sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(env, jColorSpace);
    if (GraphicsJNI::hasException(env)) {
        return;
    }

    LocalScopedBitmap bitmap(bitmapHandle);
    SkBitmap skBitmap;
    bitmap->getSkBitmap(&skBitmap);

    sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
    SkColor4f color = SkColor4f{r, g, b, a};
    bitmapErase(skBitmap, color, cs);
}
@@ -1141,14 +1129,12 @@ static jobject Bitmap_createHardwareBitmap(JNIEnv* env, jobject, jobject graphic
}

static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
                                               jfloatArray xyzD50, jobject transferParameters) {
    skcms_TransferFunction p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
    skcms_Matrix3x3 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
    sk_sp<SkColorSpace> colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
                                               jlong colorSpacePtr) {
    AHardwareBuffer* hwBuf = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
        hardwareBuffer);
    sp<GraphicBuffer> buffer(AHardwareBuffer_to_GraphicBuffer(hwBuf));
    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer, colorSpace);
    sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer,
            GraphicsJNI::getNativeColorSpace(colorSpacePtr));
    if (!bitmap.get()) {
        ALOGW("failed to create hardware bitmap from hardware buffer");
        return NULL;
@@ -1190,7 +1176,7 @@ static void Bitmap_setImmutable(JNIEnv* env, jobject, jlong bitmapHandle) {
///////////////////////////////////////////////////////////////////////////////

static const JNINativeMethod gBitmapMethods[] = {
    {   "nativeCreate",             "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
    {   "nativeCreate",             "([IIIIIIZJ)Landroid/graphics/Bitmap;",
        (void*)Bitmap_creator },
    {   "nativeCopy",               "(JIZ)Landroid/graphics/Bitmap;",
        (void*)Bitmap_copy },
@@ -1204,7 +1190,7 @@ static const JNINativeMethod gBitmapMethods[] = {
    {   "nativeCompress",           "(JIILjava/io/OutputStream;[B)Z",
        (void*)Bitmap_compress },
    {   "nativeErase",              "(JI)V", (void*)Bitmap_erase },
    {   "nativeErase",              "(JLandroid/graphics/ColorSpace;FFFF)V", (void*)Bitmap_eraseLong },
    {   "nativeErase",              "(JJFFFF)V", (void*)Bitmap_eraseLong },
    {   "nativeRowBytes",           "(J)I", (void*)Bitmap_rowBytes },
    {   "nativeConfig",             "(J)I", (void*)Bitmap_config },
    {   "nativeHasAlpha",           "(J)Z", (void*)Bitmap_hasAlpha },
@@ -1236,7 +1222,7 @@ static const JNINativeMethod gBitmapMethods[] = {
        (void*)Bitmap_copyPreserveInternalConfig },
    {   "nativeCreateHardwareBitmap", "(Landroid/graphics/GraphicBuffer;)Landroid/graphics/Bitmap;",
        (void*) Bitmap_createHardwareBitmap },
    {   "nativeWrapHardwareBufferBitmap", "(Landroid/hardware/HardwareBuffer;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
    {   "nativeWrapHardwareBufferBitmap", "(Landroid/hardware/HardwareBuffer;J)Landroid/graphics/Bitmap;",
        (void*) Bitmap_wrapHardwareBufferBitmap },
    {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
        (void*) Bitmap_createGraphicBufferHandle },
+17 −22
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize,
}

static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,
                        jobject padding, jobject options) {
                        jobject padding, jobject options, jlong colorSpaceHandle) {
    // Set default values for the options parameters.
    int sampleSize = 1;
    bool onlyDecodeSize = false;
@@ -189,7 +189,7 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,
    float scale = 1.0f;
    bool requireUnpremultiplied = false;
    jobject javaBitmap = NULL;
    sk_sp<SkColorSpace> prefColorSpace = nullptr;
    sk_sp<SkColorSpace> prefColorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);

    // Update with options supplied by the client.
    if (options != NULL) {
@@ -213,8 +213,6 @@ static jobject doDecode(JNIEnv* env, std::unique_ptr<SkStreamRewindable> stream,

        jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
        prefColorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
        jobject jcolorSpace = env->GetObjectField(options, gOptions_colorSpaceFieldID);
        prefColorSpace = GraphicsJNI::getNativeColorSpace(env, jcolorSpace);
        isHardware = GraphicsJNI::isHardwareConfig(env, jconfig);
        isMutable = env->GetBooleanField(options, gOptions_mutableFieldID);
        requireUnpremultiplied = !env->GetBooleanField(options, gOptions_premultipliedFieldID);
@@ -515,7 +513,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) {
        jobject padding, jobject options, jlong colorSpaceHandle) {

    jobject bitmap = NULL;
    std::unique_ptr<SkStream> stream(CreateJavaInputStreamAdaptor(env, is, storage));
@@ -524,13 +522,13 @@ 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);
        bitmap = doDecode(env, std::move(bufferedStream), padding, options, colorSpaceHandle);
    }
    return bitmap;
}

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

    NPE_CHECK_RETURN_ZERO(env, fileDescriptor);

@@ -566,7 +564,8 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
    // If there is no offset for the file descriptor, we use SkFILEStream directly.
    if (::lseek(descriptor, 0, SEEK_CUR) == 0) {
        assert(isSeekable(dupDescriptor));
        return doDecode(env, std::move(fileStream), padding, bitmapFactoryOptions);
        return doDecode(env, std::move(fileStream), padding, bitmapFactoryOptions,
                colorSpaceHandle);
    }

    // Use a buffered stream. Although an SkFILEStream can be rewound, this
@@ -575,24 +574,25 @@ 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);
    return doDecode(env, std::move(stream), padding, bitmapFactoryOptions, colorSpaceHandle);
}

static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jlong native_asset,
        jobject padding, jobject options) {
        jobject padding, jobject options, 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);
    return doDecode(env, skstd::make_unique<AssetStreamAdaptor>(asset), padding, options,
            colorSpaceHandle);
}

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

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

static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
@@ -600,31 +600,26 @@ static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
    return isSeekable(descriptor) ? JNI_TRUE : JNI_FALSE;
}

jobject decodeBitmap(JNIEnv* env, void* data, size_t size) {
    return doDecode(env, skstd::make_unique<SkMemoryStream>(data, size),
                    nullptr, nullptr);
}

///////////////////////////////////////////////////////////////////////////////

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

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

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

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

+0 −2
Original line number Diff line number Diff line
@@ -28,6 +28,4 @@ extern jmethodID gBitmapConfig_nativeToConfigMethodID;

jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format);

jobject decodeBitmap(JNIEnv* env, void* data, size_t size);

#endif  // _ANDROID_GRAPHICS_BITMAP_FACTORY_H_
Loading