/*
 * Copyright 2022 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_NDEBUG 0

#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <common/trace.h>
#include <gui/GLConsumer.h>
#include <math/vec3.h>
#include <system/window.h>

#include "LayerFE.h"
#include "SurfaceFlinger.h"
#include "ui/FenceResult.h"

namespace android {

namespace {
constexpr float defaultMaxLuminance = 1000.0;

constexpr mat4 inverseOrientation(uint32_t transform) {
    const mat4 flipH(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
    const mat4 flipV(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1);
    const mat4 rot90(0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1);
    mat4 tr;

    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
        tr = tr * rot90;
    }
    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
        tr = tr * flipH;
    }
    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
        tr = tr * flipV;
    }
    return inverse(tr);
}

FloatRect reduce(const FloatRect& win, const Region& exclude) {
    if (CC_LIKELY(exclude.isEmpty())) {
        return win;
    }
    // Convert through Rect (by rounding) for lack of FloatRegion
    return Region(Rect{win}).subtract(exclude).getBounds().toFloatRect();
}

// Computes the transform matrix using the setFilteringEnabled to determine whether the
// transform matrix should be computed for use with bilinear filtering.
void getDrawingTransformMatrix(const std::shared_ptr<renderengine::ExternalTexture>& buffer,
                               Rect bufferCrop, uint32_t bufferTransform, bool filteringEnabled,
                               float outMatrix[16]) {
    if (!buffer) {
        ALOGE("Buffer should not be null!");
        return;
    }
    GLConsumer::computeTransformMatrix(outMatrix, static_cast<float>(buffer->getWidth()),
                                       static_cast<float>(buffer->getHeight()),
                                       buffer->getPixelFormat(), bufferCrop, bufferTransform,
                                       filteringEnabled);
}

} // namespace

LayerFE::LayerFE(const std::string& name) : mName(name) {}

LayerFE::~LayerFE() {
    // Ensures that no promise is left unfulfilled before the LayerFE is destroyed.
    // An unfulfilled promise could occur when a screenshot is attempted, but the
    // render area is invalid and there is no memory for the capture result.
    if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
        setReleaseFence(Fence::NO_FENCE);
    }
}

const compositionengine::LayerFECompositionState* LayerFE::getCompositionState() const {
    return mSnapshot.get();
}

bool LayerFE::onPreComposition(bool) {
    return mSnapshot->hasReadyFrame;
}

std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientComposition(
        compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
    std::optional<compositionengine::LayerFE::LayerSettings> layerSettings =
            prepareClientCompositionInternal(targetSettings);
    // Nothing to render.
    if (!layerSettings) {
        return {};
    }

    // HWC requests to clear this layer.
    if (targetSettings.clearContent) {
        prepareClearClientComposition(*layerSettings, false /* blackout */);
        return layerSettings;
    }

    // set the shadow for the layer if needed
    prepareShadowClientComposition(*layerSettings, targetSettings.viewport);

    layerSettings->borderSettings = mSnapshot->borderSettings;
    layerSettings->boxShadowSettings = mSnapshot->boxShadowSettings;
    layerSettings->postProcessEffect = mSnapshot->postProcessEffect;
    layerSettings->postProcessUniforms = mSnapshot->postProcessUniforms;
    layerSettings->postProcessTarget =
            static_cast<renderengine::LayerSettings::SampleTarget>(mSnapshot->postProcessTarget);

    return layerSettings;
}

