/* * 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