C++程序  |  200行  |  7.88 KB

/*
 * 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 "GrBufferAllocPool.h"
#include "GrDeferredUpload.h"
#include "GrPathRenderer.h"
#include "GrPathRendererChain.h"
#include "GrResourceCache.h"
#include "SkSurface.h"
#include "SkTArray.h"
#include "text/GrTextContext.h"

class GrCoverageCountingPathRenderer;
class GrOnFlushCallbackObject;
class GrOpFlushState;
class GrRecordingContext;
class GrRenderTargetContext;
class GrRenderTargetProxy;
class GrRenderTargetOpList;
class GrSoftwarePathRenderer;
class GrTextureContext;
class GrTextureOpList;
class SkDeferredDisplayList;

// The GrDrawingManager allocates a new GrRenderTargetContext for each GrRenderTarget
// but all of them still land in the same GrOpList!
//
// In the future this class will allocate a new GrRenderTargetContext for
// each GrRenderTarget/GrOpList and manage the DAG.
class GrDrawingManager {
public:
    ~GrDrawingManager();

    void freeGpuResources();

    sk_sp<GrRenderTargetContext> makeRenderTargetContext(sk_sp<GrSurfaceProxy>,
                                                         sk_sp<SkColorSpace>,
                                                         const SkSurfaceProps*,
                                                         bool managedOpList = true);
    sk_sp<GrTextureContext> makeTextureContext(sk_sp<GrSurfaceProxy>, sk_sp<SkColorSpace>);

    // The caller automatically gets a ref on the returned opList. It must
    // be balanced by an unref call.
    // A managed opList is controlled by the drawing manager (i.e., sorted & flushed with the
    // other). An unmanaged one is created and used by the onFlushCallback.
    sk_sp<GrRenderTargetOpList> newRTOpList(GrRenderTargetProxy* rtp, bool managedOpList);
    sk_sp<GrTextureOpList> newTextureOpList(GrTextureProxy* textureProxy);

    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 prepareSurfaceForExternalIO(GrSurfaceProxy*,
                                                      SkSurface::BackendSurfaceAccess access,
                                                      GrFlushFlags flags,
                                                      int numSemaphores,
                                                      GrBackendSemaphore backendSemaphores[],
                                                      GrGpuFinishedProc finishedProc,
                                                      GrGpuFinishedContext finishedContext);

    void addOnFlushCallbackObject(GrOnFlushCallbackObject*);

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

    void moveOpListsToDDL(SkDeferredDisplayList* ddl);
    void copyOpListsFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest);

private:
    // This class encapsulates maintenance and manipulation of the drawing manager's DAG of opLists.
    class OpListDAG {
    public:
        OpListDAG(bool explicitlyAllocating, bool sortOpLists);
        ~OpListDAG();

        // Currently, when explicitly allocating resources, this call will topologically sort the
        // opLists.
        // MDB TODO: remove once incremental opList 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 an opList from the DAG. They are problematic bc they just
        // remove the opList 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 removeOpList(int index);
        void removeOpLists(int startIndex, int stopIndex);

        bool empty() const { return fOpLists.empty(); }
        int numOpLists() const { return fOpLists.count(); }

        GrOpList* opList(int index) { return fOpLists[index].get(); }
        const GrOpList* opList(int index) const { return fOpLists[index].get(); }

        GrOpList* back() { return fOpLists.back().get(); }
        const GrOpList* back() const { return fOpLists.back().get(); }

        void add(sk_sp<GrOpList>);
        void add(const SkTArray<sk_sp<GrOpList>>&);

        void swap(SkTArray<sk_sp<GrOpList>>* opLists);

        bool sortingOpLists() const { return fSortOpLists; }

    private:
        SkTArray<sk_sp<GrOpList>> fOpLists;
        bool                      fSortOpLists;
    };

    GrDrawingManager(GrRecordingContext*, const GrPathRendererChain::Options&,
                     const GrTextContext::Options&,
                     bool explicitlyAllocating,
                     bool sortOpLists,
                     GrContextOptions::Enable reduceOpListSplitting);

    bool wasAbandoned() const;

    void cleanup();

    // return true if any opLists were actually executed; false otherwise
    bool executeOpLists(int startIndex, int stopIndex, GrOpFlushState*, int* numOpListsExecuted);

    GrSemaphoresSubmitted flush(GrSurfaceProxy* proxy,
                                SkSurface::BackendSurfaceAccess access,
                                GrFlushFlags flags,
                                int numSemaphores,
                                GrBackendSemaphore backendSemaphores[],
                                GrGpuFinishedProc finishedProc,
                                GrGpuFinishedContext finishedContext);

    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;

    OpListDAG                         fDAG;
    GrOpList*                         fActiveOpList = nullptr;
    // These are the IDs of the opLists currently being flushed (in internalFlush)
    SkSTArray<8, uint32_t, true>      fFlushingOpListIDs;
    // These are the new opLists generated by the onFlush CBs
    SkSTArray<8, sk_sp<GrOpList>>     fOnFlushCBOpLists;

    std::unique_ptr<GrTextContext>    fTextContext;

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

    GrTokenTracker                    fTokenTracker;
    bool                              fFlushing;
    bool                              fReduceOpListSplitting;

    SkTArray<GrOnFlushCallbackObject*> fOnFlushCBObjects;
};

#endif