/*
 * 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
#undef LOG_TAG
#define LOG_TAG "SurfaceFlinger"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS

#include <gui/GLConsumer.h>
#include <gui/TraceUtils.h>
#include <math/vec3.h>
#include <system/window.h>
#include <utils/Log.h>

#include "LayerFE.h"
#include "SurfaceFlinger.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) {}

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

bool LayerFE::onPreComposition(nsecs_t refreshStartTime, bool) {
    mCompositionResult.refreshStartTime = refreshStartTime;
    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);

    return layerSettings;
}

std::optional<compositionengine::LayerFE::LayerSettings> LayerFE::prepareClientCompositionInternal(
        compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
    ATRACE_CALL();
    compositionengine::LayerFE::LayerSettings layerSettings;
    layerSettings.geometry.boundaries =
            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.roundedCornersRadius = roundedCornerState.radius;
    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.blurRegions = mSnapshot->blurRegions;
            layerSettings.blurRegionTransform = mSnapshot->localTransformInverse.asMatrix4();
            break;
        case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly:
            layerSettings.backgroundBlurRadius = mSnapshot->backgroundBlurRadius;
            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;
    // Record the name of the layer for debugging further down the stack.
    layerSettings.name = mSnapshot->name;

    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;

    // 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()) {
        layerSettings.skipContentDraw = true;
    }
}

void LayerFE::prepareBufferStateClientComposition(
        compositionengine::LayerFE::LayerSettings& layerSettings,
        compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
    ATRACE_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;
    if (FlagManager::getInstance().display_protected()) {
        blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) ||
                (mSnapshot->isSecure && !targetSettings.isSecure);
    } else {
        blackOutLayer = (mSnapshot->hasProtectedContent && !targetSettings.isProtected) ||
                ((mSnapshot->isSecure || mSnapshot->hasProtectedContent) &&
                 !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();

    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::getActiveDisplayRotationFlags();
        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;
    }

    // Shift the spot light x-position to the middle of the display and then
    // offset it by casting layer's screen pos.
    state.lightPos.x =
            (static_cast<float>(layerStackRect.width()) / 2.f) - mSnapshot->transformedBounds.left;
    state.lightPos.y -= mSnapshot->transformedBounds.top;
    caster.shadow = state;
}

void LayerFE::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult,
                               ui::LayerStack layerStack) {
    mCompositionResult.releaseFences.emplace_back(std::move(futureFenceResult), layerStack);
}

CompositionResult&& LayerFE::stealCompositionResult() {
    return std::move(mCompositionResult);
}

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.hasRoundedCorners();
}

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::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;
}

} // namespace android