std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientCompositionInternal(
        compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
    SFTRACE_CALL();
    compositionengine::LayerFE::LayerSettings layerSettings;
    layerSettings.geometry.originalBounds = mSnapshot->geomLayerBounds;

    if (mSnapshot->parentRoundedCorner.hasRequestedRadius()) {
        layerSettings.geometry.otherRoundedCornersRadii =
                mSnapshot->parentRoundedCorner.sfDrawnRadii;
        layerSettings.geometry.otherCrop = mSnapshot->parentRoundedCorner.cropRect;
    } else {
        layerSettings.geometry.otherCrop = mSnapshot->parentGeomLayerCrop;
    }

    layerSettings.geometry.boundaries =
            (FlagManager::getInstance().disable_transparent_region_hint())
            ? mSnapshot->geomLayerBounds
            : reduce(mSnapshot->geomLayerBounds, mSnapshot->transparentRegionHint);
    layerSettings.geometry.positionTransform = mSnapshot->geomLayerTransform.asMatrix4();

    // skip drawing content if the targetSettings indicate the content will be occluded
    const bool drawContent = targetSettings.realContentIsVisible || targetSettings.clearContent;
    layerSettings.skipContentDraw = !drawContent;

    if (!mSnapshot->colorTransformIsIdentity) {
        layerSettings.colorTransform = mSnapshot->colorTransform;
    }

    const auto& roundedCornerState = mSnapshot->roundedCorner;
    layerSettings.geometry.roundedCornersRadii = roundedCornerState.sfDrawnRadii;
    layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect;

    layerSettings.alpha = mSnapshot->alpha;
    layerSettings.sourceDataspace = mSnapshot->dataspace;

    // Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
    // We do this here instead of in buffer info so that dumpsys can still report layers that are
    // using the 170M transfer.
    if (targetSettings.treat170mAsSrgb &&
        (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) ==
                HAL_DATASPACE_TRANSFER_SMPTE_170M) {
        layerSettings.sourceDataspace = static_cast<ui::Dataspace>(
                (layerSettings.sourceDataspace & HAL_DATASPACE_STANDARD_MASK) |
                (layerSettings.sourceDataspace & HAL_DATASPACE_RANGE_MASK) |
                HAL_DATASPACE_TRANSFER_SRGB);
    }

    layerSettings.whitePointNits = targetSettings.whitePointNits;
    switch (targetSettings.blurSetting) {
        case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled:
            layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
            layerSettings.backgroundBlurScale = mSnapshot->backgroundBlurScale;
            layerSettings.blurRegions = mSnapshot->blurRegions;
            layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
            break;
        case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly:
            layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
            layerSettings.backgroundBlurScale = mSnapshot->backgroundBlurScale;
            break;
        case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly:
            layerSettings.blurRegions = mSnapshot->blurRegions;
            layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
            break;
        case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled:
        default:
            break;
    }
    layerSettings.stretchEffect = mSnapshot->stretchEffect;
    layerSettings.edgeExtensionEffect = mSnapshot->edgeExtensionEffect;
    // Record the name of the layer for debugging further down the stack.
    layerSettings.name = mSnapshot->name;
    layerSettings.luts = mSnapshot->luts ? mSnapshot->luts : targetSettings.luts;

    layerSettings.renderCommandBuffer = mSnapshot->renderCommandBuffer;
    layerSettings.renderResourceCache = mSnapshot->renderResourceCache;
    layerSettings.renderCommandBufferFrameId = mSnapshot->renderCommandBufferFrameId;

    if (hasEffect() && !hasBufferOrSidebandStream()) {
        prepareEffectsClientComposition(layerSettings, targetSettings);
        return layerSettings;
    }

    prepareBufferStateClientComposition(layerSettings, targetSettings);
    return layerSettings;
}

void LayerFE::prepareClearClientComposition(LayerFE::LayerSettings& layerSettings,
                                            bool blackout) const {
    layerSettings.source.buffer.buffer = nullptr;
    layerSettings.source.solidColor = half3(0.0f, 0.0f, 0.0f);
    layerSettings.disableBlending = true;
    layerSettings.bufferId = 0;
    layerSettings.frameNumber = 0;
    layerSettings.sequence = -1;

    // If layer is blacked out, force alpha to 1 so that we draw a black color layer.
    layerSettings.alpha = blackout ? 1.0f : 0.0f;
    layerSettings.name = mSnapshot->name;
}

void LayerFE::prepareEffectsClientComposition(
        compositionengine::LayerFE::LayerSettings& layerSettings,
        compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
    // If fill bounds are occluded or the fill color is invalid skip the fill settings.
    if (targetSettings.realContentIsVisible && fillsColor()) {
        // Set color for color fill settings.
        layerSettings.source.solidColor = mSnapshot->color.rgb;
    } else if (hasBlur() || drawShadows() || hasBorderSettings() || hasBoxShadowSettings()) {
        layerSettings.skipContentDraw = true;
    }
}

