diff options
author | 2023-02-06 11:11:31 -0800 | |
---|---|---|
committer | 2023-02-14 17:19:41 -0800 | |
commit | 9d2d9340ab44bfb81819d6fd4fcf0dd466a77274 (patch) | |
tree | 4e0ed3e36bc33105864b860920d614f8ebbcc868 | |
parent | 31d0a29374594e185f42e8428d5779d633a2b548 (diff) |
Make gainmap parcelable.
Bug: 267215989
Test: android.graphics.cts.GainmapTest
Change-Id: I189f652f26f2f92e37afdc3f69ae7b7653d69bf0
-rw-r--r-- | core/api/current.txt | 5 | ||||
-rw-r--r-- | graphics/java/android/graphics/Bitmap.java | 43 | ||||
-rw-r--r-- | graphics/java/android/graphics/Gainmap.java | 50 | ||||
-rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
-rw-r--r-- | libs/hwui/jni/Bitmap.cpp | 92 | ||||
-rw-r--r-- | libs/hwui/jni/Gainmap.cpp | 82 | ||||
-rw-r--r-- | libs/hwui/jni/ScopedParcel.cpp | 85 | ||||
-rw-r--r-- | libs/hwui/jni/ScopedParcel.h | 63 |
8 files changed, 312 insertions, 109 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index d54290b70a72..4b160d928573 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -15497,8 +15497,9 @@ package android.graphics { ctor @Deprecated public EmbossMaskFilter(float[], float, float, float); } - public final class Gainmap { + public final class Gainmap implements android.os.Parcelable { ctor public Gainmap(@NonNull android.graphics.Bitmap); + method public int describeContents(); method @NonNull public float getDisplayRatioForFullHdr(); method @NonNull public float[] getEpsilonHdr(); method @NonNull public float[] getEpsilonSdr(); @@ -15515,6 +15516,8 @@ package android.graphics { method @NonNull public void setMinDisplayRatioForHdrTransition(@FloatRange(from=1.0f) float); method @NonNull public void setRatioMax(float, float, float); method @NonNull public void setRatioMin(float, float, float); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.graphics.Gainmap> CREATOR; } public class HardwareBufferRenderer implements java.lang.AutoCloseable { diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index b1abc2a1a679..a39dd0853ca6 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -2175,23 +2175,26 @@ public final class Bitmap implements Parcelable { public static final @NonNull Parcelable.Creator<Bitmap> CREATOR = new Parcelable.Creator<Bitmap>() { - /** - * Rebuilds a bitmap previously stored with writeToParcel(). - * - * @param p Parcel object to read the bitmap from - * @return a new bitmap created from the data in the parcel - */ - public Bitmap createFromParcel(Parcel p) { - Bitmap bm = nativeCreateFromParcel(p); - if (bm == null) { - throw new RuntimeException("Failed to unparcel Bitmap"); - } - return bm; - } - public Bitmap[] newArray(int size) { - return new Bitmap[size]; - } - }; + /** + * Rebuilds a bitmap previously stored with writeToParcel(). + * + * @param p Parcel object to read the bitmap from + * @return a new bitmap created from the data in the parcel + */ + public Bitmap createFromParcel(Parcel p) { + Bitmap bm = nativeCreateFromParcel(p); + if (bm == null) { + throw new RuntimeException("Failed to unparcel Bitmap"); + } + if (p.readBoolean()) { + bm.setGainmap(p.readTypedObject(Gainmap.CREATOR)); + } + return bm; + } + public Bitmap[] newArray(int size) { + return new Bitmap[size]; + } + }; /** * No special parcel contents. @@ -2215,6 +2218,12 @@ public final class Bitmap implements Parcelable { if (!nativeWriteToParcel(mNativePtr, mDensity, p)) { throw new RuntimeException("native writeToParcel failed"); } + if (hasGainmap()) { + p.writeBoolean(true); + p.writeTypedObject(mGainmap, flags); + } else { + p.writeBoolean(false); + } } /** diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java index 53f23c08dab6..470a06c1f1f5 100644 --- a/graphics/java/android/graphics/Gainmap.java +++ b/graphics/java/android/graphics/Gainmap.java @@ -18,6 +18,8 @@ package android.graphics; import android.annotation.FloatRange; import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; import libcore.util.NativeAllocationRegistry; @@ -76,7 +78,7 @@ import libcore.util.NativeAllocationRegistry; * * In the above math, log() is a natural logarithm and exp() is natural exponentiation. */ -public final class Gainmap { +public final class Gainmap implements Parcelable { // Use a Holder to allow static initialization of Gainmap in the boot image. private static class NoImagePreloadHolder { @@ -284,6 +286,50 @@ public final class Gainmap { return nGetDisplayRatioSdr(mNativePtr); } + /** + * No special parcel contents. + */ + @Override + public int describeContents() { + return 0; + } + + /** + * Write the gainmap to the parcel. + * + * @param dest Parcel object to write the gainmap data into + * @param flags Additional flags about how the object should be written. + */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + if (mNativePtr == 0) { + throw new IllegalStateException("Cannot be written to a parcel"); + } + dest.writeTypedObject(mGainmapContents, flags); + // write gainmapinfo into parcel + nWriteGainmapToParcel(mNativePtr, dest); + } + + public static final @NonNull Parcelable.Creator<Gainmap> CREATOR = + new Parcelable.Creator<Gainmap>() { + /** + * Rebuilds a gainmap previously stored with writeToParcel(). + * + * @param in Parcel object to read the gainmap from + * @return a new gainmap created from the data in the parcel + */ + public Gainmap createFromParcel(Parcel in) { + Gainmap gm = new Gainmap(in.readTypedObject(Bitmap.CREATOR)); + // read gainmapinfo from parcel + nReadGainmapFromParcel(gm.mNativePtr, in); + return gm; + } + + public Gainmap[] newArray(int size) { + return new Gainmap[size]; + } + }; + private static native long nGetFinalizer(); private static native long nCreateEmpty(); @@ -309,4 +355,6 @@ public final class Gainmap { private static native void nSetDisplayRatioSdr(long ptr, float min); private static native float nGetDisplayRatioSdr(long ptr); + private static native void nWriteGainmapToParcel(long ptr, Parcel dest); + private static native void nReadGainmapFromParcel(long ptr, Parcel src); } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 9e3f115762a1..b221654f79fd 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -364,6 +364,7 @@ cc_defaults { "jni/PathMeasure.cpp", "jni/Picture.cpp", "jni/Region.cpp", + "jni/ScopedParcel.cpp", "jni/Shader.cpp", "jni/RenderEffect.cpp", "jni/Typeface.cpp", diff --git a/libs/hwui/jni/Bitmap.cpp b/libs/hwui/jni/Bitmap.cpp index e71a2a573c87..3f9c4bd2aeff 100644 --- a/libs/hwui/jni/Bitmap.cpp +++ b/libs/hwui/jni/Bitmap.cpp @@ -10,6 +10,7 @@ #include "Gainmap.h" #include "GraphicsJNI.h" #include "HardwareBufferHelpers.h" +#include "ScopedParcel.h" #include "SkBitmap.h" #include "SkBlendMode.h" #include "SkCanvas.h" @@ -27,12 +28,7 @@ #ifdef __ANDROID__ // Layoutlib does not support graphic buffer, parcel or render thread #include <android-base/unique_fd.h> -#include <android/binder_parcel.h> -#include <android/binder_parcel_jni.h> -#include <android/binder_parcel_platform.h> -#include <cutils/ashmem.h> #include <renderthread/RenderProxy.h> -#include <sys/mman.h> #endif #include <inttypes.h> @@ -616,91 +612,7 @@ static void Bitmap_setHasMipMap(JNIEnv* env, jobject, jlong bitmapHandle, /////////////////////////////////////////////////////////////////////////////// // TODO: Move somewhere else -#ifdef __ANDROID__ // Layoutlib does not support parcel - -class ScopedParcel { -public: - explicit ScopedParcel(JNIEnv* env, jobject parcel) { - mParcel = AParcel_fromJavaParcel(env, parcel); - } - - ~ScopedParcel() { AParcel_delete(mParcel); } - - int32_t readInt32() { - int32_t temp = 0; - // TODO: This behavior-matches what android::Parcel does - // but this should probably be better - if (AParcel_readInt32(mParcel, &temp) != STATUS_OK) { - temp = 0; - } - return temp; - } - - uint32_t readUint32() { - uint32_t temp = 0; - // TODO: This behavior-matches what android::Parcel does - // but this should probably be better - if (AParcel_readUint32(mParcel, &temp) != STATUS_OK) { - temp = 0; - } - return temp; - } - - void writeInt32(int32_t value) { AParcel_writeInt32(mParcel, value); } - - void writeUint32(uint32_t value) { AParcel_writeUint32(mParcel, value); } - - bool allowFds() const { return AParcel_getAllowFds(mParcel); } - - std::optional<sk_sp<SkData>> readData() { - struct Data { - void* ptr = nullptr; - size_t size = 0; - } data; - auto error = AParcel_readByteArray(mParcel, &data, - [](void* arrayData, int32_t length, - int8_t** outBuffer) -> bool { - Data* data = reinterpret_cast<Data*>(arrayData); - if (length > 0) { - data->ptr = sk_malloc_canfail(length); - if (!data->ptr) { - return false; - } - *outBuffer = - reinterpret_cast<int8_t*>(data->ptr); - data->size = length; - } - return true; - }); - if (error != STATUS_OK || data.size <= 0) { - sk_free(data.ptr); - return std::nullopt; - } else { - return SkData::MakeFromMalloc(data.ptr, data.size); - } - } - - void writeData(const std::optional<sk_sp<SkData>>& optData) { - if (optData) { - const auto& data = *optData; - AParcel_writeByteArray(mParcel, reinterpret_cast<const int8_t*>(data->data()), - data->size()); - } else { - AParcel_writeByteArray(mParcel, nullptr, -1); - } - } - - AParcel* get() { return mParcel; } - -private: - AParcel* mParcel; -}; - -enum class BlobType : int32_t { - IN_PLACE, - ASHMEM, -}; - +#ifdef __ANDROID__ // Layoutlib does not support parcel #define ON_ERROR_RETURN(X) \ if ((error = (X)) != STATUS_OK) return error diff --git a/libs/hwui/jni/Gainmap.cpp b/libs/hwui/jni/Gainmap.cpp index 9cd3fb0799d7..0f8a85dd9e62 100644 --- a/libs/hwui/jni/Gainmap.cpp +++ b/libs/hwui/jni/Gainmap.cpp @@ -16,8 +16,13 @@ #include <Gainmap.h> +#ifdef __ANDROID__ +#include <binder/Parcel.h> +#endif + #include "Bitmap.h" #include "GraphicsJNI.h" +#include "ScopedParcel.h" #include "graphics_jni_helpers.h" namespace android { @@ -154,6 +159,81 @@ static jfloat Gainmap_getDisplayRatioSdr(JNIEnv*, jobject, jlong gainmapPtr) { return fromJava(gainmapPtr)->info.fDisplayRatioSdr; } +// ---------------------------------------------------------------------------- +// Serialization +// ---------------------------------------------------------------------------- + +static void Gainmap_writeToParcel(JNIEnv* env, jobject, jlong nativeObject, jobject parcel) { +#ifdef __ANDROID__ // Layoutlib does not support parcel + if (parcel == NULL) { + ALOGD("write null parcel\n"); + return; + } + ScopedParcel p(env, parcel); + SkGainmapInfo info = fromJava(nativeObject)->info; + // write gainmap to parcel + // ratio min + p.writeFloat(info.fGainmapRatioMin.fR); + p.writeFloat(info.fGainmapRatioMin.fG); + p.writeFloat(info.fGainmapRatioMin.fB); + // ratio max + p.writeFloat(info.fGainmapRatioMax.fR); + p.writeFloat(info.fGainmapRatioMax.fG); + p.writeFloat(info.fGainmapRatioMax.fB); + // gamma + p.writeFloat(info.fGainmapGamma.fR); + p.writeFloat(info.fGainmapGamma.fG); + p.writeFloat(info.fGainmapGamma.fB); + // epsilonsdr + p.writeFloat(info.fEpsilonSdr.fR); + p.writeFloat(info.fEpsilonSdr.fG); + p.writeFloat(info.fEpsilonSdr.fB); + // epsilonhdr + p.writeFloat(info.fEpsilonHdr.fR); + p.writeFloat(info.fEpsilonHdr.fG); + p.writeFloat(info.fEpsilonHdr.fB); + // display ratio sdr + p.writeFloat(info.fDisplayRatioSdr); + // display ratio hdr + p.writeFloat(info.fDisplayRatioHdr); + // base image type + p.writeInt32(static_cast<int32_t>(info.fBaseImageType)); + // type + p.writeInt32(static_cast<int32_t>(info.fType)); +#else + doThrowRE(env, "Cannot use parcels outside of Android!"); +#endif +} + +static void Gainmap_readFromParcel(JNIEnv* env, jobject, jlong nativeObject, jobject parcel) { +#ifdef __ANDROID__ // Layoutlib does not support parcel + if (parcel == NULL) { + jniThrowNullPointerException(env, "parcel cannot be null"); + return; + } + ScopedParcel p(env, parcel); + + SkGainmapInfo info; + info.fGainmapRatioMin = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; + info.fGainmapRatioMax = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; + info.fGainmapGamma = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; + info.fEpsilonSdr = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; + info.fEpsilonHdr = {p.readFloat(), p.readFloat(), p.readFloat(), 1.f}; + info.fDisplayRatioSdr = p.readFloat(); + info.fDisplayRatioHdr = p.readFloat(); + info.fBaseImageType = static_cast<SkGainmapInfo::BaseImageType>(p.readInt32()); + info.fType = static_cast<SkGainmapInfo::Type>(p.readInt32()); + + fromJava(nativeObject)->info = info; +#else + jniThrowRuntimeException(env, "Cannot use parcels outside of Android"); +#endif +} + +// ---------------------------------------------------------------------------- +// JNI Glue +// ---------------------------------------------------------------------------- + static const JNINativeMethod gGainmapMethods[] = { {"nGetFinalizer", "()J", (void*)Gainmap_getNativeFinalizer}, {"nCreateEmpty", "()J", (void*)Gainmap_createEmpty}, @@ -172,6 +252,8 @@ static const JNINativeMethod gGainmapMethods[] = { {"nGetDisplayRatioHdr", "(J)F", (void*)Gainmap_getDisplayRatioHdr}, {"nSetDisplayRatioSdr", "(JF)V", (void*)Gainmap_setDisplayRatioSdr}, {"nGetDisplayRatioSdr", "(J)F", (void*)Gainmap_getDisplayRatioSdr}, + {"nWriteGainmapToParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_writeToParcel}, + {"nReadGainmapFromParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_readFromParcel}, }; int register_android_graphics_Gainmap(JNIEnv* env) { diff --git a/libs/hwui/jni/ScopedParcel.cpp b/libs/hwui/jni/ScopedParcel.cpp new file mode 100644 index 000000000000..b0f5423813b7 --- /dev/null +++ b/libs/hwui/jni/ScopedParcel.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "ScopedParcel.h" + +#ifdef __ANDROID__ // Layoutlib does not support parcel + +using namespace android; + +int32_t ScopedParcel::readInt32() { + int32_t temp = 0; + // TODO: This behavior-matches what android::Parcel does + // but this should probably be better + if (AParcel_readInt32(mParcel, &temp) != STATUS_OK) { + temp = 0; + } + return temp; +} + +uint32_t ScopedParcel::readUint32() { + uint32_t temp = 0; + // TODO: This behavior-matches what android::Parcel does + // but this should probably be better + if (AParcel_readUint32(mParcel, &temp) != STATUS_OK) { + temp = 0; + } + return temp; +} + +float ScopedParcel::readFloat() { + float temp = 0.; + if (AParcel_readFloat(mParcel, &temp) != STATUS_OK) { + temp = 0.; + } + return temp; +} + +std::optional<sk_sp<SkData>> ScopedParcel::readData() { + struct Data { + void* ptr = nullptr; + size_t size = 0; + } data; + auto error = AParcel_readByteArray( + mParcel, &data, [](void* arrayData, int32_t length, int8_t** outBuffer) -> bool { + Data* data = reinterpret_cast<Data*>(arrayData); + if (length > 0) { + data->ptr = sk_malloc_canfail(length); + if (!data->ptr) { + return false; + } + *outBuffer = reinterpret_cast<int8_t*>(data->ptr); + data->size = length; + } + return true; + }); + if (error != STATUS_OK || data.size <= 0) { + sk_free(data.ptr); + return std::nullopt; + } else { + return SkData::MakeFromMalloc(data.ptr, data.size); + } +} + +void ScopedParcel::writeData(const std::optional<sk_sp<SkData>>& optData) { + if (optData) { + const auto& data = *optData; + AParcel_writeByteArray(mParcel, reinterpret_cast<const int8_t*>(data->data()), + data->size()); + } else { + AParcel_writeByteArray(mParcel, nullptr, -1); + } +} +#endif // __ANDROID__ // Layoutlib does not support parcel diff --git a/libs/hwui/jni/ScopedParcel.h b/libs/hwui/jni/ScopedParcel.h new file mode 100644 index 000000000000..fd8d6a210f0f --- /dev/null +++ b/libs/hwui/jni/ScopedParcel.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "SkData.h" + +#ifdef __ANDROID__ // Layoutlib does not support parcel +#include <android-base/unique_fd.h> +#include <android/binder_parcel.h> +#include <android/binder_parcel_jni.h> +#include <android/binder_parcel_platform.h> +#include <cutils/ashmem.h> +#include <renderthread/RenderProxy.h> + +class ScopedParcel { +public: + explicit ScopedParcel(JNIEnv* env, jobject parcel) { + mParcel = AParcel_fromJavaParcel(env, parcel); + } + + ~ScopedParcel() { AParcel_delete(mParcel); } + + int32_t readInt32(); + + uint32_t readUint32(); + + float readFloat(); + + void writeInt32(int32_t value) { AParcel_writeInt32(mParcel, value); } + + void writeUint32(uint32_t value) { AParcel_writeUint32(mParcel, value); } + + void writeFloat(float value) { AParcel_writeFloat(mParcel, value); } + + bool allowFds() const { return AParcel_getAllowFds(mParcel); } + + std::optional<sk_sp<SkData>> readData(); + + void writeData(const std::optional<sk_sp<SkData>>& optData); + + AParcel* get() { return mParcel; } + +private: + AParcel* mParcel; +}; + +enum class BlobType : int32_t { + IN_PLACE, + ASHMEM, +}; + +#endif // __ANDROID__ // Layoutlib does not support parcel
\ No newline at end of file |