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