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

#ifndef AtlasRenderTask_DEFINED
#define AtlasRenderTask_DEFINED

#include "include/core/SkPath.h"
#include "src/core/SkTBlockList.h"
#include "src/gpu/GrDynamicAtlas.h"
#include "src/gpu/ops/OpsTask.h"
#include "src/gpu/tessellate/PathTessellator.h"

struct SkIPoint16;

namespace skgpu::v1 {

// Represents a GrRenderTask that draws paths into an atlas. This task gets added the DAG and left
// open, lays out its atlas while future tasks call addPath(), and finally adds its internal draw
// ops during onMakeClosed().
//
// The atlas texture does not get instantiated automatically. It is the creator's responsibility to
// call instantiate() at flush time.
class AtlasRenderTask : public OpsTask {
public:
    AtlasRenderTask(GrRecordingContext*,
                    sk_sp<GrArenas>,
                    std::unique_ptr<GrDynamicAtlas>);

    const GrTextureProxy* atlasProxy() const { return fDynamicAtlas->textureProxy(); }
    GrSurfaceProxyView readView(const GrCaps& caps) const { return fDynamicAtlas->readView(caps); }

    // Allocates a rectangle for, and stages the given path to be rendered into the atlas. Returns
    // false if there was not room in the atlas. On success, writes out the location of the path's
    // upper-left corner to 'locationInAtlas'.
    bool addPath(const SkMatrix&, const SkPath&, SkIPoint pathDevTopLeft, int widthInAtlas,
                 int heightInAtlas, bool transposedInAtlas, SkIPoint16* locationInAtlas);

    // Must be called at flush time. The texture proxy is instantiated with 'backingTexture', if
    // provided. See GrDynamicAtlas.
    void instantiate(GrOnFlushResourceProvider* onFlushRP,
                     sk_sp<GrTexture> backingTexture = nullptr) {
        SkASSERT(this->isClosed());
        fDynamicAtlas->instantiate(onFlushRP, std::move(backingTexture));
    }

private:
    // Adds internal ops to render the atlas before deferring to OpsTask::onMakeClosed.
    ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) override;

    void stencilAtlasRect(GrRecordingContext*, const SkRect&, const SkPMColor4f&,
                          const GrUserStencilSettings*);
    void addAtlasDrawOp(GrOp::Owner, const GrCaps&);

    // Executes the OpsTask and resolves msaa if needed.
    bool onExecute(GrOpFlushState* flushState) override;

    const std::unique_ptr<GrDynamicAtlas> fDynamicAtlas;

    // Allocate enough inline entries for 16 atlas path draws, then spill to the heap.
    using PathDrawList = PathTessellator::PathDrawList;
    using PathDrawAllocator = SkTBlockList<PathDrawList, 16>;
    PathDrawAllocator fPathDrawAllocator{64, SkBlockAllocator::GrowthPolicy::kFibonacci};

    class AtlasPathList : SkNoncopyable {
    public:
        void add(PathDrawAllocator* alloc, const SkMatrix& pathMatrix, const SkPath& path) {
            fPathDrawList = &alloc->emplace_back(pathMatrix, path, fPathDrawList);
            if (path.isInverseFillType()) {
                // The atlas never has inverse paths. The inversion happens later.
                fPathDrawList->fPath.toggleInverseFillType();
            }
            fTotalCombinedPathVerbCnt += path.countVerbs();
            ++fPathCount;
        }
        const PathDrawList* pathDrawList() const { return fPathDrawList; }
        int totalCombinedPathVerbCnt() const { return fTotalCombinedPathVerbCnt; }
        int pathCount() const { return fPathCount; }

    private:
        PathDrawList* fPathDrawList = nullptr;
        int fTotalCombinedPathVerbCnt = 0;
        int fPathCount = 0;
    };

    AtlasPathList fWindingPathList;
    AtlasPathList fEvenOddPathList;
};

} // namespace skgpu::v1

#endif // AtlasRenderTask_DEFINED
