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

Commit a815c63d authored by Sally Qi's avatar Sally Qi Committed by Android (Google) Code Review
Browse files

Merge "[Lut API] Introduce LUT java interface." into main

parents 6f289bec b8f42c5d
Loading
Loading
Loading
Loading
+131 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

package android.hardware;

import android.annotation.NonNull;
import android.util.IntArray;

import java.util.ArrayList;
import java.util.List;

/**
 * @hide
 */
public final class DisplayLuts {
    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;

    public DisplayLuts() {
        mOffsets = new IntArray();
        mTotalLength = 0;

        mLutBuffers = new ArrayList<>();
        mLutDimensions = new IntArray();
        mLutSizes = new IntArray();
        mLutSamplingKeys = new IntArray();
    }

    /**
     * Add the lut to be applied.
     *
     * @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!");
        }

        if (lutLength >= LUT_LENGTH_LIMIT) {
            clear();
            throw new IllegalArgumentException("The lut length is too big to handle!");
        }

        mOffsets.add(mTotalLength);
        mTotalLength += lutLength;

        mLutBuffers.add(buffer);
        mLutDimensions.add(dimension);
        mLutSizes.add(size);
        mLutSamplingKeys.add(samplingKey);
    }

    private void clear() {
        mTotalLength = 0;
        mOffsets.clear();
        mLutBuffers.clear();
        mLutDimensions.clear();
        mLutSamplingKeys.clear();
    }

    /**
     * @return the array of Lut buffers
     */
    public float[] getLutBuffers() {
        float[] buffer = new float[mTotalLength];

        for (int i = 0; i < mLutBuffers.size(); i++) {
            float[] lutBuffer = mLutBuffers.get(i);
            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
     */
    public int[] getOffsets() {
        return mOffsets.toArray();
    }

    /**
     * @return the array of Lut size
     */
    public int[] getLutSizes() {
        return mLutSizes.toArray();
    }

    /**
     * @return the array of Lut dimension
     */
    public int[] getLutDimensions() {
        return mLutDimensions.toArray();
    }

    /**
     * @return the array of sampling key
     */
    public int[] getLutSamplingKeys() {
        return mLutSamplingKeys.toArray();
    }
}
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.
 */

package android.hardware;

import android.annotation.IntDef;

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

/**
 * Lut properties class.
 *
 * A Lut (Look-Up Table) is a pre-calculated table for color transformation.
 *
 * @hide
 */
public final class LutProperties {
    private final @Dimension int mDimension;
    private final long mSize;
    private final @SamplingKey int[] mSamplingKeys;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = {"SAMPLING_KEY_"}, value = {
        SAMPLING_KEY_RGB,
        SAMPLING_KEY_MAX_RGB
    })
    public @interface SamplingKey {
    }

    /** use r,g,b channel as the gain value of a Lut */
    public static final int SAMPLING_KEY_RGB = 0;

    /** use max of r,g,b channel as the gain value of a Lut */
    public static final int SAMPLING_KEY_MAX_RGB = 1;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(value = {
        ONE_DIMENSION,
        THREE_DIMENSION
    })
    public @interface Dimension {
    }

    /** The Lut is one dimensional */
    public static final int ONE_DIMENSION = 1;

    /** The Lut is three dimensional */
    public static final int THREE_DIMENSION = 3;

    public @Dimension int getDimension() {
        return mDimension;
    }

    /**
     * @return the size of the Lut.
     */
    public long getSize() {
        return mSize;
    }

    /**
     * @return the list of sampling keys
     */
    public @SamplingKey int[] getSamplingKeys() {
        if (mSamplingKeys.length == 0) {
            throw new IllegalStateException("no sampling key!");
        }
        return mSamplingKeys;
    }

    /* use in the native code */
    private LutProperties(@Dimension int dimension, long size, @SamplingKey int[] samplingKeys) {
        if (dimension != ONE_DIMENSION || dimension != THREE_DIMENSION) {
            throw new IllegalArgumentException("The dimension is either 1 or 3!");
        }
        mDimension = dimension;
        mSize = size;
        mSamplingKeys = samplingKeys;
    }
}
+18 −1
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ public final class OverlayProperties implements Parcelable {
    // Invoked on destruction
    private Runnable mCloser;

    private LutProperties[] mLutProperties;

    private OverlayProperties(long nativeObject) {
        if (nativeObject != 0) {
            mCloser = sRegistry.registerNativeAllocation(this, nativeObject);
@@ -69,6 +71,20 @@ public final class OverlayProperties implements Parcelable {
        return sDefaultOverlayProperties;
    }

    /**
     * Gets the lut properties of the display.
     * @hide
     */
    public LutProperties[] getLutProperties() {
        if (mNativeObject == 0) {
            return null;
        }
        if (mLutProperties == null) {
            mLutProperties = nGetLutProperties(mNativeObject);
        }
        return mLutProperties;
    }

    /**
     * Indicates that hardware composition of a buffer encoded with the provided {@link DataSpace}
     * and {@link HardwareBuffer.Format} is supported on the device.
@@ -140,4 +156,5 @@ public final class OverlayProperties implements Parcelable {
            long nativeObject, int dataspace, int format);
    private static native void nWriteOverlayPropertiesToParcel(long nativeObject, Parcel dest);
    private static native long nReadOverlayPropertiesFromParcel(Parcel in);
    private static native LutProperties[] nGetLutProperties(long nativeObject);
}
 No newline at end of file
+14 −2
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.gui.DropInputMode;
import android.gui.StalledTransactionInfo;
import android.gui.TrustedOverlay;
import android.hardware.DataSpace;
import android.hardware.DisplayLuts;
import android.hardware.HardwareBuffer;
import android.hardware.OverlayProperties;
import android.hardware.SyncFence;
@@ -307,9 +308,9 @@ public final class SurfaceControl implements Parcelable {
    private static native StalledTransactionInfo nativeGetStalledTransactionInfo(int pid);
    private static native void nativeSetDesiredPresentTimeNanos(long transactionObj,
                                                                long desiredPresentTimeNanos);
    private static native void nativeSetFrameTimeline(long transactionObj,
                                                           long vsyncId);
    private static native void nativeNotifyShutdown();
    private static native void nativeSetLuts(long transactionObj, long nativeObject,
            float[] buffers, int[] slots, int[] dimensions, int[] sizes, int[] samplingKeys);

    /**
     * Transforms that can be applied to buffers as they are displayed to a window.
@@ -4399,6 +4400,17 @@ public final class SurfaceControl implements Parcelable {
            return this;
        }

        /** @hide */
        public @NonNull Transaction setLuts(@NonNull SurfaceControl sc,
                @NonNull DisplayLuts displayLuts) {
            checkPreconditions(sc);

            nativeSetLuts(mNativeObject, sc.mNativeObject, displayLuts.getLutBuffers(),
                    displayLuts.getOffsets(), displayLuts.getLutDimensions(),
                    displayLuts.getLutSizes(), displayLuts.getLutSamplingKeys());
            return this;
        }

        /**
         * Sets the caching hint for the layer. By default, the caching hint is
         * {@link CACHING_ENABLED}.
+43 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define LOG_TAG "OverlayProperties"
// #define LOG_NDEBUG 0

#include <android/gui/LutProperties.h>
#include <android/gui/OverlayProperties.h>
#include <binder/Parcel.h>
#include <gui/SurfaceComposerClient.h>
@@ -35,6 +36,12 @@ static struct {
    jclass clazz;
    jmethodID ctor;
} gOverlayPropertiesClassInfo;

static struct {
    jclass clazz;
    jmethodID ctor;
} gLutPropertiesClassInfo;

// ----------------------------------------------------------------------------
// OverlayProperties lifecycle
// ----------------------------------------------------------------------------
@@ -95,6 +102,36 @@ static jlong android_hardware_OverlayProperties_createDefault(JNIEnv* env, jobje
    return reinterpret_cast<jlong>(overlayProperties);
}

static jobjectArray android_hardware_OverlayProperties_getLutProperties(JNIEnv* env, jobject thiz,
                                                                        jlong nativeObject) {
    gui::OverlayProperties* overlayProperties =
            reinterpret_cast<gui::OverlayProperties*>(nativeObject);
    if (overlayProperties->lutProperties.has_value()) {
        return NULL;
    }
    auto& lutProperties = overlayProperties->lutProperties.value();
    if (lutProperties.empty()) {
        return NULL;
    }
    int32_t size = static_cast<int32_t>(lutProperties.size());
    jobjectArray nativeLutProperties =
            env->NewObjectArray(size, gLutPropertiesClassInfo.clazz, NULL);
    if (nativeLutProperties == NULL) {
        return NULL;
    }
    for (int32_t i = 0; i < size; i++) {
        if (lutProperties[i].has_value()) {
            auto& item = lutProperties[i].value();
            jobject properties =
                    env->NewObject(gLutPropertiesClassInfo.clazz, gLutPropertiesClassInfo.ctor,
                                   static_cast<int32_t>(item.dimension), item.size,
                                   item.samplingKeys.data());
            env->SetObjectArrayElement(nativeLutProperties, i, properties);
        }
    }
    return nativeLutProperties;
}

// ----------------------------------------------------------------------------
// Serialization
// ----------------------------------------------------------------------------
@@ -161,6 +198,8 @@ static const JNINativeMethod gMethods[] = {
    { "nReadOverlayPropertiesFromParcel", "(Landroid/os/Parcel;)J",
            (void*) android_hardware_OverlayProperties_read },
    {"nCreateDefault", "()J", (void*) android_hardware_OverlayProperties_createDefault },
    {"nGetLutProperties", "(J)[Landroid/hardware/LutProperties;",
            (void*) android_hardware_OverlayProperties_getLutProperties },
};
// clang-format on

@@ -171,5 +210,9 @@ int register_android_hardware_OverlayProperties(JNIEnv* env) {
    gOverlayPropertiesClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    gOverlayPropertiesClassInfo.ctor =
            GetMethodIDOrDie(env, gOverlayPropertiesClassInfo.clazz, "<init>", "(J)V");
    clazz = FindClassOrDie(env, "android/hardware/LutProperties");
    gLutPropertiesClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
    gLutPropertiesClassInfo.ctor =
            GetMethodIDOrDie(env, gLutPropertiesClassInfo.clazz, "<init>", "(IJ[I)V");
    return err;
}
Loading