blob: abd0b20d9e939bd754a3fbbc2bef3bc1c7182136 [file] [log] [blame]
Robert Phillipsc4039ea2018-03-01 11:36:45 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/text/GrAtlasManager.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -05009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/GrGlyph.h"
11#include "src/gpu/text/GrStrikeCache.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050012
Herb Derby081e6f32019-01-16 13:46:02 -050013GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrStrikeCache* glyphCache,
Herb Derby3c4d5332018-09-07 15:27:57 -040014 size_t maxTextureBytes,
Cary Clarkaa5f38f2018-09-10 20:28:05 +000015 GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
Herb Derby3c4d5332018-09-07 15:27:57 -040016 : fAllowMultitexturing{allowMultitexturing}
Herb Derby3c4d5332018-09-07 15:27:57 -040017 , fProxyProvider{proxyProvider}
18 , fCaps{fProxyProvider->refCaps()}
19 , fGlyphCache{glyphCache}
Jim Van Verthf6206f92018-12-14 08:22:24 -050020 , fAtlasConfig{fCaps->maxTextureSize(), maxTextureBytes} { }
Cary Clarkaa5f38f2018-09-10 20:28:05 +000021
Herb Derby3c4d5332018-09-07 15:27:57 -040022GrAtlasManager::~GrAtlasManager() = default;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050023
Robert Phillips0221e8b2019-05-13 19:55:23 +000024static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050025 switch (format) {
26 case kA8_GrMaskFormat:
Robert Phillips0221e8b2019-05-13 19:55:23 +000027 return kAlpha_8_GrPixelConfig;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050028 case kA565_GrMaskFormat:
Robert Phillips0221e8b2019-05-13 19:55:23 +000029 return kRGB_565_GrPixelConfig;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050030 case kARGB_GrMaskFormat:
Robert Phillips0221e8b2019-05-13 19:55:23 +000031 return kRGBA_8888_GrPixelConfig;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050032 default:
33 SkDEBUGFAIL("unsupported GrMaskFormat");
Robert Phillips0221e8b2019-05-13 19:55:23 +000034 return kAlpha_8_GrPixelConfig;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050035 }
36}
37
Robert Phillips0221e8b2019-05-13 19:55:23 +000038static SkColorType mask_format_to_color_type(GrMaskFormat format) {
39 switch (format) {
40 case kA8_GrMaskFormat:
41 return kAlpha_8_SkColorType;
42 case kA565_GrMaskFormat:
43 return kRGB_565_SkColorType;
44 case kARGB_GrMaskFormat:
45 return kRGBA_8888_SkColorType;
46 default:
47 SkDEBUGFAIL("unsupported GrMaskFormat");
48 return kAlpha_8_SkColorType;
49 }
50
51}
52
Robert Phillipsc4039ea2018-03-01 11:36:45 -050053void GrAtlasManager::freeAll() {
54 for (int i = 0; i < kMaskFormatCount; ++i) {
55 fAtlases[i] = nullptr;
56 }
57}
58
59bool GrAtlasManager::hasGlyph(GrGlyph* glyph) {
60 SkASSERT(glyph);
61 return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
62}
63
64// add to texture atlas that matches this format
Robert Phillipsd2e9f762018-03-07 11:54:37 -050065GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(
66 GrResourceProvider* resourceProvider,
Herb Derby081e6f32019-01-16 13:46:02 -050067 GrStrikeCache* glyphCache,
Robert Phillipscaf1ebb2018-03-01 14:28:44 -050068 GrTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050069 GrDeferredUploadTarget* target, GrMaskFormat format,
70 int width, int height, const void* image, SkIPoint16* loc) {
71 glyphCache->setStrikeToPreserve(strike);
72 return this->getAtlas(format)->addToAtlas(resourceProvider, id, target, width, height,
Robert Phillipsd2e9f762018-03-07 11:54:37 -050073 image, loc);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050074}
75
76void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
77 GrGlyph* glyph,
78 GrDeferredUploadToken token) {
79 SkASSERT(glyph);
Jim Van Verthba98b7d2018-12-05 12:33:43 -050080 if (updater->add(glyph->fID)) {
81 this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
82 }
Robert Phillipsc4039ea2018-03-01 11:36:45 -050083}
84
85#ifdef SK_DEBUG
Mike Kleinc0bd9f92019-04-23 12:05:21 -050086#include "include/private/GrSurfaceProxy.h"
87#include "include/private/GrTextureProxy.h"
88#include "src/gpu/GrContextPriv.h"
89#include "src/gpu/GrSurfaceContext.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050090
Mike Kleinc0bd9f92019-04-23 12:05:21 -050091#include "include/core/SkBitmap.h"
92#include "include/core/SkImageEncoder.h"
93#include "include/core/SkStream.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050094#include <stdio.h>
95
96/**
97 * Write the contents of the surface proxy to a PNG. Returns true if successful.
98 * @param filename Full path to desired file
99 */
100static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* filename) {
101 if (!sProxy) {
102 return false;
103 }
104
105 SkImageInfo ii = SkImageInfo::Make(sProxy->width(), sProxy->height(),
106 kRGBA_8888_SkColorType, kPremul_SkAlphaType);
107 SkBitmap bm;
108 if (!bm.tryAllocPixels(ii)) {
109 return false;
110 }
111
Robert Phillips9da87e02019-02-04 13:26:26 -0500112 sk_sp<GrSurfaceContext> sContext(context->priv().makeWrappedSurfaceContext(sk_ref_sp(sProxy)));
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500113 if (!sContext || !sContext->asTextureProxy()) {
114 return false;
115 }
116
117 bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), 0, 0);
118 if (!result) {
119 SkDebugf("------ failed to read pixels for %s\n", filename);
120 return false;
121 }
122
123 // remove any previous version of this file
124 remove(filename);
125
126 SkFILEWStream file(filename);
127 if (!file.isValid()) {
128 SkDebugf("------ failed to create file: %s\n", filename);
129 remove(filename); // remove any partial file
130 return false;
131 }
132
133 if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
134 SkDebugf("------ failed to encode %s\n", filename);
135 remove(filename); // remove any partial file
136 return false;
137 }
138
139 return true;
140}
141
142void GrAtlasManager::dump(GrContext* context) const {
143 static int gDumpCount = 0;
144 for (int i = 0; i < kMaskFormatCount; ++i) {
145 if (fAtlases[i]) {
146 const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies();
147 for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
148 SkASSERT(proxies[pageIdx]);
149 SkString filename;
150#ifdef SK_BUILD_FOR_ANDROID
151 filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
152#else
153 filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
154#endif
155
156 save_pixels(context, proxies[pageIdx].get(), filename.c_str());
157 }
158 }
159 }
160 ++gDumpCount;
161}
162#endif
163
Herb Derby3c4d5332018-09-07 15:27:57 -0400164void GrAtlasManager::setAtlasSizesToMinimum_ForTesting() {
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500165 // Delete any old atlases.
166 // This should be safe to do as long as we are not in the middle of a flush.
167 for (int i = 0; i < kMaskFormatCount; i++) {
168 fAtlases[i] = nullptr;
169 }
Herb Derby3c4d5332018-09-07 15:27:57 -0400170
171 // Set all the atlas sizes to 1x1 plot each.
Jim Van Verthf6206f92018-12-14 08:22:24 -0500172 new (&fAtlasConfig) GrDrawOpAtlasConfig{};
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500173}
174
175bool GrAtlasManager::initAtlas(GrMaskFormat format) {
176 int index = MaskFormatToAtlasIndex(format);
Herb Derby3c4d5332018-09-07 15:27:57 -0400177 if (fAtlases[index] == nullptr) {
Robert Phillips0221e8b2019-05-13 19:55:23 +0000178 GrPixelConfig config = mask_format_to_pixel_config(format);
179 SkColorType colorType = mask_format_to_color_type(format);
Jim Van Verthf6206f92018-12-14 08:22:24 -0500180 SkISize atlasDimensions = fAtlasConfig.atlasDimensions(format);
181 SkISize plotDimensions = fAtlasConfig.plotDimensions(format);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500182
Robert Phillips0221e8b2019-05-13 19:55:23 +0000183 const GrBackendFormat format = fCaps->getBackendFormatFromColorType(colorType);
Greg Daniel4065d452018-11-16 15:43:41 -0500184
Herb Derby3c4d5332018-09-07 15:27:57 -0400185 fAtlases[index] = GrDrawOpAtlas::Make(
Robert Phillips0221e8b2019-05-13 19:55:23 +0000186 fProxyProvider, format, config, atlasDimensions.width(), atlasDimensions.height(),
187 plotDimensions.width(), plotDimensions.height(), fAllowMultitexturing,
188 &GrStrikeCache::HandleEviction, fGlyphCache);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500189 if (!fAtlases[index]) {
190 return false;
191 }
192 }
193 return true;
194}