| /* | |
| * Copyright 2021 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef skgpu_graphite_DrawContext_DEFINED | |
| #define skgpu_graphite_DrawContext_DEFINED | |
| #include "include/core/SkColor.h" | |
| #include "include/core/SkImageInfo.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkSurfaceProps.h" | |
| #include "src/gpu/graphite/PaintParams.h" | |
| #include "src/gpu/graphite/TextureProxy.h" | |
| #include "src/gpu/graphite/TextureProxyView.h" | |
| #include "src/gpu/graphite/draw/DrawListBase.h" | |
| #include "src/gpu/graphite/layout/StorageContext.h" | |
| #include "src/gpu/graphite/task/UploadTask.h" | |
| #include <array> | |
| #include <memory> | |
| #include <vector> | |
| struct SkIRect; | |
| struct SkISize; | |
| namespace skgpu::graphite { | |
| class Caps; | |
| class Clip; | |
| class ComputePathAtlas; | |
| class ConditionalUploadContext; | |
| class DrawOrder; | |
| class DrawTask; | |
| class Geometry; | |
| class PaintParams; | |
| class PathAtlas; | |
| class Recorder; | |
| class Renderer; | |
| class StrokeStyle; | |
| class Task; | |
| class Transform; | |
| /** | |
| * DrawContext records draw commands into a specific Surface, via a general task graph | |
| * representing GPU work and their inter-dependencies. | |
| */ | |
| class DrawContext final : public SkRefCnt { | |
| public: | |
| // allowUnpremul=true should only be used if the target is only going to be rendered | |
| // into with src-blending with calls to drawPaint or pixel-aligned drawRect calls to | |
| // avoid anti-aliasing. | |
| static sk_sp<DrawContext> Make(const Caps* caps, | |
| sk_sp<TextureProxy> target, | |
| SkISize deviceSize, | |
| const SkColorInfo&, | |
| const SkSurfaceProps&, | |
| bool allowUnpremul); | |
| ~DrawContext() override; | |
| const SkImageInfo& imageInfo() const { return fImageInfo; } | |
| const SkColorInfo& colorInfo() const { return fImageInfo.colorInfo(); } | |
| const TextureProxyView& target() const { return fTarget; } | |
| bool isTexturable() const { return fIsTexturable; } | |
| const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; } | |
| int pendingRenderSteps() const { return fPendingDraws->renderStepCount(); } | |
| bool modifiesTarget() const { return fPendingDraws->modifiesTarget(); } | |
| bool readsTexture(const TextureProxy*) const; | |
| void clear(const SkColor4f& clearColor); | |
| void discard(); | |
| std::pair<DrawParams*, Layer*> recordDraw( | |
| const Renderer* renderer, | |
| const Transform& localToDevice, | |
| const Geometry& geometry, | |
| const Clip& clip, | |
| DrawOrder ordering, | |
| UniquePaintParamsID paintID, | |
| SkEnumBitMask<DstUsage> dstUsage, | |
| PipelineDataGatherer* gatherer, | |
| const StrokeStyle* stroke, | |
| Layer* lastInsertion=nullptr); | |
| bool recordUpload(Recorder* recorder, | |
| const UploadSource& source, | |
| std::unique_ptr<ConditionalUploadContext> = nullptr); | |
| // Add a Task that will be executed *before* any of the pending draws and uploads are | |
| // executed as part of the next flush(). | |
| void recordDependency(sk_sp<Task>); | |
| // Returns the transient path atlas that uses compute to accumulate coverage masks for atlas | |
| // draws recorded to this SDC. The atlas gets created lazily upon request. Returns nullptr | |
| // if compute path generation is not supported. | |
| PathAtlas* getComputePathAtlas(Recorder*); | |
| // Moves all accumulated pending recorded operations (draws and uploads), and any other | |
| // dependent tasks into the DrawTask currently being built. | |
| void flush(Recorder*); | |
| // Returns the current DrawTask to the caller, so all pending draws and uploads (if flush() | |
| // was not immediately called prior to this) and subsequently recorded draws and uploads will | |
| // go into a new DrawTask. | |
| sk_sp<Task> snapDrawTask(); | |
| // Returns the dst read strategy to use when/if a paint requires a dst read | |
| DstReadStrategy dstReadStrategy() const { return fDstReadStrategy; } | |
| StorageContext* storageContext() { | |
| return &fStorageContext; | |
| } | |
| private: | |
| DrawContext(const Caps*, sk_sp<TextureProxy>, const SkImageInfo&, const SkSurfaceProps&); | |
| void resetForClearOrDiscard(); | |
| // May not be texturable, but preserves the read swizzle if it were to be read back to CPU or | |
| // copied to a texturable proxy. | |
| TextureProxyView fTarget; | |
| SkImageInfo fImageInfo; | |
| const SkSurfaceProps fSurfaceProps; | |
| bool fIsTexturable; // Cache at creation so we don't require constant Caps access | |
| // Does *not* reflect whether a dst read is needed by the DrawLists - simply specifies the | |
| // strategies to use should any encountered paint require it. | |
| const DstReadStrategy fDstReadStrategy; | |
| const bool fSupportsHardwareAdvancedBlend; | |
| const bool fAdvancedBlendsRequireBarrier; | |
| // The in-progress DrawTask that will be snapped and returned when some external requirement | |
| // must depend on the contents of this DrawContext's target. As higher-level Skia operations | |
| // are recorded, it can be necessary to flush pending draws and uploads into the task list. | |
| // This provides a place to reset scratch textures or buffers as their previous state will have | |
| // been consumed by the flushed tasks rendering to this DrawContext's target. | |
| sk_sp<DrawTask> fCurrentDrawTask; | |
| // Stores the most immediately recorded draws and uploads into the DrawContext's target. These | |
| // are collected outside of the DrawTask so that encoder switches can be minimized when | |
| // flushing. | |
| std::unique_ptr<DrawListBase> fPendingDraws; | |
| std::unique_ptr<UploadList> fPendingUploads; | |
| // Accumulates atlas coverage masks generated by compute dispatches that are required by one or | |
| // more entries in `fPendingDraws`. When pending draws are snapped into a new DrawPass, a | |
| // compute dispatch group gets recorded which schedules the accumulated masks to get drawn into | |
| // an atlas texture. The accumulated masks are then cleared which frees up the atlas for | |
| // future draws. | |
| // | |
| // TODO: Currently every PathAtlas contains a single texture. If multiple snapped draw | |
| // passes resulted in multiple ComputePathAtlas dispatch groups, the later dispatches would | |
| // overwrite the atlas texture since all compute tasks are scheduled before render tasks. This | |
| // is currently not an issue since there is only one DrawPass per flush but we may want to | |
| // either support one atlas texture per DrawPass or record the dispatches once per | |
| // RenderPassTask rather than DrawPass. | |
| std::unique_ptr<ComputePathAtlas> fComputePathAtlas; | |
| StorageContext fStorageContext; | |
| }; | |
| } // namespace skgpu::graphite | |
| #endif // skgpu_graphite_DrawContext_DEFINED |