blob: c91eab69d43e0c4ba0785769b068d95531ef4251 [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
Robert Phillips207d24b2020-04-09 10:23:42 -040014GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider,
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()}
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 Phillipsc4039ea2018-03-01 11:36:45 -050024void GrAtlasManager::freeAll() {
25 for (int i = 0; i < kMaskFormatCount; ++i) {
26 fAtlases[i] = nullptr;
27 }
28}
29
Robert Phillips5fa68b42020-03-31 08:34:22 -040030bool GrAtlasManager::hasGlyph(GrMaskFormat format, GrGlyph* glyph) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050031 SkASSERT(glyph);
Robert Phillipsbf5bf742020-04-13 09:29:08 -040032 return this->getAtlas(format)->hasID(glyph->fAtlasLocator.plotLocator());
Robert Phillipsc4039ea2018-03-01 11:36:45 -050033}
34
35// add to texture atlas that matches this format
Robert Phillips6d3bc292020-04-06 10:29:28 -040036GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(GrResourceProvider* resourceProvider,
37 GrDeferredUploadTarget* target,
38 GrMaskFormat format,
39 int width, int height, const void* image,
40 GrDrawOpAtlas::AtlasLocator* atlasLocator) {
Herb Derby4d721712020-01-24 14:31:16 -050041 return this->getAtlas(format)->addToAtlas(
Robert Phillips6d3bc292020-04-06 10:29:28 -040042 resourceProvider, target, width, height, image, atlasLocator);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050043}
44
45void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
Robert Phillips5fa68b42020-03-31 08:34:22 -040046 GrMaskFormat format, GrGlyph* glyph,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050047 GrDeferredUploadToken token) {
48 SkASSERT(glyph);
Robert Phillips6d3bc292020-04-06 10:29:28 -040049 if (updater->add(glyph->fAtlasLocator)) {
50 this->getAtlas(format)->setLastUseToken(glyph->fAtlasLocator, token);
Jim Van Verthba98b7d2018-12-05 12:33:43 -050051 }
Robert Phillipsc4039ea2018-03-01 11:36:45 -050052}
53
54#ifdef SK_DEBUG
Mike Kleinc0bd9f92019-04-23 12:05:21 -050055#include "src/gpu/GrContextPriv.h"
56#include "src/gpu/GrSurfaceContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040057#include "src/gpu/GrSurfaceProxy.h"
58#include "src/gpu/GrTextureProxy.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050059
Mike Kleinc0bd9f92019-04-23 12:05:21 -050060#include "include/core/SkBitmap.h"
61#include "include/core/SkImageEncoder.h"
62#include "include/core/SkStream.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050063#include <stdio.h>
64
65/**
66 * Write the contents of the surface proxy to a PNG. Returns true if successful.
67 * @param filename Full path to desired file
68 */
Greg Daniel3912a4b2020-01-14 09:56:04 -050069static bool save_pixels(GrContext* context, GrSurfaceProxyView view, GrColorType colorType,
Brian Salomond6287472019-06-24 15:50:07 -040070 const char* filename) {
Greg Daniel3912a4b2020-01-14 09:56:04 -050071 if (!view.proxy()) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050072 return false;
73 }
74
Brian Salomon9f2b86c2019-10-22 10:37:46 -040075 SkImageInfo ii =
Greg Daniel3912a4b2020-01-14 09:56:04 -050076 SkImageInfo::Make(view.proxy()->dimensions(), kRGBA_8888_SkColorType,
77 kPremul_SkAlphaType);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050078 SkBitmap bm;
79 if (!bm.tryAllocPixels(ii)) {
80 return false;
81 }
82
Greg Daniel3912a4b2020-01-14 09:56:04 -050083 auto sContext = GrSurfaceContext::Make(context, std::move(view), colorType,
Greg Danielbfa19c42019-12-19 16:41:40 -050084 kUnknown_SkAlphaType, nullptr);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050085 if (!sContext || !sContext->asTextureProxy()) {
86 return false;
87 }
88
Brian Salomon1d435302019-07-01 13:05:28 -040089 bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), {0, 0});
Robert Phillipsc4039ea2018-03-01 11:36:45 -050090 if (!result) {
91 SkDebugf("------ failed to read pixels for %s\n", filename);
92 return false;
93 }
94
95 // remove any previous version of this file
96 remove(filename);
97
98 SkFILEWStream file(filename);
99 if (!file.isValid()) {
100 SkDebugf("------ failed to create file: %s\n", filename);
101 remove(filename); // remove any partial file
102 return false;
103 }
104
105 if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
106 SkDebugf("------ failed to encode %s\n", filename);
107 remove(filename); // remove any partial file
108 return false;
109 }
110
111 return true;
112}
113
114void GrAtlasManager::dump(GrContext* context) const {
115 static int gDumpCount = 0;
116 for (int i = 0; i < kMaskFormatCount; ++i) {
117 if (fAtlases[i]) {
Greg Daniel9715b6c2019-12-10 15:03:10 -0500118 const GrSurfaceProxyView* views = fAtlases[i]->getViews();
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500119 for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
Greg Daniel9715b6c2019-12-10 15:03:10 -0500120 SkASSERT(views[pageIdx].proxy());
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500121 SkString filename;
122#ifdef SK_BUILD_FOR_ANDROID
123 filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
124#else
125 filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
126#endif
Greg Daniel7c165a42020-01-22 12:22:36 -0500127 auto ct = GrMaskFormatToColorType(AtlasIndexToMaskFormat(i));
Greg Daniel3912a4b2020-01-14 09:56:04 -0500128 save_pixels(context, views[pageIdx], ct, filename.c_str());
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500129 }
130 }
131 }
132 ++gDumpCount;
133}
134#endif
135
Brian Salomon2638f3d2019-10-22 12:20:37 -0400136void GrAtlasManager::setAtlasDimensionsToMinimum_ForTesting() {
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500137 // Delete any old atlases.
138 // This should be safe to do as long as we are not in the middle of a flush.
139 for (int i = 0; i < kMaskFormatCount; i++) {
140 fAtlases[i] = nullptr;
141 }
Herb Derby3c4d5332018-09-07 15:27:57 -0400142
143 // Set all the atlas sizes to 1x1 plot each.
Jim Van Verthf6206f92018-12-14 08:22:24 -0500144 new (&fAtlasConfig) GrDrawOpAtlasConfig{};
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500145}
146
147bool GrAtlasManager::initAtlas(GrMaskFormat format) {
148 int index = MaskFormatToAtlasIndex(format);
Herb Derby3c4d5332018-09-07 15:27:57 -0400149 if (fAtlases[index] == nullptr) {
Greg Daniel7c165a42020-01-22 12:22:36 -0500150 GrColorType grColorType = GrMaskFormatToColorType(format);
Jim Van Verthf6206f92018-12-14 08:22:24 -0500151 SkISize atlasDimensions = fAtlasConfig.atlasDimensions(format);
152 SkISize plotDimensions = fAtlasConfig.plotDimensions(format);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500153
Robert Phillips0a15cc62019-07-30 12:49:10 -0400154 const GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType,
155 GrRenderable::kNo);
Greg Daniel4065d452018-11-16 15:43:41 -0500156
Herb Derby3c4d5332018-09-07 15:27:57 -0400157 fAtlases[index] = GrDrawOpAtlas::Make(
Robert Phillips42dda082019-05-14 13:29:45 -0400158 fProxyProvider, format, grColorType,
159 atlasDimensions.width(), atlasDimensions.height(),
160 plotDimensions.width(), plotDimensions.height(),
Herb Derbya90ed952020-01-28 15:55:58 -0500161 this, fAllowMultitexturing, nullptr);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500162 if (!fAtlases[index]) {
163 return false;
164 }
165 }
166 return true;
167}