xref: /aosp_15_r20/external/skia/src/gpu/ganesh/SurfaceFillContext.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2021 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #ifndef SurfaceFillContext_DEFINED
8 #define SurfaceFillContext_DEFINED
9 
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkColor.h"
12 #include "include/core/SkMatrix.h"
13 #include "include/core/SkRect.h"
14 #include "include/core/SkRefCnt.h"
15 #include "include/private/SkColorData.h"
16 #include "include/private/base/SkDebug.h"
17 #include "src/gpu/ganesh/GrColorInfo.h"
18 #include "src/gpu/ganesh/GrFragmentProcessor.h"
19 #include "src/gpu/ganesh/GrRenderTargetProxy.h"
20 #include "src/gpu/ganesh/GrSurfaceProxy.h"
21 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
22 #include "src/gpu/ganesh/SurfaceContext.h"
23 #include "src/gpu/ganesh/ops/GrOp.h"
24 #include "src/gpu/ganesh/ops/OpsTask.h"
25 
26 #include <array>
27 #include <memory>
28 #include <utility>
29 
30 class GrPaint;
31 class GrRecordingContext;
32 class GrRenderTask;
33 class SkArenaAlloc;
34 struct SkIPoint;
35 
36 namespace sktext::gpu {
37 class SubRunAllocator;
38 }
39 
40 namespace skgpu::ganesh {
41 
42 class SurfaceFillContext : public SurfaceContext {
43 public:
44     SurfaceFillContext(GrRecordingContext* rContext,
45                        GrSurfaceProxyView readView,
46                        GrSurfaceProxyView writeView,
47                        const GrColorInfo& colorInfo);
48 
asFillContext()49     SurfaceFillContext* asFillContext() override { return this; }
50 
51     OpsTask* getOpsTask();
52 
53 #if defined(GPU_TEST_UTILS)
testingOnly_PeekLastOpsTask()54     OpsTask* testingOnly_PeekLastOpsTask() { return fOpsTask.get(); }
55 #endif
56 
57     /**
58      * Provides a performance hint that the render target's contents are allowed
59      * to become undefined.
60      */
61     void discard();
62 
63     void resolveMSAA();
64 
65     /**
66      * Clear the rect of the render target to the given color.
67      * @param rect  the rect to clear to
68      * @param color the color to clear to.
69      */
70     template <SkAlphaType AlphaType>
clear(const SkIRect & rect,const SkRGBA4f<AlphaType> & color)71     void clear(const SkIRect& rect, const SkRGBA4f<AlphaType>& color) {
72         this->internalClear(&rect, this->adjustColorAlphaType(color));
73     }
74 
75     /** Clears the entire render target to the color. */
clear(const SkRGBA4f<AlphaType> & color)76     template <SkAlphaType AlphaType> void clear(const SkRGBA4f<AlphaType>& color) {
77         this->internalClear(nullptr, this->adjustColorAlphaType(color));
78     }
79 
80     /**
81      * Clear at minimum the pixels within 'scissor', but is allowed to clear the full render target
82      * if that is the more performant option.
83      */
84     template <SkAlphaType AlphaType>
clearAtLeast(const SkIRect & scissor,const SkRGBA4f<AlphaType> & color)85     void clearAtLeast(const SkIRect& scissor, const SkRGBA4f<AlphaType>& color) {
86         this->internalClear(&scissor,
87                             this->adjustColorAlphaType(color),
88                             /* upgrade to full */ true);
89     }
90 
91     /** Fills 'dstRect' with 'fp' */
92     void fillRectWithFP(const SkIRect& dstRect, std::unique_ptr<GrFragmentProcessor>);
93 
94     /**
95      * A convenience version of fillRectWithFP that applies a coordinate transformation via
96      * GrMatrixEffect.
97      */
98     void fillRectWithFP(const SkIRect& dstRect,
99                         const SkMatrix& localMatrix,
100                         std::unique_ptr<GrFragmentProcessor>);
101 
102     /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */
fillRectToRectWithFP(const SkRect & srcRect,const SkIRect & dstRect,std::unique_ptr<GrFragmentProcessor> fp)103     void fillRectToRectWithFP(const SkRect& srcRect,
104                               const SkIRect& dstRect,
105                               std::unique_ptr<GrFragmentProcessor> fp) {
106         SkMatrix lm = SkMatrix::RectToRect(SkRect::Make(dstRect), srcRect);
107         this->fillRectWithFP(dstRect, lm, std::move(fp));
108     }
109 
110     /** Fills 'dstRect' with 'fp' using a local matrix that maps 'srcRect' to 'dstRect' */
fillRectToRectWithFP(const SkIRect & srcRect,const SkIRect & dstRect,std::unique_ptr<GrFragmentProcessor> fp)111     void fillRectToRectWithFP(const SkIRect& srcRect,
112                               const SkIRect& dstRect,
113                               std::unique_ptr<GrFragmentProcessor> fp) {
114         this->fillRectToRectWithFP(SkRect::Make(srcRect), dstRect, std::move(fp));
115     }
116 
117     /** Fills the entire render target with the passed FP. */
fillWithFP(std::unique_ptr<GrFragmentProcessor> fp)118     void fillWithFP(std::unique_ptr<GrFragmentProcessor> fp) {
119         this->fillRectWithFP(SkIRect::MakeSize(fWriteView.proxy()->dimensions()), std::move(fp));
120     }
121 
122     /**
123      * Draws the src texture with no matrix. The dstRect is the dstPoint with the width and height
124      * of the srcRect. The srcRect and dstRect are clipped to the bounds of the src and dst surfaces
125      * respectively.
126      */
127     bool blitTexture(GrSurfaceProxyView,
128                      const SkIRect& srcRect,
129                      const SkIPoint& dstPoint);
130 
131     sk_sp<GrRenderTask> refRenderTask();
132 
numSamples()133     int numSamples() const { return this->asRenderTargetProxy()->numSamples(); }
wrapsVkSecondaryCB()134     bool wrapsVkSecondaryCB() const { return this->asRenderTargetProxy()->wrapsVkSecondaryCB(); }
135 
arenaAlloc()136     SkArenaAlloc* arenaAlloc() { return this->arenas()->arenaAlloc(); }
subRunAlloc()137     sktext::gpu::SubRunAllocator* subRunAlloc() { return this->arenas()->subRunAlloc(); }
138 
writeSurfaceView()139     const GrSurfaceProxyView& writeSurfaceView() const { return fWriteView; }
140 
141 protected:
142     OpsTask* replaceOpsTask();
143 
144     /**
145      * Creates a constant color paint for a clear, using src-over if possible to improve batching.
146      */
147     static void ClearToGrPaint(std::array<float, 4> color, GrPaint* paint);
148 
149     void addOp(GrOp::Owner);
150 
151     template <SkAlphaType AlphaType>
152     static std::array<float, 4> ConvertColor(SkRGBA4f<AlphaType> color);
153 
154     template <SkAlphaType AlphaType>
155     std::array<float, 4> adjustColorAlphaType(SkRGBA4f<AlphaType> color) const;
156 
157     GrSurfaceProxyView fWriteView;
158 
159 private:
arenas()160     sk_sp<GrArenas> arenas() { return fWriteView.proxy()->asRenderTargetProxy()->arenas(); }
161 
162     void addDrawOp(GrOp::Owner);
163 
164     /** Override to be notified in subclass before the current ops task is replaced. */
willReplaceOpsTask(OpsTask * prevTask,OpsTask * nextTask)165     virtual void willReplaceOpsTask(OpsTask* prevTask, OpsTask* nextTask) {}
166 
167     /**
168      * Override to be called to participate in the decision to discard all previous ops if a
169      * fullscreen clear occurs.
170      */
canDiscardPreviousOpsOnFullClear()171     virtual OpsTask::CanDiscardPreviousOps canDiscardPreviousOpsOnFullClear() const {
172         return OpsTask::CanDiscardPreviousOps::kYes;
173     }
174 
175     void internalClear(const SkIRect* scissor,
176                        std::array<float, 4> color,
177                        bool upgradePartialToFull = false);
178 
179     SkDEBUGCODE(void onValidate() const override;)
180 
181     // The OpsTask can be closed by some other surface context that has picked it up. For this
182     // reason, the OpsTask should only ever be accessed via 'getOpsTask'.
183     sk_sp<OpsTask> fOpsTask;
184 
185     using INHERITED = SurfaceContext;
186 };
187 
188 template<>
189 inline std::array<float, 4> SurfaceFillContext::ConvertColor<kPremul_SkAlphaType>(
190         SkPMColor4f color) {
191     return color.unpremul().array();
192 }
193 
194 template<>
195 inline std::array<float, 4> SurfaceFillContext::ConvertColor<kUnpremul_SkAlphaType>(
196         SkColor4f color) {
197     return color.premul().array();
198 }
199 
200 template <SkAlphaType AlphaType>
adjustColorAlphaType(SkRGBA4f<AlphaType> color)201 std::array<float, 4> SurfaceFillContext::adjustColorAlphaType(SkRGBA4f<AlphaType> color) const {
202     if (AlphaType == kUnknown_SkAlphaType ||
203         this->colorInfo().alphaType() == kUnknown_SkAlphaType) {
204         return color.array();
205     }
206     return (AlphaType == this->colorInfo().alphaType()) ? color.array() : ConvertColor(color);
207 }
208 
209 }  // namespace skgpu::ganesh
210 
211 #endif // SurfaceFillContext_DEFINED
212