Coverage Report

Created: 2024-09-14 07:19

/src/skia/src/gpu/ganesh/text/GrAtlasManager.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2018 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
#include "src/gpu/ganesh/text/GrAtlasManager.h"
9
10
#include "include/core/SkColorType.h"
11
#include "include/core/SkSize.h"
12
#include "include/core/SkSpan.h"
13
#include "include/private/base/SkMalloc.h"
14
#include "include/private/base/SkTLogic.h"
15
#include "src/base/SkAutoMalloc.h"
16
#include "src/core/SkDistanceFieldGen.h"
17
#include "src/core/SkGlyph.h"
18
#include "src/core/SkMask.h"
19
#include "src/core/SkMasks.h"
20
#include "src/core/SkStrikeSpec.h"
21
#include "src/gpu/ganesh/GrColor.h"
22
#include "src/gpu/ganesh/GrDeferredUpload.h"
23
#include "src/gpu/ganesh/GrMeshDrawTarget.h"
24
#include "src/text/gpu/Glyph.h"
25
#include "src/text/gpu/GlyphVector.h"
26
#include "src/text/gpu/StrikeCache.h"
27
28
#include <cstring>
29
#include <tuple>
30
31
using Glyph = sktext::gpu::Glyph;
32
using MaskFormat = skgpu::MaskFormat;
33
34
GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider,
35
                               size_t maxTextureBytes,
36
                               GrDrawOpAtlas::AllowMultitexturing allowMultitexturing,
37
                               bool supportBilerpAtlas)
38
            : fAllowMultitexturing{allowMultitexturing}
39
            , fSupportBilerpAtlas{supportBilerpAtlas}
40
            , fProxyProvider{proxyProvider}
41
            , fCaps{fProxyProvider->refCaps()}
42
4.32k
            , fAtlasConfig{fCaps->maxTextureSize(), maxTextureBytes} { }
