| /* |
| * 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/SkImageInfo.h" |
| #include "include/core/SkRefCnt.h" |
| #include "include/core/SkSurfaceProps.h" |
| #include "include/private/base/SkTArray.h" |
| |
| #include "src/gpu/graphite/DrawList.h" |
| #include "src/gpu/graphite/DrawOrder.h" |
| #include "src/gpu/graphite/DrawTypes.h" |
| #include "src/gpu/graphite/ResourceTypes.h" |
| #include "src/gpu/graphite/TextureProxyView.h" |
| #include "src/gpu/graphite/task/UploadTask.h" |
| |
| #include <vector> |
| |
| class SkPixmap; |
| |
| namespace skgpu::graphite { |
| |
| class Geometry; |
| class Recorder; |
| class Transform; |
| |
| class Caps; |
| class ComputePathAtlas; |
| class DrawTask; |
| class PathAtlas; |
| class Task; |
| class TextureProxy; |
| |
| /** |
| * 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: |
| static sk_sp<DrawContext> Make(const Caps* caps, |
| sk_sp<TextureProxy> target, |
| SkISize deviceSize, |
| const SkColorInfo&, |
| const SkSurfaceProps&); |
| |
| ~DrawContext() override; |
| |
| const SkImageInfo& imageInfo() const { return fImageInfo; } |
| const SkColorInfo& colorInfo() const { return fImageInfo.colorInfo(); } |
| TextureProxy* target() { return fTarget.get(); } |
| const TextureProxy* target() const { return fTarget.get(); } |
| sk_sp<TextureProxy> refTarget() const { return fTarget; } |
| |
| // May be null if the target is not texturable. |
| const TextureProxyView& readSurfaceView() const { return fReadView; } |
| |
| const SkSurfaceProps& surfaceProps() const { return fSurfaceProps; } |
| |
| int pendingRenderSteps() const { return fPendingDraws->renderStepCount(); } |
| |
| void clear(const SkColor4f& clearColor); |
| void discard(); |
| |
| void recordDraw(const Renderer* renderer, |
| const Transform& localToDevice, |
| const Geometry& geometry, |
| const Clip& clip, |
| DrawOrder ordering, |
| const PaintParams* paint, |
| const StrokeStyle* stroke); |
| |
| bool recordUpload(Recorder* recorder, |
| sk_sp<TextureProxy> targetProxy, |
| const SkColorInfo& srcColorInfo, |
| const SkColorInfo& dstColorInfo, |
| const std::vector<MipLevel>& levels, |
| const SkIRect& dstRect, |
| std::unique_ptr<ConditionalUploadContext>); |
| |
| // Add a Task that will be executed *before* any of the pending draws and uploads are |
| // executed as part of the next flush(). Dependency |
| 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*); |
| |
| // Flushes (if needed) and completes the current DrawTask, returning it to the caller. |
| // Subsequent recorded operations will be added to a new DrawTask. |
| sk_sp<Task> snapDrawTask(Recorder*); |
| |
| private: |
| DrawContext(const Caps*, sk_sp<TextureProxy>, const SkImageInfo&, const SkSurfaceProps&); |
| |
| sk_sp<TextureProxy> fTarget; |
| TextureProxyView fReadView; |
| SkImageInfo fImageInfo; |
| const SkSurfaceProps fSurfaceProps; |
| |
| // 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<DrawList> fPendingDraws; |
| std::unique_ptr<UploadList> fPendingUploads; |
| // Load and store information for the current pending draws. |
| LoadOp fPendingLoadOp = LoadOp::kLoad; |
| StoreOp fPendingStoreOp = StoreOp::kStore; |
| std::array<float, 4> fPendingClearColor = { 0, 0, 0, 0 }; |
| |
| // 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; |
| }; |
| |
| } // namespace skgpu::graphite |
| |
| #endif // skgpu_graphite_DrawContext_DEFINED |