void LayerFE::prepareBufferStateClientComposition(
        compositionengine::LayerFE::LayerSettings& layerSettings,
        compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
    SFTRACE_CALL();
    if (CC_UNLIKELY(!mSnapshot->externalTexture)) {
        // If there is no buffer for the layer or we have sidebandstream where there is no
        // activeBuffer, then we need to return LayerSettings.
        return;
    }
    bool blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) ||
                (mSnapshot->isSecure && !targetSettings.isSecure);
    const bool bufferCanBeUsedAsHwTexture =
            mSnapshot->externalTexture->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
    if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
        ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
                 mSnapshot->name.c_str());
        prepareClearClientComposition(layerSettings, true /* blackout */);
        return;
    }

    layerSettings.source.buffer.buffer = mSnapshot->externalTexture;
    layerSettings.source.buffer.isOpaque = mSnapshot->contentOpaque;
    layerSettings.source.buffer.fence = mSnapshot->acquireFence;
    layerSettings.source.buffer.usePremultipliedAlpha = mSnapshot->premultipliedAlpha;
    bool hasSmpte2086 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086;
    bool hasCta861_3 = mSnapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3;
    float maxLuminance = 0.f;
    if (hasSmpte2086 && hasCta861_3) {
        maxLuminance = std::min(mSnapshot->hdrMetadata.smpte2086.maxLuminance,
                                mSnapshot->hdrMetadata.cta8613.maxContentLightLevel);
    } else if (hasSmpte2086) {
        maxLuminance = mSnapshot->hdrMetadata.smpte2086.maxLuminance;
    } else if (hasCta861_3) {
        maxLuminance = mSnapshot->hdrMetadata.cta8613.maxContentLightLevel;
    } else {
        switch (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
            case HAL_DATASPACE_TRANSFER_ST2084:
            case HAL_DATASPACE_TRANSFER_HLG:
                // Behavior-match previous releases for HDR content
                maxLuminance = defaultMaxLuminance;
                break;
        }
    }
    layerSettings.source.buffer.maxLuminanceNits = maxLuminance;
    layerSettings.frameNumber = mSnapshot->frameNumber;
    layerSettings.bufferId = mSnapshot->externalTexture->getId();
    layerSettings.sequence = mSnapshot->sequence;

    const bool useFiltering = targetSettings.needsFiltering ||
                              mSnapshot->geomLayerTransform.needsBilinearFiltering();

    // Query the texture matrix given our current filtering mode.
    float textureMatrix[16];
    getDrawingTransformMatrix(layerSettings.source.buffer.buffer, mSnapshot->geomContentCrop,
                              mSnapshot->geomBufferTransform, useFiltering,
                              textureMatrix);

    if (mSnapshot->geomBufferUsesDisplayInverseTransform) {
        /*
         * the code below applies the primary display's inverse transform to
         * the texture transform
         */
        uint32_t transform = SurfaceFlinger::getFrontInternalDisplayRotationFlags();
        mat4 tr = inverseOrientation(transform);

        /**
         * TODO(b/36727915): This is basically a hack.
         *
         * Ensure that regardless of the parent transformation,
         * this buffer is always transformed from native display
         * orientation to display orientation. For example, in the case
         * of a camera where the buffer remains in native orientation,
         * we want the pixels to always be upright.
         */
        const auto parentTransform = mSnapshot->parentTransform;
        tr = tr * inverseOrientation(parentTransform.getOrientation());

        // and finally apply it to the original texture matrix
        const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
        memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
    }

    const Rect win{layerSettings.geometry.boundaries};
    float bufferWidth = static_cast<float>(mSnapshot->bufferSize.getWidth());
    float bufferHeight = static_cast<float>(mSnapshot->bufferSize.getHeight());

    // Layers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
    // been set and there is no parent layer bounds. In that case, the scale is meaningless so
    // ignore them.
    if (!mSnapshot->bufferSize.isValid()) {
        bufferWidth = float(win.right) - float(win.left);
        bufferHeight = float(win.bottom) - float(win.top);
    }

    const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
    const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
    const float translateY = float(win.top) / bufferHeight;
    const float translateX = float(win.left) / bufferWidth;

    // Flip y-coordinates because GLConsumer expects OpenGL convention.
    mat4 tr = mat4::translate(vec4(.5f, .5f, 0.f, 1.f)) * mat4::scale(vec4(1.f, -1.f, 1.f, 1.f)) *
            mat4::translate(vec4(-.5f, -.5f, 0.f, 1.f)) *
            mat4::translate(vec4(translateX, translateY, 0.f, 1.f)) *
            mat4::scale(vec4(scaleWidth, scaleHeight, 1.0f, 1.0f));

    layerSettings.source.buffer.useTextureFiltering = useFiltering;
    layerSettings.source.buffer.textureTransform =
            mat4(static_cast<const float*>(textureMatrix)) * tr;

    return;
}

void LayerFE::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
                                             const Rect& layerStackRect) const {
    ShadowSettings state = mSnapshot->shadowSettings;
    if (state.length <= 0.f || (state.ambientColor.a <= 0.f && state.spotColor.a <= 0.f)) {
        return;
    }

    // The light source should be at (screenWidth/2, globalShadowSettings.lightPos.y) in
    // screenspace.
    vec2 lightPosScreenSpace = {
            (static_cast<float>(layerStackRect.width()) / 2.f),
            state.lightPos.y,
    };

    // Skia expects light pos in layer space.
    vec2 lightPosLayerSpace = mSnapshot->geomInverseLayerTransform.transform(lightPosScreenSpace);

    state.lightPos.x = lightPosLayerSpace.x;
    state.lightPos.y = lightPosLayerSpace.y;

    caster.shadow = state;
}

void LayerFE::onPictureProfileCommitted() {
    mCompositionResult.wasPictureProfileCommitted = true;
    mCompositionResult.pictureProfileHandle = mSnapshot->pictureProfileHandle;
}

