1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/text/GrAtlasManager.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "src/codec/SkMasks.h"
11cb93a386Sopenharmony_ci#include "src/core/SkAutoMalloc.h"
12cb93a386Sopenharmony_ci#include "src/gpu/GrGlyph.h"
13cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h"
14cb93a386Sopenharmony_ci#include "src/gpu/text/GrStrikeCache.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ciGrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider,
17cb93a386Sopenharmony_ci                               size_t maxTextureBytes,
18cb93a386Sopenharmony_ci                               GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
19cb93a386Sopenharmony_ci            : fAllowMultitexturing{allowMultitexturing}
20cb93a386Sopenharmony_ci            , fProxyProvider{proxyProvider}
21cb93a386Sopenharmony_ci            , fCaps{fProxyProvider->refCaps()}
22cb93a386Sopenharmony_ci            , fAtlasConfig{fCaps->maxTextureSize(), maxTextureBytes} { }
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ciGrAtlasManager::~GrAtlasManager() = default;
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_civoid GrAtlasManager::freeAll() {
27cb93a386Sopenharmony_ci    for (int i = 0; i < kMaskFormatCount; ++i) {
28cb93a386Sopenharmony_ci        fAtlases[i] = nullptr;
29cb93a386Sopenharmony_ci    }
30cb93a386Sopenharmony_ci}
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_cibool GrAtlasManager::hasGlyph(GrMaskFormat format, GrGlyph* glyph) {
33cb93a386Sopenharmony_ci    SkASSERT(glyph);
34cb93a386Sopenharmony_ci    return this->getAtlas(format)->hasID(glyph->fAtlasLocator.plotLocator());
35cb93a386Sopenharmony_ci}
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_citemplate <typename INT_TYPE>
38cb93a386Sopenharmony_cistatic void expand_bits(INT_TYPE* dst,
39cb93a386Sopenharmony_ci                        const uint8_t* src,
40cb93a386Sopenharmony_ci                        int width,
41cb93a386Sopenharmony_ci                        int height,
42cb93a386Sopenharmony_ci                        int dstRowBytes,
43cb93a386Sopenharmony_ci                        int srcRowBytes) {
44cb93a386Sopenharmony_ci    for (int y = 0; y < height; ++y) {
45cb93a386Sopenharmony_ci        int rowWritesLeft = width;
46cb93a386Sopenharmony_ci        const uint8_t* s = src;
47cb93a386Sopenharmony_ci        INT_TYPE* d = dst;
48cb93a386Sopenharmony_ci        while (rowWritesLeft > 0) {
49cb93a386Sopenharmony_ci            unsigned mask = *s++;
50cb93a386Sopenharmony_ci            for (int x = 7; x >= 0 && rowWritesLeft; --x, --rowWritesLeft) {
51cb93a386Sopenharmony_ci                *d++ = (mask & (1 << x)) ? (INT_TYPE)(~0UL) : 0;
52cb93a386Sopenharmony_ci            }
53cb93a386Sopenharmony_ci        }
54cb93a386Sopenharmony_ci        dst = reinterpret_cast<INT_TYPE*>(reinterpret_cast<intptr_t>(dst) + dstRowBytes);
55cb93a386Sopenharmony_ci        src += srcRowBytes;
56cb93a386Sopenharmony_ci    }
57cb93a386Sopenharmony_ci}
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_cistatic void get_packed_glyph_image(
60cb93a386Sopenharmony_ci        const SkGlyph& glyph, int dstRB, GrMaskFormat expectedMaskFormat, void* dst) {
61cb93a386Sopenharmony_ci    const int width = glyph.width();
62cb93a386Sopenharmony_ci    const int height = glyph.height();
63cb93a386Sopenharmony_ci    const void* src = glyph.image();
64cb93a386Sopenharmony_ci    SkASSERT(src != nullptr);
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci    GrMaskFormat grMaskFormat = GrGlyph::FormatFromSkGlyph(glyph.maskFormat());
67cb93a386Sopenharmony_ci    if (grMaskFormat == expectedMaskFormat) {
68cb93a386Sopenharmony_ci        int srcRB = glyph.rowBytes();
69cb93a386Sopenharmony_ci        // Notice this comparison is with the glyphs raw mask format, and not its GrMaskFormat.
70cb93a386Sopenharmony_ci        if (glyph.maskFormat() != SkMask::kBW_Format) {
71cb93a386Sopenharmony_ci            if (srcRB != dstRB) {
72cb93a386Sopenharmony_ci                const int bbp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
73cb93a386Sopenharmony_ci                for (int y = 0; y < height; y++) {
74cb93a386Sopenharmony_ci                    memcpy(dst, src, width * bbp);
75cb93a386Sopenharmony_ci                    src = (const char*) src + srcRB;
76cb93a386Sopenharmony_ci                    dst = (char*) dst + dstRB;
77cb93a386Sopenharmony_ci                }
78cb93a386Sopenharmony_ci            } else {
79cb93a386Sopenharmony_ci                memcpy(dst, src, dstRB * height);
80cb93a386Sopenharmony_ci            }
81cb93a386Sopenharmony_ci        } else {
82cb93a386Sopenharmony_ci            // Handle 8-bit format by expanding the mask to the expected format.
83cb93a386Sopenharmony_ci            const uint8_t* bits = reinterpret_cast<const uint8_t*>(src);
84cb93a386Sopenharmony_ci            switch (expectedMaskFormat) {
85cb93a386Sopenharmony_ci                case kA8_GrMaskFormat: {
86cb93a386Sopenharmony_ci                    uint8_t* bytes = reinterpret_cast<uint8_t*>(dst);
87cb93a386Sopenharmony_ci                    expand_bits(bytes, bits, width, height, dstRB, srcRB);
88cb93a386Sopenharmony_ci                    break;
89cb93a386Sopenharmony_ci                }
90cb93a386Sopenharmony_ci                case kA565_GrMaskFormat: {
91cb93a386Sopenharmony_ci                    uint16_t* rgb565 = reinterpret_cast<uint16_t*>(dst);
92cb93a386Sopenharmony_ci                    expand_bits(rgb565, bits, width, height, dstRB, srcRB);
93cb93a386Sopenharmony_ci                    break;
94cb93a386Sopenharmony_ci                }
95cb93a386Sopenharmony_ci                default:
96cb93a386Sopenharmony_ci                    SK_ABORT("Invalid GrMaskFormat");
97cb93a386Sopenharmony_ci            }
98cb93a386Sopenharmony_ci        }
99cb93a386Sopenharmony_ci    } else if (grMaskFormat == kA565_GrMaskFormat && expectedMaskFormat == kARGB_GrMaskFormat) {
100cb93a386Sopenharmony_ci        // Convert if the glyph uses a 565 mask format since it is using LCD text rendering
101cb93a386Sopenharmony_ci        // but the expected format is 8888 (will happen on macOS with Metal since that
102cb93a386Sopenharmony_ci        // combination does not support 565).
103cb93a386Sopenharmony_ci        static constexpr SkMasks masks{
104cb93a386Sopenharmony_ci                {0b1111'1000'0000'0000, 11, 5},  // Red
105cb93a386Sopenharmony_ci                {0b0000'0111'1110'0000,  5, 6},  // Green
106cb93a386Sopenharmony_ci                {0b0000'0000'0001'1111,  0, 5},  // Blue
107cb93a386Sopenharmony_ci                {0, 0, 0}                        // Alpha
108cb93a386Sopenharmony_ci        };
109cb93a386Sopenharmony_ci        constexpr int a565Bpp = GrMaskFormatBytesPerPixel(kA565_GrMaskFormat);
110cb93a386Sopenharmony_ci        constexpr int argbBpp = GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat);
111cb93a386Sopenharmony_ci        for (int y = 0; y < height; y++) {
112cb93a386Sopenharmony_ci            for (int x = 0; x < width; x++) {
113cb93a386Sopenharmony_ci                uint16_t color565 = 0;
114cb93a386Sopenharmony_ci                memcpy(&color565, src, a565Bpp);
115cb93a386Sopenharmony_ci                uint32_t colorRGBA = GrColorPackRGBA(masks.getRed(color565),
116cb93a386Sopenharmony_ci                                                     masks.getGreen(color565),
117cb93a386Sopenharmony_ci                                                     masks.getBlue(color565),
118cb93a386Sopenharmony_ci                                                     0xFF);
119cb93a386Sopenharmony_ci                memcpy(dst, &colorRGBA, argbBpp);
120cb93a386Sopenharmony_ci                src = (char*)src + a565Bpp;
121cb93a386Sopenharmony_ci                dst = (char*)dst + argbBpp;
122cb93a386Sopenharmony_ci            }
123cb93a386Sopenharmony_ci        }
124cb93a386Sopenharmony_ci    } else {
125cb93a386Sopenharmony_ci        // crbug:510931
126cb93a386Sopenharmony_ci        // Retrieving the image from the cache can actually change the mask format. This case is
127cb93a386Sopenharmony_ci        // very uncommon so for now we just draw a clear box for these glyphs.
128cb93a386Sopenharmony_ci        const int bpp = GrMaskFormatBytesPerPixel(expectedMaskFormat);
129cb93a386Sopenharmony_ci        for (int y = 0; y < height; y++) {
130cb93a386Sopenharmony_ci            sk_bzero(dst, width * bpp);
131cb93a386Sopenharmony_ci            dst = (char*)dst + dstRB;
132cb93a386Sopenharmony_ci        }
133cb93a386Sopenharmony_ci    }
134cb93a386Sopenharmony_ci}
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci// returns true if glyph successfully added to texture atlas, false otherwise.  If the glyph's
137cb93a386Sopenharmony_ci// mask format has changed, then addGlyphToAtlas will draw a clear box.  This will almost never
138cb93a386Sopenharmony_ci// happen.
139cb93a386Sopenharmony_ci// TODO we can handle some of these cases if we really want to, but the long term solution is to
140cb93a386Sopenharmony_ci// get the actual glyph image itself when we get the glyph metrics.
141cb93a386Sopenharmony_ciGrDrawOpAtlas::ErrorCode GrAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph,
142cb93a386Sopenharmony_ci                                                         GrGlyph* grGlyph,
143cb93a386Sopenharmony_ci                                                         int srcPadding,
144cb93a386Sopenharmony_ci                                                         GrResourceProvider* resourceProvider,
145cb93a386Sopenharmony_ci                                                         GrDeferredUploadTarget* uploadTarget,
146cb93a386Sopenharmony_ci                                                         bool bilerpPadding) {
147cb93a386Sopenharmony_ci    if (skGlyph.image() == nullptr) {
148cb93a386Sopenharmony_ci        return GrDrawOpAtlas::ErrorCode::kError;
149cb93a386Sopenharmony_ci    }
150cb93a386Sopenharmony_ci    SkASSERT(grGlyph != nullptr);
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci    GrMaskFormat glyphFormat = GrGlyph::FormatFromSkGlyph(skGlyph.maskFormat());
153cb93a386Sopenharmony_ci    GrMaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
154cb93a386Sopenharmony_ci    int bytesPerPixel = GrMaskFormatBytesPerPixel(expectedMaskFormat);
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_ci    // Add 1 pixel padding around grGlyph if needed.
157cb93a386Sopenharmony_ci    int padding = bilerpPadding ? 1 : 0;
158cb93a386Sopenharmony_ci    const int width = skGlyph.width() + 2*padding;
159cb93a386Sopenharmony_ci    const int height = skGlyph.height() + 2*padding;
160cb93a386Sopenharmony_ci    int rowBytes = width * bytesPerPixel;
161cb93a386Sopenharmony_ci    size_t size = height * rowBytes;
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci    // Temporary storage for normalizing grGlyph image.
164cb93a386Sopenharmony_ci    SkAutoSMalloc<1024> storage(size);
165cb93a386Sopenharmony_ci    void* dataPtr = storage.get();
166cb93a386Sopenharmony_ci    if (padding > 0) {
167cb93a386Sopenharmony_ci        sk_bzero(dataPtr, size);
168cb93a386Sopenharmony_ci        // Advance in one row and one column.
169cb93a386Sopenharmony_ci        dataPtr = (char*)(dataPtr) + rowBytes + bytesPerPixel;
170cb93a386Sopenharmony_ci    }
171cb93a386Sopenharmony_ci
172cb93a386Sopenharmony_ci    get_packed_glyph_image(skGlyph, rowBytes, expectedMaskFormat, dataPtr);
173cb93a386Sopenharmony_ci
174cb93a386Sopenharmony_ci    auto errorCode = this->addToAtlas(resourceProvider,
175cb93a386Sopenharmony_ci                                      uploadTarget,
176cb93a386Sopenharmony_ci                                      expectedMaskFormat,
177cb93a386Sopenharmony_ci                                      width,
178cb93a386Sopenharmony_ci                                      height,
179cb93a386Sopenharmony_ci                                      storage.get(),
180cb93a386Sopenharmony_ci                                      &grGlyph->fAtlasLocator);
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci    if (errorCode == GrDrawOpAtlas::ErrorCode::kSucceeded) {
183cb93a386Sopenharmony_ci        grGlyph->fAtlasLocator.insetSrc(srcPadding);
184cb93a386Sopenharmony_ci    }
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci    return errorCode;
187cb93a386Sopenharmony_ci}
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_ci// add to texture atlas that matches this format
190cb93a386Sopenharmony_ciGrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(GrResourceProvider* resourceProvider,
191cb93a386Sopenharmony_ci                                                    GrDeferredUploadTarget* target,
192cb93a386Sopenharmony_ci                                                    GrMaskFormat format,
193cb93a386Sopenharmony_ci                                                    int width, int height, const void* image,
194cb93a386Sopenharmony_ci                                                    GrDrawOpAtlas::AtlasLocator* atlasLocator) {
195cb93a386Sopenharmony_ci    return this->getAtlas(format)->addToAtlas(resourceProvider, target, width, height, image,
196cb93a386Sopenharmony_ci                                              atlasLocator);
197cb93a386Sopenharmony_ci}
198cb93a386Sopenharmony_ci
199cb93a386Sopenharmony_civoid GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
200cb93a386Sopenharmony_ci                                                  GrMaskFormat format, GrGlyph* glyph,
201cb93a386Sopenharmony_ci                                                  GrDeferredUploadToken token) {
202cb93a386Sopenharmony_ci    SkASSERT(glyph);
203cb93a386Sopenharmony_ci    if (updater->add(glyph->fAtlasLocator)) {
204cb93a386Sopenharmony_ci        this->getAtlas(format)->setLastUseToken(glyph->fAtlasLocator, token);
205cb93a386Sopenharmony_ci    }
206cb93a386Sopenharmony_ci}
207cb93a386Sopenharmony_ci
208cb93a386Sopenharmony_ci#ifdef SK_DEBUG
209cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
210cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
211cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxy.h"
212cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxy.h"
213cb93a386Sopenharmony_ci#include "src/gpu/SurfaceContext.h"
214cb93a386Sopenharmony_ci
215cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
216cb93a386Sopenharmony_ci#include "include/core/SkImageEncoder.h"
217cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
218cb93a386Sopenharmony_ci#include <stdio.h>
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci/**
221cb93a386Sopenharmony_ci  * Write the contents of the surface proxy to a PNG. Returns true if successful.
222cb93a386Sopenharmony_ci  * @param filename      Full path to desired file
223cb93a386Sopenharmony_ci  */
224cb93a386Sopenharmony_cistatic bool save_pixels(GrDirectContext* dContext, GrSurfaceProxyView view, GrColorType colorType,
225cb93a386Sopenharmony_ci                        const char* filename) {
226cb93a386Sopenharmony_ci    if (!view.proxy()) {
227cb93a386Sopenharmony_ci        return false;
228cb93a386Sopenharmony_ci    }
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ci    auto ii = SkImageInfo::Make(view.proxy()->dimensions(), kRGBA_8888_SkColorType,
231cb93a386Sopenharmony_ci                                kPremul_SkAlphaType);
232cb93a386Sopenharmony_ci    SkBitmap bm;
233cb93a386Sopenharmony_ci    if (!bm.tryAllocPixels(ii)) {
234cb93a386Sopenharmony_ci        return false;
235cb93a386Sopenharmony_ci    }
236cb93a386Sopenharmony_ci
237cb93a386Sopenharmony_ci    auto sContext = dContext->priv().makeSC(std::move(view),
238cb93a386Sopenharmony_ci                                            {colorType, kUnknown_SkAlphaType, nullptr});
239cb93a386Sopenharmony_ci    if (!sContext || !sContext->asTextureProxy()) {
240cb93a386Sopenharmony_ci        return false;
241cb93a386Sopenharmony_ci    }
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci    bool result = sContext->readPixels(dContext, bm.pixmap(), {0, 0});
244cb93a386Sopenharmony_ci    if (!result) {
245cb93a386Sopenharmony_ci        SkDebugf("------ failed to read pixels for %s\n", filename);
246cb93a386Sopenharmony_ci        return false;
247cb93a386Sopenharmony_ci    }
248cb93a386Sopenharmony_ci
249cb93a386Sopenharmony_ci    // remove any previous version of this file
250cb93a386Sopenharmony_ci    remove(filename);
251cb93a386Sopenharmony_ci
252cb93a386Sopenharmony_ci    SkFILEWStream file(filename);
253cb93a386Sopenharmony_ci    if (!file.isValid()) {
254cb93a386Sopenharmony_ci        SkDebugf("------ failed to create file: %s\n", filename);
255cb93a386Sopenharmony_ci        remove(filename);   // remove any partial file
256cb93a386Sopenharmony_ci        return false;
257cb93a386Sopenharmony_ci    }
258cb93a386Sopenharmony_ci
259cb93a386Sopenharmony_ci    if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
260cb93a386Sopenharmony_ci        SkDebugf("------ failed to encode %s\n", filename);
261cb93a386Sopenharmony_ci        remove(filename);   // remove any partial file
262cb93a386Sopenharmony_ci        return false;
263cb93a386Sopenharmony_ci    }
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci    return true;
266cb93a386Sopenharmony_ci}
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_civoid GrAtlasManager::dump(GrDirectContext* context) const {
269cb93a386Sopenharmony_ci    static int gDumpCount = 0;
270cb93a386Sopenharmony_ci    for (int i = 0; i < kMaskFormatCount; ++i) {
271cb93a386Sopenharmony_ci        if (fAtlases[i]) {
272cb93a386Sopenharmony_ci            const GrSurfaceProxyView* views = fAtlases[i]->getViews();
273cb93a386Sopenharmony_ci            for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
274cb93a386Sopenharmony_ci                SkASSERT(views[pageIdx].proxy());
275cb93a386Sopenharmony_ci                SkString filename;
276cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_ANDROID
277cb93a386Sopenharmony_ci                filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
278cb93a386Sopenharmony_ci#else
279cb93a386Sopenharmony_ci                filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
280cb93a386Sopenharmony_ci#endif
281cb93a386Sopenharmony_ci                auto ct = GrMaskFormatToColorType(AtlasIndexToMaskFormat(i));
282cb93a386Sopenharmony_ci                save_pixels(context, views[pageIdx], ct, filename.c_str());
283cb93a386Sopenharmony_ci            }
284cb93a386Sopenharmony_ci        }
285cb93a386Sopenharmony_ci    }
286cb93a386Sopenharmony_ci    ++gDumpCount;
287cb93a386Sopenharmony_ci}
288cb93a386Sopenharmony_ci#endif
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_civoid GrAtlasManager::setAtlasDimensionsToMinimum_ForTesting() {
291cb93a386Sopenharmony_ci    // Delete any old atlases.
292cb93a386Sopenharmony_ci    // This should be safe to do as long as we are not in the middle of a flush.
293cb93a386Sopenharmony_ci    for (int i = 0; i < kMaskFormatCount; i++) {
294cb93a386Sopenharmony_ci        fAtlases[i] = nullptr;
295cb93a386Sopenharmony_ci    }
296cb93a386Sopenharmony_ci
297cb93a386Sopenharmony_ci    // Set all the atlas sizes to 1x1 plot each.
298cb93a386Sopenharmony_ci    new (&fAtlasConfig) GrDrawOpAtlasConfig{};
299cb93a386Sopenharmony_ci}
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_cibool GrAtlasManager::initAtlas(GrMaskFormat format) {
302cb93a386Sopenharmony_ci    int index = MaskFormatToAtlasIndex(format);
303cb93a386Sopenharmony_ci    if (fAtlases[index] == nullptr) {
304cb93a386Sopenharmony_ci        GrColorType grColorType = GrMaskFormatToColorType(format);
305cb93a386Sopenharmony_ci#ifdef SK_ENABLE_SMALL_PAGE
306cb93a386Sopenharmony_ci        int pageNum = 4; // The maximum number of texture pages in the original skia code is 4
307cb93a386Sopenharmony_ci        if ((format == kA8_GrMaskFormat) && (fAtlasConfig.getARGBDimensions().width() > 512)) {
308cb93a386Sopenharmony_ci            // reset fAtlasConfig to suit small page.
309cb93a386Sopenharmony_ci            pageNum = fAtlasConfig.resetAsSmallPage();
310cb93a386Sopenharmony_ci        }
311cb93a386Sopenharmony_ci#endif
312cb93a386Sopenharmony_ci        SkISize atlasDimensions = fAtlasConfig.atlasDimensions(format);
313cb93a386Sopenharmony_ci        SkISize plotDimensions = fAtlasConfig.plotDimensions(format);
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci        const GrBackendFormat backendFormat =
316cb93a386Sopenharmony_ci                fCaps->getDefaultBackendFormat(grColorType, GrRenderable::kNo);
317cb93a386Sopenharmony_ci
318cb93a386Sopenharmony_ci        fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, backendFormat, grColorType,
319cb93a386Sopenharmony_ci                                              atlasDimensions.width(), atlasDimensions.height(),
320cb93a386Sopenharmony_ci                                              plotDimensions.width(), plotDimensions.height(),
321cb93a386Sopenharmony_ci                                              this, fAllowMultitexturing,
322cb93a386Sopenharmony_ci#ifdef SK_ENABLE_SMALL_PAGE
323cb93a386Sopenharmony_ci                                              pageNum,
324cb93a386Sopenharmony_ci#endif
325cb93a386Sopenharmony_ci                                              nullptr);
326cb93a386Sopenharmony_ci        if (!fAtlases[index]) {
327cb93a386Sopenharmony_ci            return false;
328cb93a386Sopenharmony_ci        }
329cb93a386Sopenharmony_ci    }
330cb93a386Sopenharmony_ci    return true;
331cb93a386Sopenharmony_ci}
332