xref: /aosp_15_r20/external/skia/tools/gpu/ganesh/GrAtlasTools.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google LLC
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 "tools/gpu/ganesh/GrAtlasTools.h"
9 
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkBitmap.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkDataTable.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkStream.h"
17 #include "include/core/SkString.h"
18 #include "include/encode/SkPngEncoder.h"
19 #include "include/gpu/ganesh/GrDirectContext.h"
20 #include "include/private/base/SkDebug.h"
21 #include "src/gpu/ganesh/GrDirectContextPriv.h"
22 #include "src/gpu/ganesh/GrSurfaceProxy.h"
23 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
24 #include "src/gpu/ganesh/SurfaceContext.h"
25 
26 #include <cstdio>
27 #include <utility>
28 
29 /**
30  * Write the contents of the surface proxy to a PNG. Returns true if successful.
31  * @param filename      Full path to desired file
32  */
save_pixels(GrDirectContext * dContext,GrSurfaceProxyView view,GrColorType colorType,const char * filename)33 static bool save_pixels(GrDirectContext* dContext,
34                         GrSurfaceProxyView view,
35                         GrColorType colorType,
36                         const char* filename) {
37     if (!view.proxy()) {
38         return false;
39     }
40 
41     auto ii = SkImageInfo::Make(
42             view.proxy()->dimensions(), kRGBA_8888_SkColorType, kPremul_SkAlphaType);
43     SkBitmap bm;
44     if (!bm.tryAllocPixels(ii)) {
45         return false;
46     }
47 
48     auto sContext =
49             dContext->priv().makeSC(std::move(view), {colorType, kUnknown_SkAlphaType, nullptr});
50     if (!sContext || !sContext->asTextureProxy()) {
51         return false;
52     }
53 
54     bool result = sContext->readPixels(dContext, bm.pixmap(), {0, 0});
55     if (!result) {
56         SkDebugf("------ failed to read pixels for %s\n", filename);
57         return false;
58     }
59 
60     // remove any previous version of this file
61     remove(filename);
62 
63     SkFILEWStream file(filename);
64     if (!file.isValid()) {
65         SkDebugf("------ failed to create file: %s\n", filename);
66         remove(filename);  // remove any partial file
67         return false;
68     }
69 
70     if (!SkPngEncoder::Encode(&file, bm.pixmap(), {})) {
71         SkDebugf("------ failed to encode %s\n", filename);
72         remove(filename);  // remove any partial file
73         return false;
74     }
75 
76     return true;
77 }
78 
Dump(const GrAtlasManager * am,GrDirectContext * context)79 void GrAtlasManagerTools::Dump(const GrAtlasManager* am, GrDirectContext* context) {
80     SkASSERT(am);
81     static int gDumpCount = 0;
82     for (int i = 0; i < skgpu::kMaskFormatCount; ++i) {
83         if (am->fAtlases[i]) {
84             const GrSurfaceProxyView* views = am->fAtlases[i]->getViews();
85             for (uint32_t pageIdx = 0; pageIdx < am->fAtlases[i]->numActivePages(); ++pageIdx) {
86                 SkASSERT(views[pageIdx].proxy());
87                 SkString filename;
88 #ifdef SK_BUILD_FOR_ANDROID
89                 filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
90 #else
91                 filename.printf("fontcache_%d%d%u.png", gDumpCount, i, pageIdx);
92 #endif
93                 SkColorType ct = MaskFormatToColorType(GrAtlasManager::AtlasIndexToMaskFormat(i));
94                 save_pixels(
95                         context, views[pageIdx], SkColorTypeToGrColorType(ct), filename.c_str());
96             }
97         }
98     }
99     ++gDumpCount;
100 }
101 
SetAtlasDimensionsToMinimum(GrAtlasManager * am)102 void GrAtlasManagerTools::SetAtlasDimensionsToMinimum(GrAtlasManager* am) {
103     SkASSERT(am);
104     // Delete any old atlases.
105     // This should be safe to do as long as we are not in the middle of a flush.
106     for (int i = 0; i < skgpu::kMaskFormatCount; i++) {
107         am->fAtlases[i] = nullptr;
108     }
109 
110     // Set all the atlas sizes to 1x1 plot each.
111     new (&am->fAtlasConfig) GrDrawOpAtlasConfig{};
112 }
113 
SetMaxPages(GrAtlasManager * am,uint32_t maxPages)114 void GrAtlasManagerTools::SetMaxPages(GrAtlasManager* am, uint32_t maxPages) {
115     SkASSERT(am);
116     for (int i = 0; i < skgpu::kMaskFormatCount; i++) {
117         if (am->fAtlases[i]) {
118             GrDrawOpAtlasTools::SetMaxPages(am->fAtlases[i].get(), maxPages);
119         }
120     }
121 }
122 
NumAllocated(const GrDrawOpAtlas * doa)123 int GrDrawOpAtlasTools::NumAllocated(const GrDrawOpAtlas* doa) {
124     SkASSERT(doa);
125     int count = 0;
126     for (uint32_t i = 0; i < doa->maxPages(); ++i) {
127         if (doa->fViews[i].proxy()->isInstantiated()) {
128             ++count;
129         }
130     }
131 
132     return count;
133 }
134 
SetMaxPages(GrDrawOpAtlas * doa,uint32_t maxPages)135 void GrDrawOpAtlasTools::SetMaxPages(GrDrawOpAtlas* doa, uint32_t maxPages) {
136     SkASSERT(!doa->fNumActivePages);
137 
138     doa->fMaxPages = maxPages;
139 }
140