43
44
4.32k
GrAtlasManager::~GrAtlasManager() = default;
45
46
0
void GrAtlasManager::freeAll() {
47
0
    for (int i = 0; i < skgpu::kMaskFormatCount; ++i) {
48
0
        fAtlases[i] = nullptr;
49
0
    }
50
0
}
51
52
20.6k
bool GrAtlasManager::hasGlyph(MaskFormat format, Glyph* glyph) {
53
20.6k
    SkASSERT(glyph);
54
20.6k
    return this->getAtlas(format)->hasID(glyph->fAtlasLocator.plotLocator());
55
20.6k
}
56
57
template <typename INT_TYPE>
58
static void expand_bits(INT_TYPE* dst,
59
                        const uint8_t* src,
60
                        int width,
61
                        int height,
62
                        int dstRowBytes,
63
286
                        int srcRowBytes) {
64
6.86k
    for (int y = 0; y < height; ++y) {
65
6.57k
        int rowWritesLeft = width;
66
6.57k
        const uint8_t* s = src;
67
6.57k
        INT_TYPE* d = dst;
68
57.3k
        while (rowWritesLeft > 0) {
69
50.7k
            unsigned mask = *s++;
70
437k
            for (int x = 7; x >= 0 && rowWritesLeft; --x, --rowWritesLeft) {
71
386k
                *d++ = (mask & (1 << x)) ? (INT_TYPE)(~0UL) : 0;
72
386k
            }
73
50.7k
        }
74
6.57k
        dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
75
6.57k
        src += srcRowBytes;
76
6.57k
    }
77
286
}
GrAtlasManager.cpp:void expand_bits<unsigned char>(unsigned char*, unsigned char const*, int, int, int, int)
Line
Count
Source
63
286
                        int srcRowBytes) {
64
6.86k
    for (int y = 0; y < height; ++y) {
65
6.57k
        int rowWritesLeft = width;
66
6.57k
        const uint8_t* s = src;
67
6.57k
        INT_TYPE* d = dst;
68
57.3k
        while (rowWritesLeft > 0) {
69
50.7k
            unsigned mask = *s++;
70
437k
            for (int x = 7; x >= 0 && rowWritesLeft; --x, --rowWritesLeft) {
71
386k
                *d++ = (mask & (1 << x)) ? (INT_TYPE)(~0UL) : 0;
72
386k
            }
73
50.7k
        }
74
6.57k
        dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
75
6.57k
        src += srcRowBytes;
76
6.57k
    }
77
286
}
Unexecuted instantiation: GrAtlasManager.cpp:void expand_bits<unsigned short>(unsigned short*, unsigned char const*, int, int, int, int)
78
79
static void get_packed_glyph_image(
80
1.06k
        const SkGlyph& glyph, int dstRB, MaskFormat expectedMaskFormat, void* dst) {
81
1.06k
    const int width = glyph.width();
82
1.06k
    const int height = glyph.height();
83
1.06k
    const void* src = glyph.image();
84
1.06k
    SkASSERT(src != nullptr);
85
86
1.06k
    MaskFormat maskFormat = Glyph::FormatFromSkGlyph(glyph.maskFormat());
87
1.06k
    if (maskFormat == expectedMaskFormat) {
88
1.06k
        int srcRB = glyph.rowBytes();
89
        // Notice this comparison is with the glyphs raw mask format, and not its MaskFormat.
90
1.06k
        if (glyph.maskFormat() != SkMask::kBW_Format) {
91
780
            if (srcRB != dstRB) {
92
6
                const int bbp = MaskFormatBytesPerPixel(expectedMaskFormat);
93
18
                for (int y = 0; y < height; y++) {
94
12
                    memcpy(dst, src, width * bbp);
95
12
                    src = (const char*) src + srcRB;
96
12
                    dst = (char*) dst + dstRB;
97
12
                }
98
774
            } else {
99
774
                memcpy(dst, src, dstRB * height);
100
774
            }
101
780
        } else {
102
            // Handle 8-bit format by expanding the mask to the expected format.
103
286
            const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
104
286
            switch (expectedMaskFormat) {
105
286
                case MaskFormat::kA8: {
106
286
                    uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
107
286
                    expand_bits(bytes, bits, width, height, dstRB, srcRB);
108
286
                    break;
109
0
                }
110
0
                case MaskFormat::kA565: {
111
0
                    uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
112
0
                    expand_bits(rgb565, bits, width, height, dstRB, srcRB);
113
0
                    break;
114
0
                }
115
0
                default:
116
0
                    SK_ABORT("Invalid MaskFormat");
117
286
            }
118
286
        }
119
1.06k
    } else if (maskFormat == MaskFormat::kA565 &&
120
0
               expectedMaskFormat == MaskFormat::kARGB) {
121
        // Convert if the glyph uses a 565 mask format since it is using LCD text rendering
122
        // but the expected format is 8888 (will happen on macOS with Metal since that
123
        // combination does not support 565).
124
0
        static constexpr SkMasks masks{
125
0
                {0b1111'1000'0000'0000, 11, 5},  // Red
126
0
                {0b0000'0111'1110'0000,  5, 6},  // Green
127
0
                {0b0000'0000'0001'1111,  0, 5},  // Blue
128
0
                {0, 0, 0}                        // Alpha
129
0
        };
130
0
        constexpr int a565Bpp = MaskFormatBytesPerPixel(MaskFormat::kA565);
131
0
        constexpr int argbBpp = MaskFormatBytesPerPixel(MaskFormat::kARGB);
132
0
        constexpr bool kBGRAIsNative = kN32_SkColorType == kBGRA_8888_SkColorType;
133
0
        char* dstRow = (char*)dst;
134
0
        for (int y = 0; y < height; y++) {
135
0
            dst = dstRow;
136
0
            for (int x = 0; x < width; x++) {
137
0
                uint16_t color565 = 0;
138
0
                memcpy(&color565, src, a565Bpp);
139
0
                uint32_t color8888;
140
                // On Windows (and possibly others), font data is stored as BGR.
141
                // So we need to swizzle the data to reflect that.
142
0
                if (kBGRAIsNative) {
143
0
                    color8888 = GrColorPackRGBA(masks.getBlue(color565),
144
0
                                                masks.getGreen(color565),
145
0
                                                masks.getRed(color565),
146
0
                                                0xFF);
147
0
                } else {
148
0
                    color8888 = GrColorPackRGBA(masks.getRed(color565),
149
0
                                                masks.getGreen(color565),
150
0
                                                masks.getBlue(color565),
151
0
                                                0xFF);
152
0
                }
153
0
                memcpy(dst, &color8888, argbBpp);
154
0
                src = (const char*)src + a565Bpp;
155
0
                dst = (char*)dst + argbBpp;
156
0
            }
157
0
            dstRow += dstRB;
158
0
        }
159
0
    } else {
160
0
        SkUNREACHABLE;
161
0
    }
162
1.06k
}
GrAtlasManager.cpp:get_packed_glyph_image(SkGlyph const&, int, skgpu::MaskFormat, void*)
Line
Count
Source
80
1.06k
        const SkGlyph& glyph, int dstRB, MaskFormat expectedMaskFormat, void* dst) {
81
1.06k
    const int width = glyph.width();
82
1.06k
    const int height = glyph.height();
83
1.06k
    const void* src = glyph.image();
84
1.06k
    SkASSERT(src != nullptr);
85
86
1.06k
    MaskFormat maskFormat = Glyph::FormatFromSkGlyph(glyph.maskFormat());
87
1.06k
    if (maskFormat == expectedMaskFormat) {
88
1.06k
        int srcRB = glyph.rowBytes();
89
        // Notice this comparison is with the glyphs raw mask format, and not its MaskFormat.
90
1.06k
        if (glyph.maskFormat() != SkMask::kBW_Format) {
91
780
            if (srcRB != dstRB) {
92
6
                const int bbp = MaskFormatBytesPerPixel(expectedMaskFormat);
93
18
                for (int y = 0; y < height; y++) {
94
12
                    memcpy(dst, src, width * bbp);
95
12
                    src = (const char*) src + srcRB;
96
12
                    dst = (char*) dst + dstRB;
97
12
                }
98
774
            } else {
99
774
                memcpy(dst, src, dstRB * height);
100
774
            }
101
780
        } else {
102
            // Handle 8-bit format by expanding the mask to the expected format.
103
286
            const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
104
286
            switch (expectedMaskFormat) {
105
286
                case MaskFormat::kA8: {
106
286
                    uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
107
286
                    expand_bits(bytes, bits, width, height, dstRB, srcRB);
108
286
                    break;
109
0
                }
110
0
                case MaskFormat::kA565: {
111
0
                    uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
112
0
                    expand_bits(rgb565, bits, width, height, dstRB, srcRB);
113
0
                    break;
114
0
                }
115
0
                default:
116
0
                    SK_ABORT("Invalid MaskFormat");
117
286
            }
118
286
        }
119
1.06k
    } else if (maskFormat == MaskFormat::kA565 &&
120
0
               expectedMaskFormat == MaskFormat::kARGB) {
121
        // Convert if the glyph uses a 565 mask format since it is using LCD text rendering
122
        // but the expected format is 8888 (will happen on macOS with Metal since that
123
        // combination does not support 565).
124
0
        static constexpr SkMasks masks{
125
0
                {0b1111'1000'0000'0000, 11, 5},  // Red
126
0
                {0b0000'0111'1110'0000,  5, 6},  // Green
127
0
                {0b0000'0000'0001'1111,  0, 5},  // Blue
128
0
                {0, 0, 0}                        // Alpha
129
0
        };
130
0
        constexpr int a565Bpp = MaskFormatBytesPerPixel(MaskFormat::kA565);
131
0
        constexpr int argbBpp = MaskFormatBytesPerPixel(MaskFormat::kARGB);
132
0
        constexpr bool kBGRAIsNative = kN32_SkColorType == kBGRA_8888_SkColorType;
133
0
        char* dstRow = (char*)dst;
134
0
        for (int y = 0; y < height; y++) {
135
0
            dst = dstRow;
136
0
            for (int x = 0; x < width; x++) {
137
0
                uint16_t color565 = 0;
138
0
                memcpy(&color565, src, a565Bpp);
139
0
                uint32_t color8888;
140
                // On Windows (and possibly others), font data is stored as BGR.
141
                // So we need to swizzle the data to reflect that.
142
0
                if (kBGRAIsNative) {
143
0
                    color8888 = GrColorPackRGBA(masks.getBlue(color565),
144
0
                                                masks.getGreen(color565),
145
0
                                                masks.getRed(color565),
146
0
                                                0xFF);
147
0
                } else {
148
0
                    color8888 = GrColorPackRGBA(masks.getRed(color565),
149
0
                                                masks.getGreen(color565),
150
0
                                                masks.getBlue(color565),
151
0
                                                0xFF);
152
0
                }
153
0
                memcpy(dst, &color8888, argbBpp);
154
0
                src = (const char*)src + a565Bpp;
155
0
                dst = (char*)dst + argbBpp;
156
0
            }
157
0
            dstRow += dstRB;
158
0
        }
159
0
    } else {
160
0
        SkUNREACHABLE;
161
0
    }
162
1.06k
}
Unexecuted instantiation: GrAtlasManager.cpp:get_packed_glyph_image(SkGlyph const&, int, skgpu::MaskFormat, void*)
163
164
// returns true if glyph successfully added to texture atlas, false otherwise.
165
GrDrawOpAtlas::ErrorCode GrAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph,
166
                                                         Glyph* glyph,
167
                                                         int srcPadding,
168
                                                         GrResourceProvider* resourceProvider,
169
1.06k
                                                         GrDeferredUploadTarget* uploadTarget) {
170
1.06k
#if !defined(SK_DISABLE_SDF_TEXT)
171
1.06k
    SkASSERT(0 <= srcPadding && srcPadding <= SK_DistanceFieldInset);
172
#else
173
    SkASSERT(0 <= srcPadding);
174
#endif
175
176
1.06k
    if (skGlyph.image() == nullptr) {
177
0
        return GrDrawOpAtlas::ErrorCode::kError;
178
0
    }
179
1.06k
    SkASSERT(glyph != nullptr);
180
181
1.06k
    MaskFormat glyphFormat = Glyph::FormatFromSkGlyph(skGlyph.maskFormat());
182
1.06k
    MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
183
1.06k
    int bytesPerPixel = MaskFormatBytesPerPixel(expectedMaskFormat);
184
185
1.06k
    int padding;
186
1.06k
    switch (srcPadding) {
187
888
        case 0:
188
            // The direct mask/image case.
189
888
            padding = 0;
190
888
            if (fSupportBilerpAtlas) {
191
                // Force direct masks (glyph with no padding) to have padding.
192
0
                padding = 1;
193
0
                srcPadding = 1;
194
0
            }
195
888
            break;
196
11
        case 1:
197
            // The transformed mask/image case.
198
11
            padding = 1;
199
11
            break;
200
0
#if !defined(SK_DISABLE_SDF_TEXT)
201
167
        case SK_DistanceFieldInset:
202
            // The SDFT case.
203
            // If the srcPadding == SK_DistanceFieldInset (SDFT case) then the padding is built
204
            // into the image on the glyph; no extra padding needed.
205
            // TODO: can the SDFT glyph image in the cache be reduced by the padding?
206
167
            padding = 0;
207
167
            break;
208
0
#endif
209
0
        default:
210
            // The padding is not one of the know forms.
211
0
            return GrDrawOpAtlas::ErrorCode::kError;
212
1.06k
    }
213
214
1.06k
    const int width = skGlyph.width() + 2*padding;
215
1.06k
    const int height = skGlyph.height() + 2*padding;
216
1.06k
    int rowBytes = width * bytesPerPixel;
217
1.06k
    size_t size = height * rowBytes;
218
219
    // Temporary storage for normalizing glyph image.
220
1.06k
    SkAutoSMalloc<1024> storage(size);
221
1.06k
    void* dataPtr = storage.get();
222
1.06k
    if (padding > 0) {
223
11
        sk_bzero(dataPtr, size);
224
        // Advance in one row and one column.
225
11
        dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
226
11
    }
227
228
1.06k
    get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr);
229
230
1.06k
    auto errorCode = this->addToAtlas(resourceProvider,
231
1.06k
                                      uploadTarget,
232
1.06k
                                      expectedMaskFormat,
233
1.06k
                                      width,
234
1.06k
                                      height,
235
1.06k
                                      storage.get(),
236
1.06k
                                      &glyph->fAtlasLocator);
237
238
1.06k
    if (errorCode == GrDrawOpAtlas::ErrorCode::kSucceeded) {
239
1.06k
        glyph->fAtlasLocator.insetSrc(srcPadding);
240
1.06k
    }
241
242
1.06k
    return errorCode;
243
1.06k
}
GrAtlasManager::addGlyphToAtlas(SkGlyph const&, sktext::gpu::Glyph*, int, GrResourceProvider*, GrDeferredUploadTarget*)
Line
Count
Source
169
1.06k
                                                         GrDeferredUploadTarget* uploadTarget) {
170
1.06k
#if !defined(SK_DISABLE_SDF_TEXT)
171
1.06k
    SkASSERT(0 <= srcPadding && srcPadding <= SK_DistanceFieldInset);
172
#else
173
    SkASSERT(0 <= srcPadding);
174
#endif
175
176
1.06k
    if (skGlyph.image() == nullptr) {
177
0
        return GrDrawOpAtlas::ErrorCode::kError;
178
0
    }
179
1.06k
    SkASSERT(glyph != nullptr);
180
181
1.06k
    MaskFormat glyphFormat = Glyph::FormatFromSkGlyph(skGlyph.maskFormat());
182
1.06k
    MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
183
1.06k
    int bytesPerPixel = MaskFormatBytesPerPixel(expectedMaskFormat);
184
185
1.06k
    int padding;
186
1.06k
    switch (srcPadding) {
187
888
        case 0:
188
            // The direct mask/image case.
189
888
            padding = 0;
190
888
            if (fSupportBilerpAtlas) {
191
                // Force direct masks (glyph with no padding) to have padding.
192
0
                padding = 1;
193
0
                srcPadding = 1;
194
0
            }
195
888
            break;
196
11
        case 1:
197
            // The transformed mask/image case.
198
11
            padding = 1;
199
11
            break;
200
0
#if !defined(SK_DISABLE_SDF_TEXT)
201
167
        case SK_DistanceFieldInset:
202
            // The SDFT case.
203
            // If the srcPadding == SK_DistanceFieldInset (SDFT case) then the padding is built
204
            // into the image on the glyph; no extra padding needed.
205
            // TODO: can the SDFT glyph image in the cache be reduced by the padding?
206
167
            padding = 0;
207
167
            break;
208
0
#endif
209
0
        default:
210
            // The padding is not one of the know forms.
211
0
            return GrDrawOpAtlas::ErrorCode::kError;
212
1.06k
    }
213
214
1.06k
    const int width = skGlyph.width() + 2*padding;
215
1.06k
    const int height = skGlyph.height() + 2*padding;
216
1.06k
    int rowBytes = width * bytesPerPixel;
217
1.06k
    size_t size = height * rowBytes;
218
219
    // Temporary storage for normalizing glyph image.
220
1.06k
    SkAutoSMalloc<1024> storage(size);
221
1.06k
    void* dataPtr = storage.get();
222
1.06k
    if (padding > 0) {
223
11
        sk_bzero(dataPtr, size);
224
        // Advance in one row and one column.
225
11
        dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
226
11
    }
227
228
1.06k
    get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr);
229
230
1.06k
    auto errorCode = this->addToAtlas(resourceProvider,
231
1.06k
                                      uploadTarget,
232
1.06k
                                      expectedMaskFormat,
233
1.06k
                                      width,
234
1.06k
                                      height,
235
1.06k
                                      storage.get(),
236
1.06k
                                      &glyph->fAtlasLocator);
237
238
1.06k
    if (errorCode == GrDrawOpAtlas::ErrorCode::kSucceeded) {
239
1.06k
        glyph->fAtlasLocator.insetSrc(srcPadding);
240
1.06k
    }
241
242
1.06k
    return errorCode;
243
1.06k
}
Unexecuted instantiation: GrAtlasManager::addGlyphToAtlas(SkGlyph const&, sktext::gpu::Glyph*, int, GrResourceProvider*, GrDeferredUploadTarget*)
244
245
// add to texture atlas that matches this format
246
GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(GrResourceProvider* resourceProvider,
247
                                                    GrDeferredUploadTarget* target,
248
                                                    MaskFormat format,
249
                                                    int width, int height, const void* image,
250
1.06k
                                                    skgpu::AtlasLocator* atlasLocator) {
251
1.06k
    return this->getAtlas(format)->addToAtlas(resourceProvider, target, width, height, image,
252
1.06k
                                              atlasLocator);
253
1.06k
}
254
255
void GrAtlasManager::addGlyphToBulkAndSetUseToken(skgpu::BulkUsePlotUpdater* updater,
256
                                                  MaskFormat format, Glyph* glyph,
257
20.6k
                                                  skgpu::AtlasToken token) {
258
20.6k
    SkASSERT(glyph);
259
20.6k
    if (updater->add(glyph->fAtlasLocator)) {
260
1.15k
        this->getAtlas(format)->setLastUseToken(glyph->fAtlasLocator, token);
261
1.15k
    }
262
20.6k
}
263
264
2.13k
bool GrAtlasManager::initAtlas(MaskFormat format) {
265
2.13k
    int index = MaskFormatToAtlasIndex(format);
266
2.13k
    if (fAtlases[index] == nullptr) {
267
245
        SkColorType colorType = MaskFormatToColorType(format);
268
245
        GrColorType grColorType = SkColorTypeToGrColorType(colorType);
269
245
        SkISize atlasDimensions = fAtlasConfig.atlasDimensions(format);
270
245
        SkISize plotDimensions = fAtlasConfig.plotDimensions(format);
271
272
245
        const GrBackendFormat backendFormat =
273
245
                fCaps->getDefaultBackendFormat(grColorType, GrRenderable::kNo);
274
275
245
        fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, backendFormat,
276
245
                                              GrColorTypeToSkColorType(grColorType),
277
245
                                              GrColorTypeBytesPerPixel(grColorType),
278
245
                                              atlasDimensions.width(), atlasDimensions.height(),
279
245
                                              plotDimensions.width(), plotDimensions.height(),
280
245
                                              this,
281
245
                                              fAllowMultitexturing,
282
245
                                              nullptr,
283
245
                                              /*label=*/"TextAtlas");
284
245
        if (!fAtlases[index]) {
285
0
            return false;
286
0
        }
287
245
    }
288
2.13k
    return true;
289
2.13k
}
290
291
////////////////////////////////////////////////////////////////////////////////////////////////
292
293
namespace sktext::gpu {
294
295
std::tuple<bool, int> GlyphVector::regenerateAtlasForGanesh(
296
1.53k
        int begin, int end, MaskFormat maskFormat, int srcPadding, GrMeshDrawTarget* target) {
297
1.53k
    GrAtlasManager* atlasManager = target->atlasManager();
298
1.53k
    GrDeferredUploadTarget* uploadTarget = target->deferredUploadTarget();
299
300
1.53k
    uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
301
302
1.53k
    this->packedGlyphIDToGlyph(target->strikeCache());
303
304
1.53k
    if (fAtlasGeneration != currentAtlasGen) {
305
        // Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
306
        // is set to kInvalidAtlasGeneration) or the atlas has changed in subsequent calls..
307
1.14k
        fBulkUseUpdater.reset();
308
309
1.14k
        SkBulkGlyphMetricsAndImages metricsAndImages{fTextStrike->strikeSpec()};
310
311
        // Update the atlas information in the GrStrike.
312
1.14k
        auto tokenTracker = uploadTarget->tokenTracker();
313
1.14k
        auto glyphs = fGlyphs.subspan(begin, end - begin);
314
1.14k
        int glyphsPlacedInAtlas = 0;
315
1.14k
        bool success = true;
316
20.6k
        for (const Variant& variant : glyphs) {
317
20.6k
            Glyph* gpuGlyph = variant.glyph;
318
20.6k
            SkASSERT(gpuGlyph != nullptr);
319
320
20.6k
            if (!atlasManager->hasGlyph(maskFormat, gpuGlyph)) {
321
1.06k
                const SkGlyph& skGlyph = *metricsAndImages.glyph(gpuGlyph->fPackedID);
322
1.06k
                auto code = atlasManager->addGlyphToAtlas(
323
1.06k
                        skGlyph, gpuGlyph, srcPadding, target->resourceProvider(), uploadTarget);
324
1.06k
                if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) {
325
0
                    success = code != GrDrawOpAtlas::ErrorCode::kError;
326
0
                    break;
327
0
                }
328
1.06k
            }
329
20.6k
            atlasManager->addGlyphToBulkAndSetUseToken(
330
20.6k
                    &fBulkUseUpdater, maskFormat, gpuGlyph,
331
20.6k
                    tokenTracker->nextDrawToken());
332
20.6k
            glyphsPlacedInAtlas++;
333
20.6k
        }
334
335
        // Update atlas generation if there are no more glyphs to put in the atlas.
336
1.14k
        if (success && begin + glyphsPlacedInAtlas == SkCount(fGlyphs)) {
337
            // Need to get the freshest value of the atlas' generation because
338
            // updateTextureCoordinates may have changed it.
339
1.14k
            fAtlasGeneration = atlasManager->atlasGeneration(maskFormat);
340
1.14k
        }
341
342
1.14k
        return {success, glyphsPlacedInAtlas};
343
1.14k
    } else {
344
        // The atlas hasn't changed, so our texture coordinates are still valid.
345
394
        if (end == SkCount(fGlyphs)) {
346
            // The atlas hasn't changed and the texture coordinates are all still valid. Update
347
            // all the plots used to the new use token.
348
394
            atlasManager->setUseTokenBulk(fBulkUseUpdater,
349
394
                                          uploadTarget->tokenTracker()->nextDrawToken(),
350
394
                                          maskFormat);
351
394
        }
352
394
        return {true, end - begin};
353
394
    }
354
1.53k
}
355
356
}  // namespace sktext::gpu