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

Commit 4fff1aef authored by Alec Mouri's avatar Alec Mouri Committed by Android (Google) Code Review
Browse files

Merge "Add support for ISO gainmap metadata" into main

parents fa4edb62 d7e90a61
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -16126,24 +16126,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},
};