Loading core/api/current.txt +25 −0 Original line number Diff line number Diff line Loading @@ -18826,6 +18826,19 @@ package android.hardware { field public static final int TRANSFER_UNSPECIFIED = 0; // 0x0 } @FlaggedApi("android.hardware.flags.luts_api") public final class DisplayLuts { ctor @FlaggedApi("android.hardware.flags.luts_api") public DisplayLuts(); method @FlaggedApi("android.hardware.flags.luts_api") public void set(@NonNull android.hardware.DisplayLuts.Entry); method @FlaggedApi("android.hardware.flags.luts_api") public void set(@NonNull android.hardware.DisplayLuts.Entry, @NonNull android.hardware.DisplayLuts.Entry); } @FlaggedApi("android.hardware.flags.luts_api") public static class DisplayLuts.Entry { ctor @FlaggedApi("android.hardware.flags.luts_api") public DisplayLuts.Entry(@NonNull float[], int, int); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public float[] getBuffer(); method @FlaggedApi("android.hardware.flags.luts_api") public int getDimension(); method @FlaggedApi("android.hardware.flags.luts_api") public int getSamplingKey(); } public class GeomagneticField { ctor public GeomagneticField(float, float, float, long); method public float getDeclination(); Loading Loading @@ -18887,8 +18900,19 @@ package android.hardware { field @FlaggedApi("android.media.codec.p210_format_support") public static final int YCBCR_P210 = 60; // 0x3c } @FlaggedApi("android.hardware.flags.luts_api") public final class LutProperties { method @FlaggedApi("android.hardware.flags.luts_api") public int getDimension(); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public int[] getSamplingKeys(); method @FlaggedApi("android.hardware.flags.luts_api") public int getSize(); field @FlaggedApi("android.hardware.flags.luts_api") public static final int ONE_DIMENSION = 1; // 0x1 field @FlaggedApi("android.hardware.flags.luts_api") public static final int SAMPLING_KEY_MAX_RGB = 1; // 0x1 field @FlaggedApi("android.hardware.flags.luts_api") public static final int SAMPLING_KEY_RGB = 0; // 0x0 field @FlaggedApi("android.hardware.flags.luts_api") public static final int THREE_DIMENSION = 3; // 0x3 } @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public final class OverlayProperties implements android.os.Parcelable { method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public int describeContents(); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public android.hardware.LutProperties[] getLutProperties(); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public boolean isCombinationSupported(int, int); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public boolean isMixedColorSpacesSupported(); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public void writeToParcel(@NonNull android.os.Parcel, int); Loading Loading @@ -53173,6 +53197,7 @@ package android.view { method @FlaggedApi("com.android.window.flags.sdk_desired_present_time") @NonNull public android.view.SurfaceControl.Transaction setFrameTimeline(long); method @Deprecated @NonNull public android.view.SurfaceControl.Transaction setGeometry(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, int); method @NonNull public android.view.SurfaceControl.Transaction setLayer(@NonNull android.view.SurfaceControl, @IntRange(from=java.lang.Integer.MIN_VALUE, to=java.lang.Integer.MAX_VALUE) int); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public android.view.SurfaceControl.Transaction setLuts(@NonNull android.view.SurfaceControl, @Nullable android.hardware.DisplayLuts); method @NonNull public android.view.SurfaceControl.Transaction setOpaque(@NonNull android.view.SurfaceControl, boolean); method @NonNull public android.view.SurfaceControl.Transaction setPosition(@NonNull android.view.SurfaceControl, float, float); method @NonNull public android.view.SurfaceControl.Transaction setScale(@NonNull android.view.SurfaceControl, float, float); core/java/android/hardware/DisplayLuts.java +232 −54 Original line number Diff line number Diff line Loading @@ -16,116 +16,294 @@ package android.hardware; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.hardware.flags.Flags; import android.util.IntArray; import java.util.ArrayList; import java.util.List; /** * @hide * DisplayLuts provides the developers to apply Lookup Tables (Luts) to a * {@link android.view.SurfaceControl}. Luts provides ways to control tonemapping * for specific content. * * The general flow is as follows: * <p> * <img src="{@docRoot}reference/android/images/graphics/DisplayLuts.png" /> * <figcaption style="text-align: center;">DisplayLuts flow</figcaption> * </p> * * @see LutProperties */ @FlaggedApi(Flags.FLAG_LUTS_API) public final class DisplayLuts { private ArrayList<Entry> mEntries; private IntArray mOffsets; private int mTotalLength; private List<float[]> mLutBuffers; private IntArray mLutDimensions; private IntArray mLutSizes; private IntArray mLutSamplingKeys; private static final int LUT_LENGTH_LIMIT = 100000; /** * Create a {@link DisplayLuts} instance. */ @FlaggedApi(Flags.FLAG_LUTS_API) public DisplayLuts() { mEntries = new ArrayList<>(); mOffsets = new IntArray(); mTotalLength = 0; mLutBuffers = new ArrayList<>(); mLutDimensions = new IntArray(); mLutSizes = new IntArray(); mLutSamplingKeys = new IntArray(); } @FlaggedApi(Flags.FLAG_LUTS_API) public static class Entry { private float[] mBuffer; private @LutProperties.Dimension int mDimension; private int mSize; private @LutProperties.SamplingKey int mSamplingKey; private static final int LUT_LENGTH_LIMIT = 100000; /** * Add the lut to be applied. * Create a Lut entry. * * @param buffer * @param dimension either 1D or 3D * @param size * @param samplingKey */ public void addLut(@NonNull float[] buffer, @LutProperties.Dimension int dimension, int size, @LutProperties.SamplingKey int samplingKey) { int lutLength = 0; if (dimension == LutProperties.ONE_DIMENSION) { lutLength = size; } else if (dimension == LutProperties.THREE_DIMENSION) { lutLength = size * size * size; } else { clear(); throw new IllegalArgumentException("The dimension is either 1D or 3D!"); * <p> * Noted that 1D Lut(s) are treated as gain curves. * For 3D Lut(s), 3D Lut(s) are used for direct color manipulations. * The values of 3D Lut(s) data should be normalized to the range {@code 0.0} * to {@code 1.0}, inclusive. And 3D Lut(s) data is organized in the order of * R, G, B channels. * * @param buffer The raw lut data * @param dimension Either 1D or 3D * @param samplingKey The sampling kay used for the Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public Entry(@NonNull float[] buffer, @LutProperties.Dimension int dimension, @LutProperties.SamplingKey int samplingKey) { if (buffer == null || buffer.length < 1) { throw new IllegalArgumentException("The buffer cannot be empty!"); } if (lutLength >= LUT_LENGTH_LIMIT) { clear(); if (buffer.length >= LUT_LENGTH_LIMIT) { throw new IllegalArgumentException("The lut length is too big to handle!"); } mOffsets.add(mTotalLength); mTotalLength += lutLength; if (dimension != LutProperties.ONE_DIMENSION && dimension != LutProperties.THREE_DIMENSION) { throw new IllegalArgumentException("The dimension should be either 1D or 3D!"); } if (dimension == LutProperties.THREE_DIMENSION) { if (buffer.length <= 3) { throw new IllegalArgumentException( "The 3d lut size of each dimension should be over 1!"); } int lengthPerChannel = buffer.length; if (lengthPerChannel % 3 != 0) { throw new IllegalArgumentException( "The lut buffer of 3dlut should have 3 channels!"); } lengthPerChannel /= 3; double size = Math.cbrt(lengthPerChannel); if (size == (int) size) { mSize = (int) size; } else { throw new IllegalArgumentException( "Cannot get the cube root of the 3d lut buffer!"); } } else { mSize = buffer.length; } mBuffer = buffer; mDimension = dimension; mSamplingKey = samplingKey; } /** * @return the dimension of the lut entry */ @FlaggedApi(Flags.FLAG_LUTS_API) public int getDimension() { return mDimension; } /** * @return the size of the lut for each dimension * @hide */ public int getSize() { return mSize; } /** * @return the lut raw data of the lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public @NonNull float[] getBuffer() { return mBuffer; } /** * @return the sampling key used by the lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public int getSamplingKey() { return mSamplingKey; } mLutBuffers.add(buffer); mLutDimensions.add(dimension); mLutSizes.add(size); mLutSamplingKeys.add(samplingKey); @Override public String toString() { return "Entry{" + "dimension=" + DisplayLuts.Entry.dimensionToString(getDimension()) + ", size(each dimension)=" + getSize() + ", samplingKey=" + samplingKeyToString(getSamplingKey()) + "}"; } private static String dimensionToString(int dimension) { switch(dimension) { case LutProperties.ONE_DIMENSION: return "ONE_DIMENSION"; case LutProperties.THREE_DIMENSION: return "THREE_DIMENSION"; default: return ""; } } private static String samplingKeyToString(int key) { switch(key) { case LutProperties.SAMPLING_KEY_RGB: return "SAMPLING_KEY_RGB"; case LutProperties.SAMPLING_KEY_MAX_RGB: return "SAMPLING_KEY_MAX_RGB"; default: return ""; } } } @Override public String toString() { StringBuilder sb = new StringBuilder("DisplayLuts{"); sb.append("\n"); for (DisplayLuts.Entry entry: mEntries) { sb.append(entry.toString()); sb.append("\n"); } sb.append("}"); return sb.toString(); } private void addEntry(Entry entry) { mEntries.add(entry); mOffsets.add(mTotalLength); mTotalLength += entry.getBuffer().length; } private void clear() { mTotalLength = 0; mOffsets.clear(); mLutBuffers.clear(); mLutDimensions.clear(); mLutSamplingKeys.clear(); mTotalLength = 0; mEntries.clear(); } /** * @return the array of Lut buffers * Set a Lut to be applied. * * <p>Use either this or {@link #set(Entry, Entry)}. The function will * replace any previously set lut(s).</p> * * @param entry Either an 1D Lut or a 3D Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public void set(@NonNull Entry entry) { if (entry == null) { throw new IllegalArgumentException("The entry is null!"); } clear(); addEntry(entry); } /** * Set Luts in order to be applied. * * <p> An 1D Lut and 3D Lut will be applied in order. Use either this or * {@link #set(Entry)}. The function will replace any previously set lut(s)</p> * * @param first An 1D Lut * @param second A 3D Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public void set(@NonNull Entry first, @NonNull Entry second) { if (first == null || second == null) { throw new IllegalArgumentException("The entry is null!"); } if (first.getDimension() != LutProperties.ONE_DIMENSION || second.getDimension() != LutProperties.THREE_DIMENSION) { throw new IllegalArgumentException("The entries should be 1D and 3D in order!"); } clear(); addEntry(first); addEntry(second); } /** * @hide */ public boolean valid() { return mEntries.size() > 0; } /** * @hide */ public float[] getLutBuffers() { float[] buffer = new float[mTotalLength]; for (int i = 0; i < mLutBuffers.size(); i++) { float[] lutBuffer = mLutBuffers.get(i); for (int i = 0; i < mEntries.size(); i++) { float[] lutBuffer = mEntries.get(i).getBuffer(); System.arraycopy(lutBuffer, 0, buffer, mOffsets.get(i), lutBuffer.length); } return buffer; } /** * @return the starting point of each lut memory region of the lut buffer * @hide */ public int[] getOffsets() { return mOffsets.toArray(); } /** * @return the array of Lut size * @hide */ public int[] getLutSizes() { return mLutSizes.toArray(); int[] sizes = new int[mEntries.size()]; for (int i = 0; i < mEntries.size(); i++) { sizes[i] = mEntries.get(i).getSize(); } return sizes; } /** * @return the array of Lut dimension * @hide */ public int[] getLutDimensions() { return mLutDimensions.toArray(); int[] dimensions = new int[mEntries.size()]; for (int i = 0; i < mEntries.size(); i++) { dimensions[i] = mEntries.get(i).getDimension(); } return dimensions; } /** * @return the array of sampling key * @hide */ public int[] getLutSamplingKeys() { return mLutSamplingKeys.toArray(); int[] samplingKeys = new int[mEntries.size()]; for (int i = 0; i < mEntries.size(); i++) { samplingKeys[i] = mEntries.get(i).getSamplingKey(); } return samplingKeys; } } core/java/android/hardware/LutProperties.java +22 −5 Original line number Diff line number Diff line Loading @@ -16,23 +16,31 @@ package android.hardware; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.hardware.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Lut properties class. * Provides Lut properties of the device. * * A Lut (Look-Up Table) is a pre-calculated table for color transformation. * * @hide * <p> * A Lut (Look-Up Table) is a pre-calculated table for color correction. * Applications may be interested in the Lut properties exposed by * this class to determine if the Lut(s) they select using * {@link android.view.SurfaceControl.Transaction#setLuts} are by the HWC. * </p> */ @FlaggedApi(Flags.FLAG_LUTS_API) public final class LutProperties { private final @Dimension int mDimension; private final int mSize; private final @SamplingKey int[] mSamplingKeys; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"SAMPLING_KEY_"}, value = { SAMPLING_KEY_RGB, Loading @@ -42,11 +50,14 @@ public final class LutProperties { } /** use r,g,b channel as the gain value of a Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int SAMPLING_KEY_RGB = 0; /** use max of r,g,b channel as the gain value of a Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int SAMPLING_KEY_MAX_RGB = 1; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { ONE_DIMENSION, Loading @@ -56,18 +67,22 @@ public final class LutProperties { } /** The Lut is one dimensional */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int ONE_DIMENSION = 1; /** The Lut is three dimensional */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int THREE_DIMENSION = 3; @FlaggedApi(Flags.FLAG_LUTS_API) public @Dimension int getDimension() { return mDimension; } /** * @return the size of the Lut. * @return the size of the Lut for each dimension */ @FlaggedApi(Flags.FLAG_LUTS_API) public int getSize() { return mSize; } Loading @@ -75,6 +90,8 @@ public final class LutProperties { /** * @return the list of sampling keys */ @FlaggedApi(Flags.FLAG_LUTS_API) @NonNull public @SamplingKey int[] getSamplingKeys() { if (mSamplingKeys.length == 0) { throw new IllegalStateException("no sampling key!"); Loading core/java/android/hardware/OverlayProperties.java +5 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.hardware; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.SuppressLint; import android.hardware.flags.Flags; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -72,9 +73,11 @@ public final class OverlayProperties implements Parcelable { } /** * Gets the lut properties of the display. * @hide * Returns the lut properties of the device. */ @FlaggedApi(Flags.FLAG_LUTS_API) @SuppressLint("ArrayReturn") @NonNull public LutProperties[] getLutProperties() { if (mNativeObject == 0) { return null; Loading core/java/android/hardware/flags/overlayproperties_flags.aconfig→core/java/android/hardware/flags/flags.aconfig +9 −0 Original line number Diff line number Diff line package: "android.hardware.flags" container: "system" flag { name: "luts_api" is_exported: true is_fixed_read_only: true namespace: "core_graphics" description: "public Luts related Apis" bug: "349667978" } flag { name: "overlayproperties_class_api" is_exported: true Loading Loading
core/api/current.txt +25 −0 Original line number Diff line number Diff line Loading @@ -18826,6 +18826,19 @@ package android.hardware { field public static final int TRANSFER_UNSPECIFIED = 0; // 0x0 } @FlaggedApi("android.hardware.flags.luts_api") public final class DisplayLuts { ctor @FlaggedApi("android.hardware.flags.luts_api") public DisplayLuts(); method @FlaggedApi("android.hardware.flags.luts_api") public void set(@NonNull android.hardware.DisplayLuts.Entry); method @FlaggedApi("android.hardware.flags.luts_api") public void set(@NonNull android.hardware.DisplayLuts.Entry, @NonNull android.hardware.DisplayLuts.Entry); } @FlaggedApi("android.hardware.flags.luts_api") public static class DisplayLuts.Entry { ctor @FlaggedApi("android.hardware.flags.luts_api") public DisplayLuts.Entry(@NonNull float[], int, int); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public float[] getBuffer(); method @FlaggedApi("android.hardware.flags.luts_api") public int getDimension(); method @FlaggedApi("android.hardware.flags.luts_api") public int getSamplingKey(); } public class GeomagneticField { ctor public GeomagneticField(float, float, float, long); method public float getDeclination(); Loading Loading @@ -18887,8 +18900,19 @@ package android.hardware { field @FlaggedApi("android.media.codec.p210_format_support") public static final int YCBCR_P210 = 60; // 0x3c } @FlaggedApi("android.hardware.flags.luts_api") public final class LutProperties { method @FlaggedApi("android.hardware.flags.luts_api") public int getDimension(); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public int[] getSamplingKeys(); method @FlaggedApi("android.hardware.flags.luts_api") public int getSize(); field @FlaggedApi("android.hardware.flags.luts_api") public static final int ONE_DIMENSION = 1; // 0x1 field @FlaggedApi("android.hardware.flags.luts_api") public static final int SAMPLING_KEY_MAX_RGB = 1; // 0x1 field @FlaggedApi("android.hardware.flags.luts_api") public static final int SAMPLING_KEY_RGB = 0; // 0x0 field @FlaggedApi("android.hardware.flags.luts_api") public static final int THREE_DIMENSION = 3; // 0x3 } @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public final class OverlayProperties implements android.os.Parcelable { method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public int describeContents(); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public android.hardware.LutProperties[] getLutProperties(); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public boolean isCombinationSupported(int, int); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public boolean isMixedColorSpacesSupported(); method @FlaggedApi("android.hardware.flags.overlayproperties_class_api") public void writeToParcel(@NonNull android.os.Parcel, int); Loading Loading @@ -53173,6 +53197,7 @@ package android.view { method @FlaggedApi("com.android.window.flags.sdk_desired_present_time") @NonNull public android.view.SurfaceControl.Transaction setFrameTimeline(long); method @Deprecated @NonNull public android.view.SurfaceControl.Transaction setGeometry(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, int); method @NonNull public android.view.SurfaceControl.Transaction setLayer(@NonNull android.view.SurfaceControl, @IntRange(from=java.lang.Integer.MIN_VALUE, to=java.lang.Integer.MAX_VALUE) int); method @FlaggedApi("android.hardware.flags.luts_api") @NonNull public android.view.SurfaceControl.Transaction setLuts(@NonNull android.view.SurfaceControl, @Nullable android.hardware.DisplayLuts); method @NonNull public android.view.SurfaceControl.Transaction setOpaque(@NonNull android.view.SurfaceControl, boolean); method @NonNull public android.view.SurfaceControl.Transaction setPosition(@NonNull android.view.SurfaceControl, float, float); method @NonNull public android.view.SurfaceControl.Transaction setScale(@NonNull android.view.SurfaceControl, float, float);
core/java/android/hardware/DisplayLuts.java +232 −54 Original line number Diff line number Diff line Loading @@ -16,116 +16,294 @@ package android.hardware; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.hardware.flags.Flags; import android.util.IntArray; import java.util.ArrayList; import java.util.List; /** * @hide * DisplayLuts provides the developers to apply Lookup Tables (Luts) to a * {@link android.view.SurfaceControl}. Luts provides ways to control tonemapping * for specific content. * * The general flow is as follows: * <p> * <img src="{@docRoot}reference/android/images/graphics/DisplayLuts.png" /> * <figcaption style="text-align: center;">DisplayLuts flow</figcaption> * </p> * * @see LutProperties */ @FlaggedApi(Flags.FLAG_LUTS_API) public final class DisplayLuts { private ArrayList<Entry> mEntries; private IntArray mOffsets; private int mTotalLength; private List<float[]> mLutBuffers; private IntArray mLutDimensions; private IntArray mLutSizes; private IntArray mLutSamplingKeys; private static final int LUT_LENGTH_LIMIT = 100000; /** * Create a {@link DisplayLuts} instance. */ @FlaggedApi(Flags.FLAG_LUTS_API) public DisplayLuts() { mEntries = new ArrayList<>(); mOffsets = new IntArray(); mTotalLength = 0; mLutBuffers = new ArrayList<>(); mLutDimensions = new IntArray(); mLutSizes = new IntArray(); mLutSamplingKeys = new IntArray(); } @FlaggedApi(Flags.FLAG_LUTS_API) public static class Entry { private float[] mBuffer; private @LutProperties.Dimension int mDimension; private int mSize; private @LutProperties.SamplingKey int mSamplingKey; private static final int LUT_LENGTH_LIMIT = 100000; /** * Add the lut to be applied. * Create a Lut entry. * * @param buffer * @param dimension either 1D or 3D * @param size * @param samplingKey */ public void addLut(@NonNull float[] buffer, @LutProperties.Dimension int dimension, int size, @LutProperties.SamplingKey int samplingKey) { int lutLength = 0; if (dimension == LutProperties.ONE_DIMENSION) { lutLength = size; } else if (dimension == LutProperties.THREE_DIMENSION) { lutLength = size * size * size; } else { clear(); throw new IllegalArgumentException("The dimension is either 1D or 3D!"); * <p> * Noted that 1D Lut(s) are treated as gain curves. * For 3D Lut(s), 3D Lut(s) are used for direct color manipulations. * The values of 3D Lut(s) data should be normalized to the range {@code 0.0} * to {@code 1.0}, inclusive. And 3D Lut(s) data is organized in the order of * R, G, B channels. * * @param buffer The raw lut data * @param dimension Either 1D or 3D * @param samplingKey The sampling kay used for the Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public Entry(@NonNull float[] buffer, @LutProperties.Dimension int dimension, @LutProperties.SamplingKey int samplingKey) { if (buffer == null || buffer.length < 1) { throw new IllegalArgumentException("The buffer cannot be empty!"); } if (lutLength >= LUT_LENGTH_LIMIT) { clear(); if (buffer.length >= LUT_LENGTH_LIMIT) { throw new IllegalArgumentException("The lut length is too big to handle!"); } mOffsets.add(mTotalLength); mTotalLength += lutLength; if (dimension != LutProperties.ONE_DIMENSION && dimension != LutProperties.THREE_DIMENSION) { throw new IllegalArgumentException("The dimension should be either 1D or 3D!"); } if (dimension == LutProperties.THREE_DIMENSION) { if (buffer.length <= 3) { throw new IllegalArgumentException( "The 3d lut size of each dimension should be over 1!"); } int lengthPerChannel = buffer.length; if (lengthPerChannel % 3 != 0) { throw new IllegalArgumentException( "The lut buffer of 3dlut should have 3 channels!"); } lengthPerChannel /= 3; double size = Math.cbrt(lengthPerChannel); if (size == (int) size) { mSize = (int) size; } else { throw new IllegalArgumentException( "Cannot get the cube root of the 3d lut buffer!"); } } else { mSize = buffer.length; } mBuffer = buffer; mDimension = dimension; mSamplingKey = samplingKey; } /** * @return the dimension of the lut entry */ @FlaggedApi(Flags.FLAG_LUTS_API) public int getDimension() { return mDimension; } /** * @return the size of the lut for each dimension * @hide */ public int getSize() { return mSize; } /** * @return the lut raw data of the lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public @NonNull float[] getBuffer() { return mBuffer; } /** * @return the sampling key used by the lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public int getSamplingKey() { return mSamplingKey; } mLutBuffers.add(buffer); mLutDimensions.add(dimension); mLutSizes.add(size); mLutSamplingKeys.add(samplingKey); @Override public String toString() { return "Entry{" + "dimension=" + DisplayLuts.Entry.dimensionToString(getDimension()) + ", size(each dimension)=" + getSize() + ", samplingKey=" + samplingKeyToString(getSamplingKey()) + "}"; } private static String dimensionToString(int dimension) { switch(dimension) { case LutProperties.ONE_DIMENSION: return "ONE_DIMENSION"; case LutProperties.THREE_DIMENSION: return "THREE_DIMENSION"; default: return ""; } } private static String samplingKeyToString(int key) { switch(key) { case LutProperties.SAMPLING_KEY_RGB: return "SAMPLING_KEY_RGB"; case LutProperties.SAMPLING_KEY_MAX_RGB: return "SAMPLING_KEY_MAX_RGB"; default: return ""; } } } @Override public String toString() { StringBuilder sb = new StringBuilder("DisplayLuts{"); sb.append("\n"); for (DisplayLuts.Entry entry: mEntries) { sb.append(entry.toString()); sb.append("\n"); } sb.append("}"); return sb.toString(); } private void addEntry(Entry entry) { mEntries.add(entry); mOffsets.add(mTotalLength); mTotalLength += entry.getBuffer().length; } private void clear() { mTotalLength = 0; mOffsets.clear(); mLutBuffers.clear(); mLutDimensions.clear(); mLutSamplingKeys.clear(); mTotalLength = 0; mEntries.clear(); } /** * @return the array of Lut buffers * Set a Lut to be applied. * * <p>Use either this or {@link #set(Entry, Entry)}. The function will * replace any previously set lut(s).</p> * * @param entry Either an 1D Lut or a 3D Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public void set(@NonNull Entry entry) { if (entry == null) { throw new IllegalArgumentException("The entry is null!"); } clear(); addEntry(entry); } /** * Set Luts in order to be applied. * * <p> An 1D Lut and 3D Lut will be applied in order. Use either this or * {@link #set(Entry)}. The function will replace any previously set lut(s)</p> * * @param first An 1D Lut * @param second A 3D Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public void set(@NonNull Entry first, @NonNull Entry second) { if (first == null || second == null) { throw new IllegalArgumentException("The entry is null!"); } if (first.getDimension() != LutProperties.ONE_DIMENSION || second.getDimension() != LutProperties.THREE_DIMENSION) { throw new IllegalArgumentException("The entries should be 1D and 3D in order!"); } clear(); addEntry(first); addEntry(second); } /** * @hide */ public boolean valid() { return mEntries.size() > 0; } /** * @hide */ public float[] getLutBuffers() { float[] buffer = new float[mTotalLength]; for (int i = 0; i < mLutBuffers.size(); i++) { float[] lutBuffer = mLutBuffers.get(i); for (int i = 0; i < mEntries.size(); i++) { float[] lutBuffer = mEntries.get(i).getBuffer(); System.arraycopy(lutBuffer, 0, buffer, mOffsets.get(i), lutBuffer.length); } return buffer; } /** * @return the starting point of each lut memory region of the lut buffer * @hide */ public int[] getOffsets() { return mOffsets.toArray(); } /** * @return the array of Lut size * @hide */ public int[] getLutSizes() { return mLutSizes.toArray(); int[] sizes = new int[mEntries.size()]; for (int i = 0; i < mEntries.size(); i++) { sizes[i] = mEntries.get(i).getSize(); } return sizes; } /** * @return the array of Lut dimension * @hide */ public int[] getLutDimensions() { return mLutDimensions.toArray(); int[] dimensions = new int[mEntries.size()]; for (int i = 0; i < mEntries.size(); i++) { dimensions[i] = mEntries.get(i).getDimension(); } return dimensions; } /** * @return the array of sampling key * @hide */ public int[] getLutSamplingKeys() { return mLutSamplingKeys.toArray(); int[] samplingKeys = new int[mEntries.size()]; for (int i = 0; i < mEntries.size(); i++) { samplingKeys[i] = mEntries.get(i).getSamplingKey(); } return samplingKeys; } }
core/java/android/hardware/LutProperties.java +22 −5 Original line number Diff line number Diff line Loading @@ -16,23 +16,31 @@ package android.hardware; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.hardware.flags.Flags; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Lut properties class. * Provides Lut properties of the device. * * A Lut (Look-Up Table) is a pre-calculated table for color transformation. * * @hide * <p> * A Lut (Look-Up Table) is a pre-calculated table for color correction. * Applications may be interested in the Lut properties exposed by * this class to determine if the Lut(s) they select using * {@link android.view.SurfaceControl.Transaction#setLuts} are by the HWC. * </p> */ @FlaggedApi(Flags.FLAG_LUTS_API) public final class LutProperties { private final @Dimension int mDimension; private final int mSize; private final @SamplingKey int[] mSamplingKeys; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"SAMPLING_KEY_"}, value = { SAMPLING_KEY_RGB, Loading @@ -42,11 +50,14 @@ public final class LutProperties { } /** use r,g,b channel as the gain value of a Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int SAMPLING_KEY_RGB = 0; /** use max of r,g,b channel as the gain value of a Lut */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int SAMPLING_KEY_MAX_RGB = 1; /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(value = { ONE_DIMENSION, Loading @@ -56,18 +67,22 @@ public final class LutProperties { } /** The Lut is one dimensional */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int ONE_DIMENSION = 1; /** The Lut is three dimensional */ @FlaggedApi(Flags.FLAG_LUTS_API) public static final int THREE_DIMENSION = 3; @FlaggedApi(Flags.FLAG_LUTS_API) public @Dimension int getDimension() { return mDimension; } /** * @return the size of the Lut. * @return the size of the Lut for each dimension */ @FlaggedApi(Flags.FLAG_LUTS_API) public int getSize() { return mSize; } Loading @@ -75,6 +90,8 @@ public final class LutProperties { /** * @return the list of sampling keys */ @FlaggedApi(Flags.FLAG_LUTS_API) @NonNull public @SamplingKey int[] getSamplingKeys() { if (mSamplingKeys.length == 0) { throw new IllegalStateException("no sampling key!"); Loading
core/java/android/hardware/OverlayProperties.java +5 −2 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.hardware; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.SuppressLint; import android.hardware.flags.Flags; import android.os.Parcel; import android.os.Parcelable; Loading Loading @@ -72,9 +73,11 @@ public final class OverlayProperties implements Parcelable { } /** * Gets the lut properties of the display. * @hide * Returns the lut properties of the device. */ @FlaggedApi(Flags.FLAG_LUTS_API) @SuppressLint("ArrayReturn") @NonNull public LutProperties[] getLutProperties() { if (mNativeObject == 0) { return null; Loading
core/java/android/hardware/flags/overlayproperties_flags.aconfig→core/java/android/hardware/flags/flags.aconfig +9 −0 Original line number Diff line number Diff line package: "android.hardware.flags" container: "system" flag { name: "luts_api" is_exported: true is_fixed_read_only: true namespace: "core_graphics" description: "public Luts related Apis" bug: "349667978" } flag { name: "overlayproperties_class_api" is_exported: true Loading