• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2015 Google Inc.
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 
8 #ifndef AtlasTextOp_DEFINED
9 #define AtlasTextOp_DEFINED
10 
11 #include "src/gpu/effects/GrDistanceFieldGeoProc.h"
12 #include "src/gpu/ops/GrMeshDrawOp.h"
13 #include "src/gpu/text/GrTextBlob.h"
14 
15 class GrRecordingContext;
16 
17 namespace skgpu::v1 {
18 
19 class AtlasTextOp final : public GrMeshDrawOp {
20 public:
21     DEFINE_OP_CLASS_ID
22 
~AtlasTextOp()23     ~AtlasTextOp() override {
24         for (const Geometry* g = fHead; g != nullptr;) {
25             const Geometry* next = g->fNext;
26             g->~Geometry();
27             g = next;
28         }
29     }
30 
31     void* operator new(size_t s);
32     void operator delete(void* b) noexcept;
33     static void ClearCache();
34 
35     struct Geometry {
GeometryGeometry36         Geometry(const GrAtlasSubRun& subRun,
37                  const SkMatrix& drawMatrix,
38                  SkPoint drawOrigin,
39                  SkIRect clipRect,
40                  sk_sp<SkRefCnt> supportData,
41                  GrAtlasSubRunOwner subRunOwner,
42                  const SkPMColor4f& color)
43             : fSubRun{subRun}
44             , fSupportDataKeepAlive{std::move(supportData)}
45             , fSubRunDtor{std::move(subRunOwner)}
46             , fDrawMatrix{drawMatrix}
47             , fDrawOrigin{drawOrigin}
48             , fClipRect{clipRect}
49             , fColor{color} {
50                 SkASSERT(fSupportDataKeepAlive != nullptr || fSubRunDtor != nullptr);
51                 SkASSERT(SkToBool(fSubRunDtor) != SkToBool(fSupportDataKeepAlive));
52         }
53 
54         static Geometry* MakeForBlob(const GrAtlasSubRun& subRun,
55                                      const SkMatrix& drawMatrix,
56                                      SkPoint drawOrigin,
57                                      SkIRect clipRect,
58                                      sk_sp<SkRefCnt> supportData,
59                                      const SkPMColor4f& color,
60                                      SkArenaAlloc* alloc);
61 
62         void fillVertexData(void* dst, int offset, int count) const;
63 
64         const GrAtlasSubRun& fSubRun;
65 
66         // Either this Geometry holds a ref to the support data in the case of a blob based
67         // SubRun (WithCaching case), or it holds a unique_ptr to a SubRun allocated on the
68         // GrTextBlobAllocator in the NoCache case. It must hold one, and can't hold both.
69         sk_sp<SkRefCnt> fSupportDataKeepAlive;
70         GrAtlasSubRunOwner fSubRunDtor;
71 
72         const SkMatrix fDrawMatrix;
73         const SkPoint fDrawOrigin;
74 
75         // fClipRect is only used in the DirectMaskSubRun case to do geometric clipping.
76         // TransformedMaskSubRun, and SDFTSubRun don't use this field, and expect an empty rect.
77         const SkIRect fClipRect;
78 
79         // Color is updated after processor analysis if it was determined the shader resolves to
80         // a constant color that we then evaluate on the CPU.
81         // TODO: This can be made const once processor analysis is separated from op creation.
82         SkPMColor4f fColor;
83         Geometry* fNext{nullptr};
84     };
85 
name()86     const char* name() const override { return "AtlasTextOp"; }
87 
88     void visitProxies(const GrVisitProxyFunc&) const override;
89 
90     FixedFunctionFlags fixedFunctionFlags() const override;
91 
92     GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override;
93 
94     enum class MaskType : uint32_t {
95         kGrayscaleCoverage,
96         kLCDCoverage,
97         kColorBitmap,
98         kAliasedDistanceField,
99         kGrayscaleDistanceField,
100         kLCDDistanceField,
101         kLCDBGRDistanceField,
102 
103         kLast = kLCDBGRDistanceField
104     };
105     inline static constexpr int kMaskTypeCount = static_cast<int>(MaskType::kLast) + 1;
106 
107 #if GR_TEST_UTILS && SK_GPU_V1
108     static GrOp::Owner CreateOpTestingOnly(skgpu::v1::SurfaceDrawContext*,
109                                            const SkPaint&,
110                                            const SkFont&,
111                                            const SkMatrixProvider&,
112                                            const char* text,
113                                            int x,
114                                            int y);
115 #endif
116 
117 private:
118     friend class GrOp; // for ctor
119 
120     struct FlushInfo {
121         sk_sp<const GrBuffer> fVertexBuffer;
122         sk_sp<const GrBuffer> fIndexBuffer;
123         GrGeometryProcessor*  fGeometryProcessor;
124         const GrSurfaceProxy** fPrimProcProxies;
125         int fGlyphsToFlush = 0;
126         int fVertexOffset = 0;
127         int fNumDraws = 0;
128     };
129 
130     AtlasTextOp(MaskType maskType,
131                 bool needsTransform,
132                 int glyphCount,
133                 SkRect deviceRect,
134                 Geometry* geo,
135                 GrPaint&& paint);
136 
137     AtlasTextOp(MaskType maskType,
138                 bool needsTransform,
139                 int glyphCount,
140                 SkRect deviceRect,
141                 SkColor luminanceColor,
142                 bool useGammaCorrectDistanceTable,
143                 uint32_t DFGPFlags,
144                 Geometry* geo,
145                 GrPaint&& paint);
146 
programInfo()147     GrProgramInfo* programInfo() override {
148         // TODO [PI]: implement
149         return nullptr;
150     }
151 
addGeometry(Geometry * geometry)152     void addGeometry(Geometry* geometry) {
153         *fTail = geometry;
154         // The geometry may have many entries. Find the end.
155         do {
156             fTail = &(*fTail)->fNext;
157         } while (*fTail != nullptr);
158     }
159 
onCreateProgramInfo(const GrCaps *,SkArenaAlloc *,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip &&,const GrDstProxyView &,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)160     void onCreateProgramInfo(const GrCaps*,
161                              SkArenaAlloc*,
162                              const GrSurfaceProxyView& writeView,
163                              bool usesMSAASurface,
164                              GrAppliedClip&&,
165                              const GrDstProxyView&,
166                              GrXferBarrierFlags renderPassXferBarriers,
167                              GrLoadOp colorLoadOp) override {
168         // We cannot surface the AtlasTextOp's programInfo at record time. As currently
169         // implemented, the GP is modified at flush time based on the number of pages in the
170         // atlas.
171     }
172 
onPrePrepareDraws(GrRecordingContext *,const GrSurfaceProxyView & writeView,GrAppliedClip *,const GrDstProxyView &,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)173     void onPrePrepareDraws(GrRecordingContext*,
174                            const GrSurfaceProxyView& writeView,
175                            GrAppliedClip*,
176                            const GrDstProxyView&,
177                            GrXferBarrierFlags renderPassXferBarriers,
178                            GrLoadOp colorLoadOp) override {
179         // TODO [PI]: implement
180     }
181 
182     void onPrepareDraws(GrMeshDrawTarget*) override;
183     void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
184 
185 #if GR_TEST_UTILS
186     SkString onDumpInfo() const override;
187 #endif
188 
maskFormat()189     GrMaskFormat maskFormat() const {
190         switch (this->maskType()) {
191             case MaskType::kLCDCoverage:
192                 return kA565_GrMaskFormat;
193             case MaskType::kColorBitmap:
194                 return kARGB_GrMaskFormat;
195             case MaskType::kGrayscaleCoverage:
196             case MaskType::kAliasedDistanceField:
197             case MaskType::kGrayscaleDistanceField:
198             case MaskType::kLCDDistanceField:
199             case MaskType::kLCDBGRDistanceField:
200                 return kA8_GrMaskFormat;
201         }
202         // SkUNREACHABLE;
203         return kA8_GrMaskFormat;
204     }
205 
usesDistanceFields()206     bool usesDistanceFields() const {
207         return MaskType::kAliasedDistanceField == this->maskType() ||
208                MaskType::kGrayscaleDistanceField == this->maskType() ||
209                MaskType::kLCDDistanceField == this->maskType() ||
210                MaskType::kLCDBGRDistanceField == this->maskType();
211     }
212 
isLCD()213     bool isLCD() const {
214         return MaskType::kLCDCoverage == this->maskType() ||
215                MaskType::kLCDDistanceField == this->maskType() ||
216                MaskType::kLCDBGRDistanceField == this->maskType();
217     }
218 
219     inline void createDrawForGeneratedGlyphs(
220             GrMeshDrawTarget* target, FlushInfo* flushInfo) const;
221 
maskType()222     MaskType maskType() const { return static_cast<MaskType>(fMaskType); }
223 
224     CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override;
225 
226     GrGeometryProcessor* setupDfProcessor(SkArenaAlloc*,
227                                           const GrShaderCaps&,
228                                           const SkMatrix& localMatrix,
229                                           const GrSurfaceProxyView* views,
230                                           unsigned int numActiveViews) const;
231 
232     GrProcessorSet fProcessors;
233     int fNumGlyphs; // Sum of glyphs in each geometry's subrun
234 
235     // All combinable atlas ops have equal bit field values
236     uint32_t fDFGPFlags                    : 9; // Distance field properties
237     uint32_t fMaskType                     : 3; // MaskType
238     uint32_t fUsesLocalCoords              : 1; // Filled in post processor analysis
239     uint32_t fNeedsGlyphTransform          : 1;
240     uint32_t fHasPerspective               : 1; // True if perspective affects draw
241     uint32_t fUseGammaCorrectDistanceTable : 1;
242     static_assert(kMaskTypeCount <= 8, "MaskType does not fit in 3 bits");
243     static_assert(kInvalid_DistanceFieldEffectFlag <= (1 << 8),  "DFGP Flags do not fit in 9 bits");
244 
245     // Only used for distance fields; per-channel luminance for LCD, or gamma-corrected luminance
246     // for single-channel distance fields.
247     const SkColor fLuminanceColor{0};
248 
249     Geometry* fHead{nullptr};
250     Geometry** fTail{&fHead};
251 
252     using INHERITED = GrMeshDrawOp;
253 };
254 
255 } // namespace skgpu::v1
256 
257 #endif // AtlasTextOp_DEFINED
258