/* * 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 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 Make(const Caps* caps, sk_sp 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 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 targetProxy, const SkColorInfo& srcColorInfo, const SkColorInfo& dstColorInfo, const std::vector& levels, const SkIRect& dstRect, std::unique_ptr); // 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); // 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 snapDrawTask(Recorder*); private: DrawContext(const Caps*, sk_sp, const SkImageInfo&, const SkSurfaceProps&); sk_sp 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 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 fPendingDraws; std::unique_ptr fPendingUploads; // Load and store information for the current pending draws. LoadOp fPendingLoadOp = LoadOp::kLoad; StoreOp fPendingStoreOp = StoreOp::kStore; std::array 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 fComputePathAtlas; }; } // namespace skgpu::graphite #endif // skgpu_graphite_DrawContext_DEFINED