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

#ifndef GrDrawingManager_DEFINED
#define GrDrawingManager_DEFINED

#include <set>
#include "include/core/SkSurface.h"
#include "include/private/SkTArray.h"
#include "src/gpu/GrBufferAllocPool.h"
#include "src/gpu/GrDeferredUpload.h"
#include "src/gpu/GrPathRenderer.h"
#include "src/gpu/GrPathRendererChain.h"
#include "src/gpu/GrResourceCache.h"
#include "src/gpu/text/GrTextContext.h"

class GrCoverageCountingPathRenderer;
class GrOnFlushCallbackObject;
class GrOpFlushState;
class GrOpsTask;
class GrRecordingContext;
class GrRenderTargetContext;
class GrRenderTargetProxy;
class GrSoftwarePathRenderer;
class GrTextureContext;
class SkDeferredDisplayList;

class GrDrawingManager {
public:
    ~GrDrawingManager();

    void freeGpuResources();

    std::unique_ptr<GrRenderTargetContext> makeRenderTargetContext(sk_sp<GrSurfaceProxy>,
                                                                   GrColorType,
                                                                   sk_sp<SkColorSpace>,
                                                                   const SkSurfaceProps*,
                                                                   bool managedOpsTask = true);
    std::unique_ptr<GrTextureContext> makeTextureContext(sk_sp<GrSurfaceProxy>,
                                                         GrColorType,
                                                         SkAlphaType,
                                                         sk_sp<SkColorSpace>);

    // A managed opsTask is controlled by the drawing manager (i.e., sorted & flushed with the
    // others). An unmanaged one is created and used by the onFlushCallback.
    sk_sp<GrOpsTask> newOpsTask(sk_sp<GrRenderTargetProxy>, bool managedOpsTask);

    // Create a new, specialized, render task that will regenerate mipmap levels and/or resolve
    // MSAA (depending on GrTextureResolveFlags). This method will add the new render task to the
    // list of render tasks and make it depend on the target texture proxy. It is up to the caller
    // to add any dependencies on the new render task.
    GrRenderTask* newTextureResolveRenderTask(
            sk_sp<GrTextureProxy>, GrTextureResolveFlags, const GrCaps&);

    // Create a new render task which copies the pixels from the srcProxy into the dstBuffer. This
    // is used to support the asynchronous readback API. The srcRect is the region of the srcProxy
    // to be copied. The surfaceColorType says how we should interpret the data when reading back
    // from the source. DstColorType describes how the data should be stored in the dstBuffer.
    // DstOffset is the offset into the dstBuffer where we will start writing data.
    void newTransferFromRenderTask(sk_sp<GrSurfaceProxy> srcProxy, const SkIRect& srcRect,
                                   GrColorType surfaceColorType, GrColorType dstColorType,
                                   sk_sp<GrGpuBuffer> dstBuffer, size_t dstOffset);

    // Creates a new render task which copies a pixel rectangle from srcProxy into dstProxy. The src
    // pixels copied are specified by srcRect. They are copied to a rect of the same size in
    // dstProxy with top left at dstPoint. If the src rect is clipped by the src bounds then  pixel
    // values in the dst rect corresponding to the area clipped by the src rect are not overwritten.
    // This method is not guaranteed to succeed depending on the type of surface, formats, etc, and
    // the backend-specific limitations.
    bool newCopyRenderTask(sk_sp<GrSurfaceProxy> srcProxy, const SkIRect& srcRect,
                           sk_sp<GrSurfaceProxy> dstProxy, const SkIPoint& dstPoint);

    GrRecordingContext* getContext() { return fContext; }

    GrTextContext* getTextContext();

    GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
                                    bool allowSW,
                                    GrPathRendererChain::DrawType drawType,
                                    GrPathRenderer::StencilSupport* stencilSupport = nullptr);

    GrPathRenderer* getSoftwarePathRenderer();

    // Returns a direct pointer to the coverage counting path renderer, or null if it is not
    // supported and turned on.
    GrCoverageCountingPathRenderer* getCoverageCountingPathRenderer();

    void flushIfNecessary();

    static bool ProgramUnitTest(GrContext* context, int maxStages, int maxLevels);

    GrSemaphoresSubmitted flushSurfaces(GrSurfaceProxy* proxies[],
                                        int cnt,
                                        SkSurface::BackendSurfaceAccess access,
                                        const GrFlushInfo& info);
    GrSemaphoresSubmitted flushSurface(GrSurfaceProxy* proxy,
                                       SkSurface::BackendSurfaceAccess access,
                                       const GrFlushInfo& info) {
        return this->flushSurfaces(&proxy, 1, access, info);
    }

    void addOnFlushCallbackObject(GrOnFlushCallbackObject*);

#if GR_TEST_UTILS
    void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*);
#endif

    void moveRenderTasksToDDL(SkDeferredDisplayList* ddl);
    void copyRenderTasksFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);

