blob: 143f84d193aa6816d3427e5bf0be66e0621f1933 [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
8#include "GrAtlasManager.h"
9
Robert Phillipsc4039ea2018-03-01 11:36:45 -050010#include "GrGlyph.h"
11#include "GrGlyphCache.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050012
Cary Clarkaa5f38f2018-09-10 20:28:05 +000013GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrGlyphCache* 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}
20 , fAtlasConfigs{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
Brian Osman2b23c4b2018-06-01 12:25:08 -040024static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050025 switch (format) {
26 case kA8_GrMaskFormat:
27 return kAlpha_8_GrPixelConfig;
28 case kA565_GrMaskFormat:
29 return kRGB_565_GrPixelConfig;
30 case kARGB_GrMaskFormat:
Brian Osman2b23c4b2018-06-01 12:25:08 -040031 return kRGBA_8888_GrPixelConfig;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050032 default:
33 SkDEBUGFAIL("unsupported GrMaskFormat");
34 return kAlpha_8_GrPixelConfig;
35 }
36}
37
Robert Phillipsc4039ea2018-03-01 11:36:45 -050038void GrAtlasManager::freeAll() {
39 for (int i = 0; i < kMaskFormatCount; ++i) {
40 fAtlases[i] = nullptr;
41 }
42}
43
44bool GrAtlasManager::hasGlyph(GrGlyph* glyph) {
45 SkASSERT(glyph);
46 return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
47}
48
49// add to texture atlas that matches this format
Robert Phillipsd2e9f762018-03-07 11:54:37 -050050GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(
51 GrResourceProvider* resourceProvider,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050052 GrGlyphCache* glyphCache,
Robert Phillipscaf1ebb2018-03-01 14:28:44 -050053 GrTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050054 GrDeferredUploadTarget* target, GrMaskFormat format,
55 int width, int height, const void* image, SkIPoint16* loc) {
56 glyphCache->setStrikeToPreserve(strike);
57 return this->getAtlas(format)->addToAtlas(resourceProvider, id, target, width, height,
Robert Phillipsd2e9f762018-03-07 11:54:37 -050058 image, loc);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050059}
60
61void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
62 GrGlyph* glyph,
63 GrDeferredUploadToken token) {
64 SkASSERT(glyph);
65 updater->add(glyph->fID);
66 this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
67}
68
69#ifdef SK_DEBUG
70#include "GrContextPriv.h"
71#include "GrSurfaceProxy.h"
72#include "GrSurfaceContext.h"
73#include "GrTextureProxy.h"
74
75#include "SkBitmap.h"
76#include "SkImageEncoder.h"
77#include "SkStream.h"
78#include <stdio.h>
79
80/**
81 * Write the contents of the surface proxy to a PNG. Returns true if successful.
82 * @param filename Full path to desired file
83 */
84static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* filename) {
85 if (!sProxy) {
86 return false;
87 }
88
89 SkImageInfo ii = SkImageInfo::Make(sProxy->width(), sProxy->height(),
90 kRGBA_8888_SkColorType, kPremul_SkAlphaType);
91 SkBitmap bm;
92 if (!bm.tryAllocPixels(ii)) {
93 return false;
94 }
95
96 sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext(
97 sk_ref_sp(sProxy)));
98 if (!sContext || !sContext->asTextureProxy()) {
99 return false;
100 }
101
102 bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), 0, 0);
103 if (!result) {
104 SkDebugf("------ failed to read pixels for %s\n", filename);
105 return false;
106 }
107
108 // remove any previous version of this file
109 remove(filename);
110
111 SkFILEWStream file(filename);
112 if (!file.isValid()) {
113 SkDebugf("------ failed to create file: %s\n", filename);
114 remove(filename); // remove any partial file
115 return false;
116 }
117
118 if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
119 SkDebugf("------ failed to encode %s\n", filename);
120 remove(filename); // remove any partial file
121 return false;
122 }
123
124 return true;
125}
126
127void GrAtlasManager::dump(GrContext* context) const {
128 static int gDumpCount = 0;
129 for (int i = 0; i < kMaskFormatCount; ++i) {
130 if (fAtlases[i]) {
131 const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies();
132 for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
133 SkASSERT(proxies[pageIdx]);
134 SkString filename;
135#ifdef SK_BUILD_FOR_ANDROID
136 filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
137#else
138 filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
139#endif
140
141 save_pixels(context, proxies[pageIdx].get(), filename.c_str());
142 }
143 }
144 }
145 ++gDumpCount;
146}
147#endif
148
Herb Derby3c4d5332018-09-07 15:27:57 -0400149void GrAtlasManager::setAtlasSizesToMinimum_ForTesting() {
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500150 // Delete any old atlases.
151 // This should be safe to do as long as we are not in the middle of a flush.
152 for (int i = 0; i < kMaskFormatCount; i++) {
153 fAtlases[i] = nullptr;
154 }
Herb Derby3c4d5332018-09-07 15:27:57 -0400155
156 // Set all the atlas sizes to 1x1 plot each.
157 new (&fAtlasConfigs) GrDrawOpAtlasConfig{};
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500158}
159
160bool GrAtlasManager::initAtlas(GrMaskFormat format) {
161 int index = MaskFormatToAtlasIndex(format);
Herb Derby3c4d5332018-09-07 15:27:57 -0400162 if (fAtlases[index] == nullptr) {
Brian Osman2b23c4b2018-06-01 12:25:08 -0400163 GrPixelConfig config = mask_format_to_pixel_config(format);
Herb Derby3c4d5332018-09-07 15:27:57 -0400164 SkISize atlasDimensions = fAtlasConfigs.atlasDimensions(format);
165 SkISize numPlots = fAtlasConfigs.numPlots(format);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500166
Herb Derby3c4d5332018-09-07 15:27:57 -0400167 fAtlases[index] = GrDrawOpAtlas::Make(
Greg Danield7157b22018-11-14 15:28:10 +0000168 fProxyProvider, config, atlasDimensions.width(), atlasDimensions.height(),
Herb Derby3c4d5332018-09-07 15:27:57 -0400169 numPlots.width(), numPlots.height(), fAllowMultitexturing,
170 &GrGlyphCache::HandleEviction, fGlyphCache);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500171 if (!fAtlases[index]) {
172 return false;
173 }
174 }
175 return true;
176}