CompositionResult LayerFE::stealCompositionResult() {
    CompositionResult result;
    std::swap(mCompositionResult, result);
    return result;
}

const char* LayerFE::getDebugName() const {
    return mName.c_str();
}

const LayerMetadata* LayerFE::getMetadata() const {
    return &mSnapshot->layerMetadata;
}

const LayerMetadata* LayerFE::getRelativeMetadata() const {
    return &mSnapshot->relativeLayerMetadata;
}

int32_t LayerFE::getSequence() const {
    return static_cast<int32_t>(mSnapshot->uniqueSequence);
}

bool LayerFE::hasRoundedCorners() const {
    return mSnapshot->roundedCorner.hasSfDrawnRadius();
}

void LayerFE::setWasClientComposed(const sp<Fence>& fence) {
    mCompositionResult.lastClientCompositionFence = fence;
}

bool LayerFE::hasBufferOrSidebandStream() const {
    return mSnapshot->externalTexture || mSnapshot->sidebandStream;
}

bool LayerFE::fillsColor() const {
    return mSnapshot->color.r >= 0.0_hf && mSnapshot->color.g >= 0.0_hf &&
            mSnapshot->color.b >= 0.0_hf;
}

bool LayerFE::hasBlur() const {
    return mSnapshot->backgroundBlurRadius > 0 || mSnapshot->blurRegions.size() > 0;
}

bool LayerFE::hasBorderSettings() const {
    return mSnapshot->hasBorderSettings();
}

bool LayerFE::hasBoxShadowSettings() const {
    return mSnapshot->hasBoxShadowSettings();
}

bool LayerFE::drawShadows() const {
    return mSnapshot->shadowSettings.length > 0.f &&
            (mSnapshot->shadowSettings.ambientColor.a > 0 ||
             mSnapshot->shadowSettings.spotColor.a > 0);
};

const sp<GraphicBuffer> LayerFE::getBuffer() const {
    return mSnapshot->externalTexture ? mSnapshot->externalTexture->getBuffer() : nullptr;
}

void LayerFE::setReleaseFence(const FenceResult& releaseFence) {
    // Promises should not be fulfilled more than once. This case can occur if virtual
    // displays with the same layerstack ID are being created and destroyed in quick
    // succession, such as in tests. This would result in a race condition in which
    // multiple displays have the same layerstack ID within the same vsync interval.
    if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::FULFILLED) {
        return;
    }

    if (releaseFence.has_value()) {
        if (FlagManager::getInstance().monitor_buffer_fences()) {
            if (auto strongBuffer = mReleasedBuffer.promote()) {
                strongBuffer->getDependencyMonitor()
                        .addAccessCompletion(FenceTime::makeValid(releaseFence.value()), "HWC");
            }
        }
    }
    mReleaseFence.set_value(releaseFence);
    mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::FULFILLED;
}

// LayerFEs are reused and a new fence needs to be created whevever a buffer is latched.
ftl::Future<FenceResult> LayerFE::createReleaseFenceFuture() {
    if (mReleaseFencePromiseStatus == ReleaseFencePromiseStatus::INITIALIZED) {
        LOG_ALWAYS_FATAL_IF(!FlagManager::getInstance().frontend_caching_v0(),
                            "Attempting to create a new promise while one is still unfulfilled.");
        ALOGW("Creating a new promise while one is still unfulfilled. Fulfilling with NO_FENCE.");
        mReleaseFence.set_value(Fence::NO_FENCE);
    }
    mReleaseFence = std::promise<FenceResult>();
    mReleaseFencePromiseStatus = ReleaseFencePromiseStatus::INITIALIZED;
    return mReleaseFence.get_future();
}

LayerFE::ReleaseFencePromiseStatus LayerFE::getReleaseFencePromiseStatus() {
    return mReleaseFencePromiseStatus;
}

void LayerFE::setReleasedBuffer(sp<GraphicBuffer> buffer) {
    mReleasedBuffer = std::move(buffer);
}

void LayerFE::setLastHwcState(const LayerFE::HwcLayerDebugState &state) {
    mLastHwcState = state;
}

const LayerFE::HwcLayerDebugState& LayerFE::getLastHwcState() const {
    return mLastHwcState;
};

void LayerFE::setLastClientTargetAcquireFence(const FenceResult& lastCompositionAcquireFence) {
    mLastClientCompositionAcquireFence = lastCompositionAcquireFence;
}

sp<Fence> LayerFE::getAndClearLastClientTargetAcquireFence() {
    sp<Fence> lastCompositionAcquireFence =
            mLastClientCompositionAcquireFence.value_or(Fence::NO_FENCE);
    mLastClientCompositionAcquireFence = Fence::NO_FENCE;
    return lastCompositionAcquireFence;
}

} // namespace android
