/*
 * Copyright 2022 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/gpu/graphite/Renderer.h"

#include "src/gpu/graphite/DrawParams.h"
#include "src/gpu/graphite/UniformManager.h"

namespace skgpu::graphite {

RenderStep::RenderStep(Layout layout,
                       RenderStepID renderStepID,
                       SkEnumBitMask<Flags> flags,
                       std::initializer_list<Uniform> uniforms,
                       PrimitiveType primitiveType,
                       StencilSettings stencilSettings,
                       SkSpan<const Attribute> staticAttrs,
                       SkSpan<const Attribute> appendAttrs,
                       SkSpan<const Uniform> storageUniforms,
                       SkSpan<const Varying> varyings)
        : fRenderStepID(renderStepID)
        , fFlags(flags)
        , fStorageBufferStages(
                  (SkToBool(flags & Flags::kVsUsesStorage) ? PipelineStageFlags::kVertexShader
                                                           : PipelineStageFlags{}) |
                  (SkToBool(flags & Flags::kFsUsesStorage) ? PipelineStageFlags::kFragmentShader
                                                           : PipelineStageFlags{}))
        , fPrimitiveType(primitiveType)
        , fStencilSettings(stencilSettings)
        , fUniforms(uniforms)
        , fStaticAttrs(staticAttrs.begin(), staticAttrs.end())
        , fAppendAttrs(appendAttrs.begin(), appendAttrs.end())
        , fStorageUniforms(storageUniforms.begin(), storageUniforms.end())
        , fVaryings(varyings.begin(), varyings.end())
        , fUniformAlignment(0)
        , fStaticDataStride(0)
        , fAppendDataStride(0)
        , fStorageUniformStride(0)
        , fStorageUniformAlignment(1) {
    // If declaring storage uniforms, the flags must specify their visibility
    SkASSERT(fStorageUniforms.empty() ||
             SkToBool(fStorageBufferStages & (PipelineStageFlags::kVertexShader |
                                              PipelineStageFlags::kFragmentShader)));

    // kAllowSelfIntersection and kNoSelfIntersection are mutually exclusive
    SkASSERT(!(SkToBool(fFlags & Flags::kAllowsSelfIntersection) &&
               SkToBool(fFlags & Flags::kNoSelfIntersections)));

    for (auto v : this->staticAttributes()) {
        fStaticDataStride += v.sizeAlign4();
    }
    for (auto i : this->appendAttributes()) {
        fAppendDataStride += i.sizeAlign4();
    }

    if (!fStorageUniforms.empty()) {
        // Storage uniforms are backed by a storage buffer or emulated via a fallback texture.
        // In both cases the struct layout follows Std430.
        UniformOffsetCalculator calculator = UniformOffsetCalculator::ForStruct(Layout::kStd430);
        for (const auto& u : fStorageUniforms) {
            calculator.advanceOffset(u.type(), u.count());
        }
        fStorageUniformAlignment = calculator.requiredAlignment();
        fStorageUniformStride = SkAlignTo<size_t>(calculator.size(), fStorageUniformAlignment);
    }

    UniformOffsetCalculator calculator = UniformOffsetCalculator::ForTopLevel(layout);
    for (const auto& u : fUniforms) {
        calculator.advanceOffset(u.type(), u.count());
    }
    fUniformAlignment = calculator.requiredAlignment();
}

std::optional<SkIRect> RenderStep::getScissor(const DrawParams& params,
                                              SkIRect currentScissor,
                                              SkIRect deviceBounds) const {
    if (currentScissor == params.scissor()) {
        return {}; // Trivially no change in scissor state is required
    }

    Rect drawBounds = params.drawBounds();
    if (params.geometry().isShape() && params.geometry().shape().inverted()) {
        // For inverse filled shapes, the scissor is able to be handled in unique ways.
        if (fFlags & Flags::kInverseFillsScissor) {
            // In this case, the RenderStep geometrically respects the scissor so as long as the
            // current scissor doesn't interfere, we don't need a state change.
            if (currentScissor.contains(params.scissor())) {
                return {};
            } else {
                // This draw doesn't need a scissor at all, so return the device bounds. It is
                // expected that this will generally lead to fewer scissor state changes (for
                // instance when applying the cover steps for a lot of inverse-filled intersect
                // clip depth-only draws). However, it could lead to a redundant scissor change if
                // the next draw would have used this draw's original scissor.
                return deviceBounds;
            }
        }

        if (fFlags & Flags::kIgnoreInverseFill) {
            // In this case params.drawBounds() fills the scissor from the inverse fill rule,
            // but we want to apply the scissor as if it were a regular fill.
            drawBounds = params.transformedShapeBounds(); // this ignores fill rule
            drawBounds.intersect(params.scissor());
        } // Else leave drawBounds filling the original scissor

        // Fall through to regular scissor state checking with the possibly-updated bounds
    }

    // Draws that are unaffected by a clip stack will have a scissor matching the device's bounds.
    // If their transformed shape bounds clipped to the current scissor are no different than their
    // draw bounds (clipped to the original scissor), then no state change is required.
    Rect currentClippedBounds = params.transformedShapeBounds();
    currentClippedBounds.intersect(currentScissor);
    if (currentClippedBounds == drawBounds) {
        return {};
    }

    if (drawBounds == params.transformedShapeBounds()) {
        // We need to change the scissor, but the registered scissor is a no-op so
        // use the device bounds as a canonical scissor.
        return deviceBounds;
    }

    return params.scissor();
}

Coverage RenderStep::GetCoverage(SkEnumBitMask<Flags> flags) {
    return !(flags & Flags::kEmitsCoverage) ? Coverage::kNone
           : (flags & Flags::kLCDCoverage)  ? Coverage::kLCD
                                            : Coverage::kSingleChannel;
}

const char* RenderStep::RenderStepName(RenderStepID id) {
#define CASE1(BaseName) case RenderStepID::k##BaseName: return #BaseName "RenderStep";
#define CASE2(BaseName, VariantName) \
    case RenderStepID::k##BaseName##_##VariantName: return #BaseName "RenderStep[" #VariantName "]";

    switch (id) {
        SKGPU_RENDERSTEP_TYPES(CASE1, CASE2)
    }
#undef CASE1
#undef CASE2

    SkUNREACHABLE;
}

bool RenderStep::IsValidRenderStepID(uint32_t renderStepID) {
    return renderStepID > (int) RenderStep::RenderStepID::kInvalid &&
           renderStepID < RenderStep::kNumRenderSteps;
}

} // namespace skgpu::graphite