private:
    // This class encapsulates maintenance and manipulation of the drawing manager's DAG of
    // renderTasks.
    class RenderTaskDAG {
    public:
        RenderTaskDAG(bool sortRenderTasks);
        ~RenderTaskDAG();

        // Currently, when explicitly allocating resources, this call will topologically sort the
        // GrRenderTasks.
        // MDB TODO: remove once incremental GrRenderTask sorting is enabled
        void prepForFlush();

        void closeAll(const GrCaps* caps);

        // A yucky combination of closeAll and reset
        void cleanup(const GrCaps* caps);

        void gatherIDs(SkSTArray<8, uint32_t, true>* idArray) const;

        void reset();

        // These calls forceably remove a GrRenderTask from the DAG. They are problematic bc they
        // just remove the GrRenderTask but don't cleanup any refering pointers (i.e., dependency
        // pointers in the DAG). They work right now bc they are only called at flush time, after
        // the topological sort is complete (so the dangling pointers aren't used).
        void removeRenderTask(int index);
        void removeRenderTasks(int startIndex, int stopIndex);

        bool empty() const { return fRenderTasks.empty(); }
        int numRenderTasks() const { return fRenderTasks.count(); }

        bool isUsed(GrSurfaceProxy*) const;

        GrRenderTask* renderTask(int index) { return fRenderTasks[index].get(); }
        const GrRenderTask* renderTask(int index) const { return fRenderTasks[index].get(); }

        GrRenderTask* back() { return fRenderTasks.back().get(); }
        const GrRenderTask* back() const { return fRenderTasks.back().get(); }

        GrRenderTask* add(sk_sp<GrRenderTask>);
        GrRenderTask* addBeforeLast(sk_sp<GrRenderTask>);
        void add(const SkTArray<sk_sp<GrRenderTask>>&);

        void swap(SkTArray<sk_sp<GrRenderTask>>* renderTasks);

        bool sortingRenderTasks() const { return fSortRenderTasks; }

    private:
        SkTArray<sk_sp<GrRenderTask>> fRenderTasks;
        bool                          fSortRenderTasks;
    };

    GrDrawingManager(GrRecordingContext*, const GrPathRendererChain::Options&,
                     const GrTextContext::Options&,
                     bool sortRenderTasks,
                     bool reduceOpsTaskSplitting);

    bool wasAbandoned() const;

    void cleanup();

    // Closes the target's dependent render tasks (or, if not in sorting/opsTask-splitting-reduction
    // mode, closes fActiveOpsTask) in preparation for us opening a new opsTask that will write to
    // 'target'.
    void closeRenderTasksForNewRenderTask(GrSurfaceProxy* target);

    // return true if any GrRenderTasks were actually executed; false otherwise
    bool executeRenderTasks(int startIndex, int stopIndex, GrOpFlushState*,
                            int* numRenderTasksExecuted);

    GrSemaphoresSubmitted flush(GrSurfaceProxy* proxies[],
                                int numProxies,
                                SkSurface::BackendSurfaceAccess access,
                                const GrFlushInfo&,
                                const GrPrepareForExternalIORequests&);

    SkDEBUGCODE(void validate() const);

    friend class GrContext; // access to: flush & cleanup
    friend class GrContextPriv; // access to: flush
    friend class GrOnFlushResourceProvider; // this is just a shallow wrapper around this class
    friend class GrRecordingContext;  // access to: ctor
    friend class SkImage; // for access to: flush

    static const int kNumPixelGeometries = 5; // The different pixel geometries
    static const int kNumDFTOptions = 2;      // DFT or no DFT

    GrRecordingContext*               fContext;
    GrPathRendererChain::Options      fOptionsForPathRendererChain;
    GrTextContext::Options            fOptionsForTextContext;
    // This cache is used by both the vertex and index pools. It reuses memory across multiple
    // flushes.
    sk_sp<GrBufferAllocPool::CpuBufferCache> fCpuBufferCache;

    RenderTaskDAG                     fDAG;
    GrOpsTask*                        fActiveOpsTask = nullptr;
    // These are the IDs of the opsTask currently being flushed (in internalFlush)
    SkSTArray<8, uint32_t, true>      fFlushingRenderTaskIDs;
    // These are the new opsTask generated by the onFlush CBs
    SkSTArray<8, sk_sp<GrOpsTask>>    fOnFlushCBOpsTasks;

    std::unique_ptr<GrTextContext>    fTextContext;

    std::unique_ptr<GrPathRendererChain> fPathRendererChain;
    sk_sp<GrSoftwarePathRenderer>     fSoftwarePathRenderer;

    GrTokenTracker                    fTokenTracker;
    bool                              fFlushing;
    bool                              fReduceOpsTaskSplitting;

    SkTArray<GrOnFlushCallbackObject*> fOnFlushCBObjects;

    void addDDLTarget(GrSurfaceProxy* proxy) { fDDLTargets.insert(proxy); }
    bool isDDLTarget(GrSurfaceProxy* proxy) { return fDDLTargets.find(proxy) != fDDLTargets.end(); }
    void clearDDLTargets() { fDDLTargets.clear(); }

    // We play a trick with lazy proxies to retarget the base target of a DDL to the SkSurface
    // it is replayed on. Because of this remapping we need to explicitly store the targets of
    // DDL replaying.
    // Note: we do not expect a whole lot of these per flush
    std::set<GrSurfaceProxy*> fDDLTargets;
};

#endif
