Loading native/android/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ cc_library_shared { "surface_control_input_receiver.cpp", "choreographer.cpp", "configuration.cpp", "display_luts.cpp", "dynamic_instrumentation_manager.cpp", "hardware_buffer_jni.cpp", "input.cpp", Loading native/android/display_luts.cpp 0 → 100644 +135 −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. */ #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 native/android/libandroid.map.txt +10 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,15 @@ LIBANDROID { AConfiguration_setTouchscreen; AConfiguration_setUiModeNight; AConfiguration_setUiModeType; ADisplayLuts_create; # introduced=36 ADisplayLuts_setEntries; # introduced=36 ADisplayLuts_destroy; # introduced=36 ADisplayLutsEntry_createEntry; # introduced=36 ADisplayLutsEntry_getDimension; # introduced=36 ADisplayLutsEntry_getSize; # introduced=36 ADisplayLutsEntry_getSamplingKey; # introduced=36 ADisplayLutsEntry_getBuffer; # introduced=36 ADisplayLutsEntry_destroy; # introduced=36 AInputEvent_getDeviceId; AInputEvent_getSource; AInputEvent_getType; Loading Loading @@ -300,6 +309,7 @@ LIBANDROID { ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29 ASurfaceTransaction_setExtendedRangeBrightness; # introduced=UpsideDownCake ASurfaceTransaction_setDesiredHdrHeadroom; # introduced=VanillaIceCream ASurfaceTransaction_setLuts; # introduced=36 ASurfaceTransaction_setOnComplete; # introduced=29 ASurfaceTransaction_setOnCommit; # introduced=31 ASurfaceTransaction_setPosition; # introduced=31 Loading native/android/surface_control.cpp +63 −0 Original line number Diff line number Diff line Loading @@ -14,12 +14,15 @@ * limitations under the License. */ #include <android/gui/LutProperties.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <android/native_window.h> #include <android/surface_control.h> #include <android/surface_control_jni.h> #include <android_runtime/android_view_SurfaceControl.h> #include <configstore/Utils.h> #include <cutils/ashmem.h> #include <display_luts_private.h> #include <gui/HdrMetadata.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> Loading Loading @@ -53,6 +56,14 @@ static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPA static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == static_cast<int>(HAL_DATASPACE_DISPLAY_P3)); static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ)); static_assert(static_cast<int>(ADISPLAYLUTS_ONE_DIMENSION) == static_cast<int>(android::gui::LutProperties::Dimension::ONE_D)); static_assert(static_cast<int>(ADISPLAYLUTS_THREE_DIMENSION) == static_cast<int>(android::gui::LutProperties::Dimension::THREE_D)); static_assert(static_cast<int>(ADISPLAYLUTS_SAMPLINGKEY_RGB) == static_cast<int>(android::gui::LutProperties::SamplingKey::RGB)); static_assert(static_cast<int>(ADISPLAYLUTS_SAMPLINGKEY_MAX_RGB) == static_cast<int>(android::gui::LutProperties::SamplingKey::MAX_RGB)); Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) { return reinterpret_cast<Transaction*>(aSurfaceTransaction); Loading Loading @@ -693,6 +704,58 @@ void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* aSurfaceTran transaction->setDesiredHdrHeadroom(surfaceControl, desiredRatio); } void ASurfaceTransaction_setLuts(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, const struct ADisplayLuts* luts) { CHECK_NOT_NULL(aSurfaceTransaction); CHECK_NOT_NULL(aSurfaceControl); sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); int fd = -1; std::vector<int32_t> offsets; std::vector<int32_t> dimensions; std::vector<int32_t> sizes; std::vector<int32_t> samplingKeys; if (luts) { std::vector<float> buffer(luts->totalBufferSize); int32_t count = luts->offsets.size(); offsets = luts->offsets; dimensions.reserve(count); sizes.reserve(count); samplingKeys.reserve(count); for (int32_t i = 0; i < count; i++) { dimensions.emplace_back(luts->entries[i]->properties.dimension); sizes.emplace_back(luts->entries[i]->properties.size); samplingKeys.emplace_back(luts->entries[i]->properties.samplingKey); std::copy(luts->entries[i]->buffer.data.begin(), luts->entries[i]->buffer.data.end(), buffer.begin() + offsets[i]); } // mmap fd = ashmem_create_region("lut_shared_mem", luts->totalBufferSize * sizeof(float)); if (fd < 0) { LOG_ALWAYS_FATAL("setLuts, ashmem_create_region() failed"); return; } void* ptr = mmap(nullptr, luts->totalBufferSize * sizeof(float), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { LOG_ALWAYS_FATAL("setLuts, Failed to map the shared memory"); return; } memcpy(ptr, buffer.data(), luts->totalBufferSize * sizeof(float)); munmap(ptr, luts->totalBufferSize * sizeof(float)); } transaction->setLuts(surfaceControl, base::unique_fd(fd), offsets, dimensions, sizes, samplingKeys); } void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, float r, float g, float b, float alpha, Loading Loading
native/android/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ cc_library_shared { "surface_control_input_receiver.cpp", "choreographer.cpp", "configuration.cpp", "display_luts.cpp", "dynamic_instrumentation_manager.cpp", "hardware_buffer_jni.cpp", "input.cpp", Loading
native/android/display_luts.cpp 0 → 100644 +135 −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. */ #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
native/android/libandroid.map.txt +10 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,15 @@ LIBANDROID { AConfiguration_setTouchscreen; AConfiguration_setUiModeNight; AConfiguration_setUiModeType; ADisplayLuts_create; # introduced=36 ADisplayLuts_setEntries; # introduced=36 ADisplayLuts_destroy; # introduced=36 ADisplayLutsEntry_createEntry; # introduced=36 ADisplayLutsEntry_getDimension; # introduced=36 ADisplayLutsEntry_getSize; # introduced=36 ADisplayLutsEntry_getSamplingKey; # introduced=36 ADisplayLutsEntry_getBuffer; # introduced=36 ADisplayLutsEntry_destroy; # introduced=36 AInputEvent_getDeviceId; AInputEvent_getSource; AInputEvent_getType; Loading Loading @@ -300,6 +309,7 @@ LIBANDROID { ASurfaceTransaction_setHdrMetadata_smpte2086; # introduced=29 ASurfaceTransaction_setExtendedRangeBrightness; # introduced=UpsideDownCake ASurfaceTransaction_setDesiredHdrHeadroom; # introduced=VanillaIceCream ASurfaceTransaction_setLuts; # introduced=36 ASurfaceTransaction_setOnComplete; # introduced=29 ASurfaceTransaction_setOnCommit; # introduced=31 ASurfaceTransaction_setPosition; # introduced=31 Loading
native/android/surface_control.cpp +63 −0 Original line number Diff line number Diff line Loading @@ -14,12 +14,15 @@ * limitations under the License. */ #include <android/gui/LutProperties.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> #include <android/native_window.h> #include <android/surface_control.h> #include <android/surface_control_jni.h> #include <android_runtime/android_view_SurfaceControl.h> #include <configstore/Utils.h> #include <cutils/ashmem.h> #include <display_luts_private.h> #include <gui/HdrMetadata.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> Loading Loading @@ -53,6 +56,14 @@ static_assert(static_cast<int>(ADATASPACE_SCRGB) == static_cast<int>(HAL_DATASPA static_assert(static_cast<int>(ADATASPACE_DISPLAY_P3) == static_cast<int>(HAL_DATASPACE_DISPLAY_P3)); static_assert(static_cast<int>(ADATASPACE_BT2020_PQ) == static_cast<int>(HAL_DATASPACE_BT2020_PQ)); static_assert(static_cast<int>(ADISPLAYLUTS_ONE_DIMENSION) == static_cast<int>(android::gui::LutProperties::Dimension::ONE_D)); static_assert(static_cast<int>(ADISPLAYLUTS_THREE_DIMENSION) == static_cast<int>(android::gui::LutProperties::Dimension::THREE_D)); static_assert(static_cast<int>(ADISPLAYLUTS_SAMPLINGKEY_RGB) == static_cast<int>(android::gui::LutProperties::SamplingKey::RGB)); static_assert(static_cast<int>(ADISPLAYLUTS_SAMPLINGKEY_MAX_RGB) == static_cast<int>(android::gui::LutProperties::SamplingKey::MAX_RGB)); Transaction* ASurfaceTransaction_to_Transaction(ASurfaceTransaction* aSurfaceTransaction) { return reinterpret_cast<Transaction*>(aSurfaceTransaction); Loading Loading @@ -693,6 +704,58 @@ void ASurfaceTransaction_setDesiredHdrHeadroom(ASurfaceTransaction* aSurfaceTran transaction->setDesiredHdrHeadroom(surfaceControl, desiredRatio); } void ASurfaceTransaction_setLuts(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, const struct ADisplayLuts* luts) { CHECK_NOT_NULL(aSurfaceTransaction); CHECK_NOT_NULL(aSurfaceControl); sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl); Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction); int fd = -1; std::vector<int32_t> offsets; std::vector<int32_t> dimensions; std::vector<int32_t> sizes; std::vector<int32_t> samplingKeys; if (luts) { std::vector<float> buffer(luts->totalBufferSize); int32_t count = luts->offsets.size(); offsets = luts->offsets; dimensions.reserve(count); sizes.reserve(count); samplingKeys.reserve(count); for (int32_t i = 0; i < count; i++) { dimensions.emplace_back(luts->entries[i]->properties.dimension); sizes.emplace_back(luts->entries[i]->properties.size); samplingKeys.emplace_back(luts->entries[i]->properties.samplingKey); std::copy(luts->entries[i]->buffer.data.begin(), luts->entries[i]->buffer.data.end(), buffer.begin() + offsets[i]); } // mmap fd = ashmem_create_region("lut_shared_mem", luts->totalBufferSize * sizeof(float)); if (fd < 0) { LOG_ALWAYS_FATAL("setLuts, ashmem_create_region() failed"); return; } void* ptr = mmap(nullptr, luts->totalBufferSize * sizeof(float), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (ptr == MAP_FAILED) { LOG_ALWAYS_FATAL("setLuts, Failed to map the shared memory"); return; } memcpy(ptr, buffer.data(), luts->totalBufferSize * sizeof(float)); munmap(ptr, luts->totalBufferSize * sizeof(float)); } transaction->setLuts(surfaceControl, base::unique_fd(fd), offsets, dimensions, sizes, samplingKeys); } void ASurfaceTransaction_setColor(ASurfaceTransaction* aSurfaceTransaction, ASurfaceControl* aSurfaceControl, float r, float g, float b, float alpha, Loading