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