blob: 89b488d03a11865318db6f96216f8a49ebc36faf [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"
Brian Salomonf2ebdd92019-09-30 12:15:30 -040011#include "src/gpu/GrImageInfo.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/gpu/text/GrStrikeCache.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050013
Herb Derby081e6f32019-01-16 13:46:02 -050014GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrStrikeCache* glyphCache,
Herb Derby3c4d5332018-09-07 15:27:57 -040015 size_t maxTextureBytes,
Cary Clarkaa5f38f2018-09-10 20:28:05 +000016 GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
Herb Derby3c4d5332018-09-07 15:27:57 -040017 : fAllowMultitexturing{allowMultitexturing}
Herb Derby3c4d5332018-09-07 15:27:57 -040018 , fProxyProvider{proxyProvider}
19 , fCaps{fProxyProvider->refCaps()}
20 , fGlyphCache{glyphCache}
Jim Van Verthf6206f92018-12-14 08:22:24 -050021 , fAtlasConfig{fCaps->maxTextureSize(), maxTextureBytes} { }
Cary Clarkaa5f38f2018-09-10 20:28:05 +000022
Herb Derby3c4d5332018-09-07 15:27:57 -040023GrAtlasManager::~GrAtlasManager() = default;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050024
Robert Phillips42dda082019-05-14 13:29:45 -040025static GrColorType mask_format_to_gr_color_type(GrMaskFormat format) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050026 switch (format) {
27 case kA8_GrMaskFormat:
Robert Phillips42dda082019-05-14 13:29:45 -040028 return GrColorType::kAlpha_8;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050029 case kA565_GrMaskFormat:
Greg Daniel48fec762019-06-18 17:06:43 -040030 return GrColorType::kBGR_565;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050031 case kARGB_GrMaskFormat:
Robert Phillips42dda082019-05-14 13:29:45 -040032 return GrColorType::kRGBA_8888;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050033 default:
34 SkDEBUGFAIL("unsupported GrMaskFormat");
Robert Phillips42dda082019-05-14 13:29:45 -040035 return GrColorType::kAlpha_8;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050036 }
37}
38
Robert Phillipsc4039ea2018-03-01 11:36:45 -050039void GrAtlasManager::freeAll() {
40 for (int i = 0; i < kMaskFormatCount; ++i) {
41 fAtlases[i] = nullptr;
42 }
43}
44
45bool GrAtlasManager::hasGlyph(GrGlyph* glyph) {
46 SkASSERT(glyph);
47 return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
48}
49
50// add to texture atlas that matches this format
Robert Phillipsd2e9f762018-03-07 11:54:37 -050051GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(
52 GrResourceProvider* resourceProvider,
Herb Derby081e6f32019-01-16 13:46:02 -050053 GrStrikeCache* glyphCache,
Robert Phillipscaf1ebb2018-03-01 14:28:44 -050054 GrTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050055 GrDeferredUploadTarget* target, GrMaskFormat format,
56 int width, int height, const void* image, SkIPoint16* loc) {
57 glyphCache->setStrikeToPreserve(strike);
58 return this->getAtlas(format)->addToAtlas(resourceProvider, id, target, width, height,
Robert Phillipsd2e9f762018-03-07 11:54:37 -050059 image, loc);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050060}
61
62void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
63 GrGlyph* glyph,
64 GrDeferredUploadToken token) {
65 SkASSERT(glyph);
Jim Van Verthba98b7d2018-12-05 12:33:43 -050066 if (updater->add(glyph->fID)) {
67 this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
68 }
Robert Phillipsc4039ea2018-03-01 11:36:45 -050069}
70
71#ifdef SK_DEBUG
Mike Kleinc0bd9f92019-04-23 12:05:21 -050072#include "src/gpu/GrContextPriv.h"
73#include "src/gpu/GrSurfaceContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040074#include "src/gpu/GrSurfaceProxy.h"
75#include "src/gpu/GrTextureProxy.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050076
Mike Kleinc0bd9f92019-04-23 12:05:21 -050077#include "include/core/SkBitmap.h"
78#include "include/core/SkImageEncoder.h"
79#include "include/core/SkStream.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050080#include <stdio.h>
81
82/**
83 * Write the contents of the surface proxy to a PNG. Returns true if successful.
84 * @param filename Full path to desired file
85 */
Brian Salomond6287472019-06-24 15:50:07 -040086static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, GrColorType colorType,
87 const char* filename) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050088 if (!sProxy) {
89 return false;
90 }
91
Brian Salomon9f2b86c2019-10-22 10:37:46 -040092 SkImageInfo ii =
93 SkImageInfo::Make(sProxy->dimensions(), kRGBA_8888_SkColorType, kPremul_SkAlphaType);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050094 SkBitmap bm;
95 if (!bm.tryAllocPixels(ii)) {
96 return false;
97 }
98
Brian Salomonbf6b9792019-08-21 09:38:10 -040099 auto sContext = context->priv().makeWrappedSurfaceContext(sk_ref_sp(sProxy), colorType,
100 kUnknown_SkAlphaType);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500101 if (!sContext || !sContext->asTextureProxy()) {
102 return false;
103 }
104
Brian Salomon1d435302019-07-01 13:05:28 -0400105 bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), {0, 0});
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500106 if (!result) {
107 SkDebugf("------ failed to read pixels for %s\n", filename);
108 return false;
109 }
110
111 // remove any previous version of this file
112 remove(filename);
113
114 SkFILEWStream file(filename);
115 if (!file.isValid()) {
116 SkDebugf("------ failed to create file: %s\n", filename);
117 remove(filename); // remove any partial file
118 return false;
119 }
120
121 if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
122 SkDebugf("------ failed to encode %s\n", filename);
123 remove(filename); // remove any partial file
124 return false;
125 }
126
127 return true;
128}
129
130void GrAtlasManager::dump(GrContext* context) const {
131 static int gDumpCount = 0;
132 for (int i = 0; i < kMaskFormatCount; ++i) {
133 if (fAtlases[i]) {
134 const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies();
135 for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
136 SkASSERT(proxies[pageIdx]);
137 SkString filename;
138#ifdef SK_BUILD_FOR_ANDROID
139 filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
140#else
141 filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
142#endif
Brian Salomond6287472019-06-24 15:50:07 -0400143 auto ct = mask_format_to_gr_color_type(AtlasIndexToMaskFormat(i));
144 save_pixels(context, proxies[pageIdx].get(), ct, filename.c_str());
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500145 }
146 }
147 }
148 ++gDumpCount;
149}
150#endif
151
Brian Salomon2638f3d2019-10-22 12:20:37 -0400152void GrAtlasManager::setAtlasDimensionsToMinimum_ForTesting() {
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500153 // Delete any old atlases.
154 // This should be safe to do as long as we are not in the middle of a flush.
155 for (int i = 0; i < kMaskFormatCount; i++) {
156 fAtlases[i] = nullptr;
157 }
Herb Derby3c4d5332018-09-07 15:27:57 -0400158
159 // Set all the atlas sizes to 1x1 plot each.
Jim Van Verthf6206f92018-12-14 08:22:24 -0500160 new (&fAtlasConfig) GrDrawOpAtlasConfig{};
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500161}
162
163bool GrAtlasManager::initAtlas(GrMaskFormat format) {
164 int index = MaskFormatToAtlasIndex(format);
Herb Derby3c4d5332018-09-07 15:27:57 -0400165 if (fAtlases[index] == nullptr) {
Robert Phillips42dda082019-05-14 13:29:45 -0400166 GrColorType grColorType = mask_format_to_gr_color_type(format);
Jim Van Verthf6206f92018-12-14 08:22:24 -0500167 SkISize atlasDimensions = fAtlasConfig.atlasDimensions(format);
168 SkISize plotDimensions = fAtlasConfig.plotDimensions(format);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500169
Robert Phillips0a15cc62019-07-30 12:49:10 -0400170 const GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType,
171 GrRenderable::kNo);
Greg Daniel4065d452018-11-16 15:43:41 -0500172
Herb Derby3c4d5332018-09-07 15:27:57 -0400173 fAtlases[index] = GrDrawOpAtlas::Make(
Robert Phillips42dda082019-05-14 13:29:45 -0400174 fProxyProvider, format, grColorType,
175 atlasDimensions.width(), atlasDimensions.height(),
176 plotDimensions.width(), plotDimensions.height(),
177 fAllowMultitexturing, &GrStrikeCache::HandleEviction, fGlyphCache);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500178 if (!fAtlases[index]) {
179 return false;
180 }
181 }
182 return true;
183}