Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/gpu/ops/GrAtlasTextOp.h
Line
Count
Source (jump to first uncovered line)
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
27
520
    ~GrAtlasTextOp() override {
28
1.04k
        for (const Geometry* g = fHead; g != nullptr;) {
29
520
            const Geometry* next = g->fNext;
30
520
            g->~Geometry();
31
520
            g = next;
32
520
        }
33
520
    }
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
40
    static void ClearCache() {}
41
#endif
42
43
    static const int kVerticesPerGlyph = GrAtlasSubRun::kVerticesPerGlyph;
44
    static const int kIndicesPerGlyph = 6;
45
46
    struct Geometry {
47
        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
520
            , fColor{color} {
61
520
                SkASSERT(fBlob != nullptr || fSubRunDtor != nullptr);
62
520
                SkASSERT(SkToBool(fSubRunDtor) != SkToBool(fBlob));
63
520
        }
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
97
0
    const char* name() const override { return "AtlasTextOp"; }
98
99
    void visitProxies(const GrVisitProxyFunc&) 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 && SK_GPU_V1
119
    static GrOp::Owner CreateOpTestingOnly(skgpu::v1::SurfaceDrawContext*,
120
                                           const SkPaint&,
121
                                           const SkFont&,
122
                                           const SkMatrixProvider&,
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
158
0
    GrProgramInfo* programInfo() override {
159
        // TODO [PI]: implement
160
0
        return nullptr;
161
0
    }
162
163
173
    void addGeometry(Geometry* geometry) {
164
173
        *fTail = geometry;
165
        // The geometry may have many entries. Find the end.
166
173
        do {
167
173
            fTail = &(*fTail)->fNext;
168
173
        } while (*fTail != nullptr);
169
173
    }
170
171
    void onCreateProgramInfo(const GrCaps*,
172
                             SkArenaAlloc*,
173
                             const GrSurfaceProxyView& writeView,
174
                             bool usesMSAASurface,
175
                             GrAppliedClip&&,
176
                             const GrDstProxyView&,
177
                             GrXferBarrierFlags renderPassXferBarriers,
178
0
                             GrLoadOp colorLoadOp) override {
179
        // We cannot surface the GrAtlasTextOp's programInfo at record time. As currently
180
        // implemented, the GP is modified at flush time based on the number of pages in the
181
        // atlas.
182
0
    }
183
184
    void onPrePrepareDraws(GrRecordingContext*,
185
                           const GrSurfaceProxyView& writeView,
186
                           GrAppliedClip*,
187
                           const GrDstProxyView&,
188
                           GrXferBarrierFlags renderPassXferBarriers,
189
0
                           GrLoadOp colorLoadOp) override {
190
        // TODO [PI]: implement
191
0
    }
192
193
    void onPrepareDraws(GrMeshDrawTarget*) override;
194
    void onExecute(GrOpFlushState*, const SkRect& chainBounds) override;
195
196
#if GR_TEST_UTILS
197
    SkString onDumpInfo() const override;
198
#endif
199
200
670
    GrMaskFormat maskFormat() const {
201
670
        switch (this->maskType()) {
202
0
            case MaskType::kLCDCoverage:
203
0
                return kA565_GrMaskFormat;
204
8
            case MaskType::kColorBitmap:
205
8
                return kARGB_GrMaskFormat;
206
532
            case MaskType::kGrayscaleCoverage:
207
586
            case MaskType::kAliasedDistanceField:
208
662
            case MaskType::kGrayscaleDistanceField:
209
662
            case MaskType::kLCDDistanceField:
210
662
            case MaskType::kLCDBGRDistanceField:
211
662
                return kA8_GrMaskFormat;
212
0
        }
213
        // SkUNREACHABLE;
214
0
        return kA8_GrMaskFormat;
215
0
    }
216
217
622
    bool usesDistanceFields() const {
218
622
        return MaskType::kAliasedDistanceField == this->maskType() ||
219
582
               MaskType::kGrayscaleDistanceField == this->maskType() ||
220
520
               MaskType::kLCDDistanceField == this->maskType() ||
221
520
               MaskType::kLCDBGRDistanceField == this->maskType();
222
622
    }
223
224
78
    bool isLCD() const {
225
78
        return MaskType::kLCDCoverage == this->maskType() ||
226
78
               MaskType::kLCDDistanceField == this->maskType() ||
227
78
               MaskType::kLCDBGRDistanceField == this->maskType();
228
78
    }
229
230
    inline void createDrawForGeneratedGlyphs(
231
            GrMeshDrawTarget* target, FlushInfo* flushInfo) const;
232
233
4.37k
    MaskType maskType() const { return static_cast<MaskType>(fMaskType); }
234
235
    CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override;
236
237
    GrGeometryProcessor* setupDfProcessor(SkArenaAlloc*,
238
                                          const GrShaderCaps&,
239
                                          const SkMatrix& localMatrix,
240
                                          const GrSurfaceProxyView* views,
241
                                          unsigned int numActiveViews) const;
242
243
    GrProcessorSet fProcessors;
244
    int fNumGlyphs; // Sum of glyphs in each geometry's subrun
245
246
    // All combinable atlas ops have equal bit field values
247
    uint32_t fDFGPFlags                    : 9; // Distance field properties
248
    uint32_t fMaskType                     : 3; // MaskType
249
    uint32_t fUsesLocalCoords              : 1; // Filled in post processor analysis
250
    uint32_t fNeedsGlyphTransform          : 1;
251
    uint32_t fHasPerspective               : 1; // True if perspective affects draw
252
    uint32_t fUseGammaCorrectDistanceTable : 1;
253
    static_assert(kMaskTypeCount <= 8, "MaskType does not fit in 3 bits");
254
    static_assert(kInvalid_DistanceFieldEffectFlag <= (1 << 8),  "DFGP Flags do not fit in 9 bits");
255
256
    // Only used for distance fields; per-channel luminance for LCD, or gamma-corrected luminance
257
    // for single-channel distance fields.
258
    const SkColor fLuminanceColor{0};
259
260
    Geometry* fHead{nullptr};
261
    Geometry** fTail{&fHead};
262
263
    using INHERITED = GrMeshDrawOp;
264
};
265
266
#endif