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

Commit d7e90a61 authored by Alec Mouri's avatar Alec Mouri
Browse files

Add support for ISO gainmap metadata

Bug: 349357636
Flag: com.android.graphics.hwui.flags.iso_gainmap_apis
Test: builds
Change-Id: Id13791404168ac5b880c51f07f56c1c4287d5d31
parent 6f6679bf
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -16128,24 +16128,30 @@ package android.graphics {
    ctor public Gainmap(@NonNull android.graphics.Bitmap);
    ctor @FlaggedApi("com.android.graphics.hwui.flags.gainmap_constructor_with_metadata") public Gainmap(@NonNull android.graphics.Gainmap, @NonNull android.graphics.Bitmap);
    method public int describeContents();
    method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") @Nullable public android.graphics.ColorSpace getAlternativeImagePrimaries();
    method @NonNull public float getDisplayRatioForFullHdr();
    method @NonNull public float[] getEpsilonHdr();
    method @NonNull public float[] getEpsilonSdr();
    method @NonNull public android.graphics.Bitmap getGainmapContents();
    method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public int getGainmapDirection();
    method @NonNull public float[] getGamma();
    method @NonNull public float getMinDisplayRatioForHdrTransition();
    method @NonNull public float[] getRatioMax();
    method @NonNull public float[] getRatioMin();
    method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public void setAlternativeImagePrimaries(@Nullable android.graphics.ColorSpace);
    method public void setDisplayRatioForFullHdr(@FloatRange(from=1.0f) float);
    method public void setEpsilonHdr(float, float, float);
    method public void setEpsilonSdr(float, float, float);
    method public void setGainmapContents(@NonNull android.graphics.Bitmap);
    method @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public void setGainmapDirection(int);
    method public void setGamma(float, float, float);
    method public void setMinDisplayRatioForHdrTransition(@FloatRange(from=1.0f) float);
    method public void setRatioMax(float, float, float);
    method 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;
    field @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public static final int GAINMAP_DIRECTION_HDR_TO_SDR = 1; // 0x1
    field @FlaggedApi("com.android.graphics.hwui.flags.iso_gainmap_apis") public static final int GAINMAP_DIRECTION_SDR_TO_HDR = 0; // 0x0
  }
  public class HardwareBufferRenderer implements java.lang.AutoCloseable {
+87 −6
Original line number Diff line number Diff line
@@ -18,7 +18,9 @@ package android.graphics;

import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;

@@ -26,6 +28,9 @@ import com.android.graphics.hwui.flags.Flags;

import libcore.util.NativeAllocationRegistry;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Gainmap represents a mechanism for augmenting an SDR image to produce an HDR one with variable
 * display adjustment capability. It is a combination of a set of metadata describing how to apply
@@ -83,6 +88,27 @@ import libcore.util.NativeAllocationRegistry;
 */
public final class Gainmap implements Parcelable {

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"GAINMAP_DIRECTION_"},
            value = {GAINMAP_DIRECTION_SDR_TO_HDR,
                     GAINMAP_DIRECTION_HDR_TO_SDR})
    public @interface GainmapDirection {}

    /**
     * The gainmap will be applied as if the base image were SDR, and fully applying the gainmap
     * results in an HDR image.
     */
    @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS)
    public static final int GAINMAP_DIRECTION_SDR_TO_HDR = 0;

    /**
     * The gainmap will be applied as if the base image were HDR, and fully applying the gainmap
     * results in an SDR image.
     */
    @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS)
    public static final int GAINMAP_DIRECTION_HDR_TO_SDR = 1;

    // Use a Holder to allow static initialization of Gainmap in the boot image.
    private static class NoImagePreloadHolder {
        public static final NativeAllocationRegistry sRegistry =
@@ -252,8 +278,9 @@ public final class Gainmap implements Parcelable {
    }

    /**
     * Sets the hdr/sdr ratio at which point the gainmap is fully applied.
     * @param max The hdr/sdr ratio at which the gainmap is fully applied. Must be >= 1.0f
     * Sets the hdr/sdr ratio at which point applying the gainmap results in an HDR rendition.
     * @param max The hdr/sdr ratio at which point applying the gainmap results in an HDR rendition.
     * Must be >= 1.0f
     */
    public void setDisplayRatioForFullHdr(@FloatRange(from = 1.0f) float max) {
        if (!Float.isFinite(max) || max < 1f) {
@@ -264,7 +291,7 @@ public final class Gainmap implements Parcelable {
    }

    /**
     * Gets the hdr/sdr ratio at which point the gainmap is fully applied.
     * Gets the hdr/sdr ratio at which point applying the gainmap results in an HDR rendition
     */
    @NonNull
    public float getDisplayRatioForFullHdr() {
@@ -272,8 +299,9 @@ public final class Gainmap implements Parcelable {
    }

    /**
     * Sets the hdr/sdr ratio below which only the SDR image is displayed.
     * @param min The minimum hdr/sdr ratio at which to begin applying the gainmap. Must be >= 1.0f
     * Sets the hdr/sdr ratio below which applying the gainmap results in an SDR rendition.
     * @param min The minimum hdr/sdr ratio at which point applying the gainmap results in an SDR
     * rendition. Must be >= 1.0f
     */
    public void setMinDisplayRatioForHdrTransition(@FloatRange(from = 1.0f) float min) {
        if (!Float.isFinite(min) || min < 1f) {
@@ -284,13 +312,62 @@ public final class Gainmap implements Parcelable {
    }

    /**
     * Gets the hdr/sdr ratio below which only the SDR image is displayed.
     * Gets the hdr/sdr ratio below which applying the gainmap results in an SDR rendition.
     */
    @NonNull
    public float getMinDisplayRatioForHdrTransition() {
        return nGetDisplayRatioSdr(mNativePtr);
    }

    /**
     * Sets the colorspace that the gainmap math should be applied in.
     * Only the primaries are what is relevant for applying the gainmap. The transfer and range
     * characteritics are ignored.
     *
     * If the supplied ColorSpace is null, then applying the gainmap will be done using the color
     * gamut of the base image.
     */
    @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS)
    public void setAlternativeImagePrimaries(@Nullable ColorSpace colorSpace) {
        long colorSpaceInstance = colorSpace == null ? 0 : colorSpace.getNativeInstance();
        nSetAlternativeColorSpace(mNativePtr, colorSpaceInstance);
    }

    /**
     * Gets the colorspace that the gainmap math should be applied in.
     * Only the primaries are what is relevant for applying the gainmap. The transfer and range
     * characteritics are ignored.
     *
     * If the returned ColorSpace is null, then applying the gainmap will be done using the color
     * gamut of the base image.
     */
    @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS)
    @Nullable
    public ColorSpace getAlternativeImagePrimaries() {
        return nGetAlternativeColorSpace(mNativePtr);
    }

    /**
     * Sets the direction that the gainmap math should be applied in.
     */
    @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS)
    public void setGainmapDirection(@GainmapDirection int direction) {
        if (direction != GAINMAP_DIRECTION_SDR_TO_HDR
                && direction != GAINMAP_DIRECTION_HDR_TO_SDR) {
            throw new IllegalArgumentException("Invalid gainmap direction: " + direction);
        }
        nSetDirection(mNativePtr, direction);
    }

    /**
     * Gets the direction that the gainmap math should be applied in.
     */
    @FlaggedApi(Flags.FLAG_ISO_GAINMAP_APIS)
    public @GainmapDirection int getGainmapDirection() {
        return nGetDirection(mNativePtr);
    }


    /**
     * No special parcel contents.
     */
@@ -361,6 +438,10 @@ public final class Gainmap implements Parcelable {

    private static native void nSetDisplayRatioSdr(long ptr, float min);
    private static native float nGetDisplayRatioSdr(long ptr);
    private static native void nSetAlternativeColorSpace(long ptr, long colorSpacePtr);
    private static native ColorSpace nGetAlternativeColorSpace(long ptr);
    private static native void nSetDirection(long ptr, int direction);
    private static native int nGetDirection(long ptr);
    private static native void nWriteGainmapToParcel(long ptr, Parcel dest);
    private static native void nReadGainmapFromParcel(long ptr, Parcel src);
}
+8 −0
Original line number Diff line number Diff line
@@ -121,3 +121,11 @@ flag {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "iso_gainmap_apis"
  is_exported: true
  namespace: "core_graphics"
  description: "APIs that expose gainmap metadata corresponding to those defined in ISO 21496-1"
  bug: "349357636"
}
+60 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

#include <Gainmap.h>

#include "SkColorType.h"
#include "SkGainmapInfo.h"

#ifdef __ANDROID__
#include <binder/Parcel.h>
#endif
@@ -36,6 +39,28 @@ static Gainmap* fromJava(jlong gainmap) {
    return reinterpret_cast<Gainmap*>(gainmap);
}

static SkGainmapInfo::BaseImageType baseImageTypeFromJava(jint direction) {
    switch (direction) {
        case 0:
            return SkGainmapInfo::BaseImageType::kSDR;
        case 1:
            return SkGainmapInfo::BaseImageType::kHDR;
        default:
            LOG_ALWAYS_FATAL("Unrecognized Gainmap direction: %d", direction);
    }
}

static jint baseImageTypeToJava(SkGainmapInfo::BaseImageType type) {
    switch (type) {
        case SkGainmapInfo::BaseImageType::kSDR:
            return 0;
        case SkGainmapInfo::BaseImageType::kHDR:
            return 1;
        default:
            LOG_ALWAYS_FATAL("Unrecognized base image: %d", type);
    }
}

static int getCreateFlags(const sk_sp<Bitmap>& bitmap) {
    int flags = 0;
    if (bitmap->info().alphaType() == kPremul_SkAlphaType) {
@@ -169,6 +194,36 @@ static jfloat Gainmap_getDisplayRatioSdr(JNIEnv*, jobject, jlong gainmapPtr) {
    return fromJava(gainmapPtr)->info.fDisplayRatioSdr;
}

static void Gainmap_setAlternativeColorSpace(JNIEnv*, jobject, jlong gainmapPtr,
                                             jlong colorSpacePtr) {
    auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr);
    fromJava(gainmapPtr)->info.fGainmapMathColorSpace = colorSpace;
}

static jobject Gainmap_getAlternativeColorSpace(JNIEnv* env, jobject, jlong gainmapPtr) {
    const auto javaGainmap = fromJava(gainmapPtr);
    auto colorSpace = javaGainmap->info.fGainmapMathColorSpace.get();
    if (colorSpace == nullptr) {
        return nullptr;
    }

    auto colorType = javaGainmap->bitmap->colorType();
    // A8 bitmaps don't support colorspaces, but an alternative colorspace is
    // still valid for configuring the gainmap math, so use RGBA8888 instead.
    if (colorType == kAlpha_8_SkColorType) {
        colorType = kRGBA_8888_SkColorType;
    }
    return GraphicsJNI::getColorSpace(env, colorSpace, colorType);
}

static void Gainmap_setDirection(JNIEnv*, jobject, jlong gainmapPtr, jint direction) {
    fromJava(gainmapPtr)->info.fBaseImageType = baseImageTypeFromJava(direction);
}

static jint Gainmap_getDirection(JNIEnv* env, jobject, jlong gainmapPtr) {
    return baseImageTypeToJava(fromJava(gainmapPtr)->info.fBaseImageType);
}

// ----------------------------------------------------------------------------
// Serialization
// ----------------------------------------------------------------------------
@@ -260,6 +315,11 @@ static const JNINativeMethod gGainmapMethods[] = {
        {"nGetDisplayRatioHdr", "(J)F", (void*)Gainmap_getDisplayRatioHdr},
        {"nSetDisplayRatioSdr", "(JF)V", (void*)Gainmap_setDisplayRatioSdr},
        {"nGetDisplayRatioSdr", "(J)F", (void*)Gainmap_getDisplayRatioSdr},
        {"nSetAlternativeColorSpace", "(JJ)V", (void*)Gainmap_setAlternativeColorSpace},
        {"nGetAlternativeColorSpace", "(J)Landroid/graphics/ColorSpace;",
         (void*)Gainmap_getAlternativeColorSpace},
        {"nSetDirection", "(JI)V", (void*)Gainmap_setDirection},
        {"nGetDirection", "(J)I", (void*)Gainmap_getDirection},
        {"nWriteGainmapToParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_writeToParcel},
        {"nReadGainmapFromParcel", "(JLandroid/os/Parcel;)V", (void*)Gainmap_readFromParcel},
};