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

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

Merge "[Lut NDK] Define ASurfaceTransaction_setLuts API" into main

parents 28391401 176e379d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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",
+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
+10 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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
+63 −0
Original line number Diff line number Diff line
@@ -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>
@@ -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);
@@ -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,