[Lut NDK] Define ASurfaceTransaction_setLuts API

- And also ADisplayLuts, ADisplayLutsEntry struct and correspsonding NDK
  APIs.

Bug: 377329333
Test: android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setLuts_*
Flag: EXEMPT NDK
Change-Id: I23eaef36725a0d63ceba557811812b82b157f83e
diff --git a/native/android/display_luts.cpp b/native/android/display_luts.cpp
new file mode 100644
index 0000000..179a32b
--- /dev/null
+++ b/native/android/display_luts.cpp
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+#define LOG_TAG "DisplayLuts"
+
+#include <android/display_luts.h>
+#include <display_luts_private.h>
+#include <utils/Log.h>
+
+#include <cmath>
+
+#define ADISPLAYLUTS_BUFFER_LENGTH_LIMIT (100000)
+
+#define CHECK_NOT_NULL(name) \
+    LOG_ALWAYS_FATAL_IF(name == nullptr, "nullptr passed as " #name " argument");
+
+ADisplayLutsEntry* ADisplayLutsEntry_createEntry(float* buffer, int32_t length, int32_t dimension,
+                                                 int32_t key) {
+    CHECK_NOT_NULL(buffer);
+    LOG_ALWAYS_FATAL_IF(length >= ADISPLAYLUTS_BUFFER_LENGTH_LIMIT,
+                        "the lut raw buffer length is too big to handle");
+    if (dimension != ADISPLAYLUTS_ONE_DIMENSION && dimension != ADISPLAYLUTS_THREE_DIMENSION) {
+        LOG_ALWAYS_FATAL("the lut dimension is be either 1 or 3");
+    }
+    int32_t size = 0;
+    if (dimension == ADISPLAYLUTS_THREE_DIMENSION) {
+        LOG_ALWAYS_FATAL_IF(length % 3 != 0, "the 3d lut raw buffer is not divisible by 3");
+        int32_t lengthPerChannel = length / 3;
+        float sizeForDim = std::cbrt(static_cast<float>(lengthPerChannel));
+        LOG_ALWAYS_FATAL_IF(sizeForDim != (int)(sizeForDim),
+                            "the 3d lut buffer length is incorrect");
+        size = (int)sizeForDim;
+    } else {
+        size = length;
+    }
+    LOG_ALWAYS_FATAL_IF(size < 2, "the lut size for each dimension is too small");
+
+    ADisplayLutsEntry* entry = new ADisplayLutsEntry();
+    entry->buffer.data.resize(length);
+    std::copy(buffer, buffer + length, entry->buffer.data.begin());
+    entry->properties = {dimension, size, key};
+
+    entry->incStrong((void*)ADisplayLutsEntry_createEntry);
+    return static_cast<ADisplayLutsEntry*>(entry);
+}
+
+void ADisplayLutsEntry_destroy(ADisplayLutsEntry* entry) {
+    if (entry != NULL) {
+        entry->decStrong((void*)ADisplayLutsEntry_createEntry);
+    }
+}
+
+ADisplayLuts_Dimension ADisplayLutsEntry_getDimension(const ADisplayLutsEntry* entry) {
+    CHECK_NOT_NULL(entry);
+    return static_cast<ADisplayLuts_Dimension>(entry->properties.dimension);
+}
+
+int32_t ADisplayLutsEntry_getSize(const ADisplayLutsEntry* entry) {
+    CHECK_NOT_NULL(entry);
+    return entry->properties.size;
+}
+
+ADisplayLuts_SamplingKey ADisplayLutsEntry_getSamplingKey(const ADisplayLutsEntry* entry) {
+    CHECK_NOT_NULL(entry);
+    return static_cast<ADisplayLuts_SamplingKey>(entry->properties.samplingKey);
+}
+
+const float* ADisplayLutsEntry_getBuffer(const ADisplayLutsEntry* _Nonnull entry) {
+    CHECK_NOT_NULL(entry);
+    return entry->buffer.data.data();
+}
+
+ADisplayLuts* ADisplayLuts_create() {
+    ADisplayLuts* luts = new ADisplayLuts();
+    if (luts == NULL) {
+        delete luts;
+        return NULL;
+    }
+    luts->incStrong((void*)ADisplayLuts_create);
+    return static_cast<ADisplayLuts*>(luts);
+}
+
+void ADisplayLuts_clearLuts(ADisplayLuts* luts) {
+    for (auto& entry : luts->entries) {
+        entry->decStrong((void*)ADisplayLuts_setEntries); // Decrement ref count
+    }
+    luts->entries.clear();
+    luts->offsets.clear();
+    luts->totalBufferSize = 0;
+}
+
+void ADisplayLuts_destroy(ADisplayLuts* luts) {
+    if (luts != NULL) {
+        ADisplayLuts_clearLuts(luts);
+        luts->decStrong((void*)ADisplayLuts_create);
+    }
+}
+
+void ADisplayLuts_setEntries(ADisplayLuts* luts, ADisplayLutsEntry** entries, int32_t numEntries) {
+    CHECK_NOT_NULL(luts);
+    // always clear the previously set lut(s)
+    ADisplayLuts_clearLuts(luts);
+
+    // do nothing
+    if (!entries || numEntries == 0) {
+        return;
+    }
+
+    LOG_ALWAYS_FATAL_IF(numEntries > 2, "The number of entries should be not over 2!");
+    if (numEntries == 2 && entries[0]->properties.dimension != ADISPLAYLUTS_ONE_DIMENSION &&
+        entries[1]->properties.dimension != ADISPLAYLUTS_THREE_DIMENSION) {
+        LOG_ALWAYS_FATAL("The entries should be 1D and 3D in order!");
+    }
+
+    luts->offsets.reserve(numEntries);
+    luts->entries.reserve(numEntries);
+    for (int32_t i = 0; i < numEntries; i++) {
+        luts->offsets.emplace_back(luts->totalBufferSize);
+        luts->totalBufferSize += entries[i]->buffer.data.size();
+        luts->entries.emplace_back(entries[i]);
+        luts->entries.back()->incStrong((void*)ADisplayLuts_setEntries);
+    }
+}
\ No newline at end of file