• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/text/GrAtlasManager.h"
9 
10 #include "src/gpu/GrGlyph.h"
11 #include "src/gpu/GrImageInfo.h"
12 #include "src/gpu/text/GrStrikeCache.h"
13 
GrAtlasManager(GrProxyProvider * proxyProvider,GrStrikeCache * glyphCache,size_t maxTextureBytes,GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)14 GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrStrikeCache* glyphCache,
15                                size_t maxTextureBytes,
16                                GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
17             : fAllowMultitexturing{allowMultitexturing}
18             , fProxyProvider{proxyProvider}
19             , fCaps{fProxyProvider->refCaps()}
20             , fGlyphCache{glyphCache}
21             , fAtlasConfig{fCaps->maxTextureSize(), maxTextureBytes} { }
22 
23 GrAtlasManager::~GrAtlasManager() = default;
24 
freeAll()25 void GrAtlasManager::freeAll() {
26     for (int i = 0; i < kMaskFormatCount; ++i) {
27         fAtlases[i] = nullptr;
28     }
29 }
30 
hasGlyph(GrGlyph * glyph)31 bool GrAtlasManager::hasGlyph(GrGlyph* glyph) {
32     SkASSERT(glyph);
33     return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fPlotLocator);
34 }
35 
36 // add to texture atlas that matches this format
addToAtlas(GrResourceProvider * resourceProvider,GrDrawOpAtlas::PlotLocator * plotLocator,GrDeferredUploadTarget * target,GrMaskFormat format,int width,int height,const void * image,SkIPoint16 * loc)37 GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(
38                                 GrResourceProvider* resourceProvider,
39                                 GrDrawOpAtlas::PlotLocator* plotLocator,
40                                 GrDeferredUploadTarget* target, GrMaskFormat format,
41                                 int width, int height, const void* image, SkIPoint16* loc) {
42     return this->getAtlas(format)->addToAtlas(
43             resourceProvider, plotLocator, target, width, height, image, loc);
44 }
45 
addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater * updater,GrGlyph * glyph,GrDeferredUploadToken token)46 void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
47                                                   GrGlyph* glyph,
48                                                   GrDeferredUploadToken token) {
49     SkASSERT(glyph);
50     if (updater->add(glyph->fPlotLocator)) {
51         this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fPlotLocator, token);
52     }
53 }
54 
55 #ifdef SK_DEBUG
56 #include "src/gpu/GrContextPriv.h"
57 #include "src/gpu/GrSurfaceContext.h"
58 #include "src/gpu/GrSurfaceProxy.h"
59 #include "src/gpu/GrTextureProxy.h"
60 
61 #include "include/core/SkBitmap.h"
62 #include "include/core/SkImageEncoder.h"
63 #include "include/core/SkStream.h"
64 #include <stdio.h>
65 
66 /**
67   * Write the contents of the surface proxy to a PNG. Returns true if successful.
68   * @param filename      Full path to desired file
69   */
save_pixels(GrContext * context,GrSurfaceProxyView view,GrColorType colorType,const char * filename)70 static bool save_pixels(GrContext* context, GrSurfaceProxyView view, GrColorType colorType,
71                         const char* filename) {
72     if (!view.proxy()) {
73         return false;
74     }
75 
76     SkImageInfo ii =
77             SkImageInfo::Make(view.proxy()->dimensions(), kRGBA_8888_SkColorType,
78                               kPremul_SkAlphaType);
79     SkBitmap bm;
80     if (!bm.tryAllocPixels(ii)) {
81         return false;
82     }
83 
84     auto sContext = GrSurfaceContext::Make(context, std::move(view), colorType,
85                                            kUnknown_SkAlphaType, nullptr);
86     if (!sContext || !sContext->asTextureProxy()) {
87         return false;
88     }
89 
90     bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), {0, 0});
91     if (!result) {
92         SkDebugf("------ failed to read pixels for %s\n", filename);
93         return false;
94     }
95 
96     // remove any previous version of this file
97     remove(filename);
98 
99     SkFILEWStream file(filename);
100     if (!file.isValid()) {
101         SkDebugf("------ failed to create file: %s\n", filename);
102         remove(filename);   // remove any partial file
103         return false;
104     }
105 
106     if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
107         SkDebugf("------ failed to encode %s\n", filename);
108         remove(filename);   // remove any partial file
109         return false;
110     }
111 
112     return true;
113 }
114 
dump(GrContext * context) const115 void GrAtlasManager::dump(GrContext* context) const {
116     static int gDumpCount = 0;
117     for (int i = 0; i < kMaskFormatCount; ++i) {
118         if (fAtlases[i]) {
119             const GrSurfaceProxyView* views = fAtlases[i]->getViews();
120             for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
121                 SkASSERT(views[pageIdx].proxy());
122                 SkString filename;
123 #ifdef SK_BUILD_FOR_ANDROID
124                 filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
125 #else
126                 filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
127 #endif
128                 auto ct = GrMaskFormatToColorType(AtlasIndexToMaskFormat(i));
129                 save_pixels(context, views[pageIdx], ct, filename.c_str());
130             }
131         }
132     }
133     ++gDumpCount;
134 }
135 #endif
136 
setAtlasDimensionsToMinimum_ForTesting()137 void GrAtlasManager::setAtlasDimensionsToMinimum_ForTesting() {
138     // Delete any old atlases.
139     // This should be safe to do as long as we are not in the middle of a flush.
140     for (int i = 0; i < kMaskFormatCount; i++) {
141         fAtlases[i] = nullptr;
142     }
143 
144     // Set all the atlas sizes to 1x1 plot each.
145     new (&fAtlasConfig) GrDrawOpAtlasConfig{};
146 }
147 
initAtlas(GrMaskFormat format)148 bool GrAtlasManager::initAtlas(GrMaskFormat format) {
149     int index = MaskFormatToAtlasIndex(format);
150     if (fAtlases[index] == nullptr) {
151         GrColorType grColorType = GrMaskFormatToColorType(format);
152         SkISize atlasDimensions = fAtlasConfig.atlasDimensions(format);
153         SkISize plotDimensions = fAtlasConfig.plotDimensions(format);
154 
155         const GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType,
156                                                                       GrRenderable::kNo);
157 
158         fAtlases[index] = GrDrawOpAtlas::Make(
159                 fProxyProvider, format, grColorType,
160                 atlasDimensions.width(), atlasDimensions.height(),
161                 plotDimensions.width(), plotDimensions.height(),
162                 this, fAllowMultitexturing, nullptr);
163         if (!fAtlases[index]) {
164             return false;
165         }
166     }
167     return true;
168 }
169