blob: c0bbeeed0528fec73d5505649451262a112528fa [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 Phillipsc4039ea2018-03-01 11:36:45 -050025void GrAtlasManager::freeAll() {
26 for (int i = 0; i < kMaskFormatCount; ++i) {
27 fAtlases[i] = nullptr;
28 }
29}
30
Robert Phillips5fa68b42020-03-31 08:34:22 -040031bool GrAtlasManager::hasGlyph(GrMaskFormat format, GrGlyph* glyph) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050032 SkASSERT(glyph);
Robert Phillips5fa68b42020-03-31 08:34:22 -040033 return this->getAtlas(format)->hasID(glyph->fPlotLocator);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050034}
35
36// add to texture atlas that matches this format
Robert Phillipsd2e9f762018-03-07 11:54:37 -050037GrDrawOpAtlas::ErrorCode GrAtlasManager::addToAtlas(
38 GrResourceProvider* resourceProvider,
Herb Derby5ddc34c2020-02-01 20:38:30 -050039 GrDrawOpAtlas::PlotLocator* plotLocator,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050040 GrDeferredUploadTarget* target, GrMaskFormat format,
41 int width, int height, const void* image, SkIPoint16* loc) {
Herb Derby4d721712020-01-24 14:31:16 -050042 return this->getAtlas(format)->addToAtlas(
43 resourceProvider, plotLocator, target, width, height, image, loc);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050044}
45
46void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
Robert Phillips5fa68b42020-03-31 08:34:22 -040047 GrMaskFormat format, GrGlyph* glyph,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050048 GrDeferredUploadToken token) {
49 SkASSERT(glyph);
Herb Derby4d721712020-01-24 14:31:16 -050050 if (updater->add(glyph->fPlotLocator)) {
Robert Phillips5fa68b42020-03-31 08:34:22 -040051 this->getAtlas(format)->setLastUseToken(glyph->fPlotLocator, token);
Jim Van Verthba98b7d2018-12-05 12:33:43 -050052 }
Robert Phillipsc4039ea2018-03-01 11:36:45 -050053}
54
55#ifdef SK_DEBUG
Mike Kleinc0bd9f92019-04-23 12:05:21 -050056#include "src/gpu/GrContextPriv.h"
57#include "src/gpu/GrSurfaceContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040058#include "src/gpu/GrSurfaceProxy.h"
59#include "src/gpu/GrTextureProxy.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050060
Mike Kleinc0bd9f92019-04-23 12:05:21 -050061#include "include/core/SkBitmap.h"
62#include "include/core/SkImageEncoder.h"
63#include "include/core/SkStream.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050064#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 */
Greg Daniel3912a4b2020-01-14 09:56:04 -050070static bool save_pixels(GrContext* context, GrSurfaceProxyView view, GrColorType colorType,
Brian Salomond6287472019-06-24 15:50:07 -040071 const char* filename) {
Greg Daniel3912a4b2020-01-14 09:56:04 -050072 if (!view.proxy()) {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050073 return false;
74 }
75
Brian Salomon9f2b86c2019-10-22 10:37:46 -040076 SkImageInfo ii =
Greg Daniel3912a4b2020-01-14 09:56:04 -050077 SkImageInfo::Make(view.proxy()->dimensions(), kRGBA_8888_SkColorType,
78 kPremul_SkAlphaType);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050079 SkBitmap bm;
80 if (!bm.tryAllocPixels(ii)) {
81 return false;
82 }
83
Greg Daniel3912a4b2020-01-14 09:56:04 -050084 auto sContext = GrSurfaceContext::Make(context, std::move(view), colorType,
Greg Danielbfa19c42019-12-19 16:41:40 -050085 kUnknown_SkAlphaType, nullptr);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050086 if (!sContext || !sContext->asTextureProxy()) {
87 return false;
88 }
89
Brian Salomon1d435302019-07-01 13:05:28 -040090 bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), {0, 0});
Robert Phillipsc4039ea2018-03-01 11:36:45 -050091 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
115void GrAtlasManager::dump(GrContext* context) const {
116 static int gDumpCount = 0;
117 for (int i = 0; i < kMaskFormatCount; ++i) {
118 if (fAtlases[i]) {
Greg Daniel9715b6c2019-12-10 15:03:10 -0500119 const GrSurfaceProxyView* views = fAtlases[i]->getViews();
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500120 for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
Greg Daniel9715b6c2019-12-10 15:03:10 -0500121 SkASSERT(views[pageIdx].proxy());
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500122 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
Greg Daniel7c165a42020-01-22 12:22:36 -0500128 auto ct = GrMaskFormatToColorType(AtlasIndexToMaskFormat(i));
Greg Daniel3912a4b2020-01-14 09:56:04 -0500129 save_pixels(context, views[pageIdx], ct, filename.c_str());
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500130 }
131 }
132 }
133 ++gDumpCount;
134}
135#endif
136
Brian Salomon2638f3d2019-10-22 12:20:37 -0400137void GrAtlasManager::setAtlasDimensionsToMinimum_ForTesting() {
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500138 // 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 }
Herb Derby3c4d5332018-09-07 15:27:57 -0400143
144 // Set all the atlas sizes to 1x1 plot each.
Jim Van Verthf6206f92018-12-14 08:22:24 -0500145 new (&fAtlasConfig) GrDrawOpAtlasConfig{};
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500146}
147
148bool GrAtlasManager::initAtlas(GrMaskFormat format) {
149 int index = MaskFormatToAtlasIndex(format);
Herb Derby3c4d5332018-09-07 15:27:57 -0400150 if (fAtlases[index] == nullptr) {
Greg Daniel7c165a42020-01-22 12:22:36 -0500151 GrColorType grColorType = GrMaskFormatToColorType(format);
Jim Van Verthf6206f92018-12-14 08:22:24 -0500152 SkISize atlasDimensions = fAtlasConfig.atlasDimensions(format);
153 SkISize plotDimensions = fAtlasConfig.plotDimensions(format);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500154
Robert Phillips0a15cc62019-07-30 12:49:10 -0400155 const GrBackendFormat format = fCaps->getDefaultBackendFormat(grColorType,
156 GrRenderable::kNo);
Greg Daniel4065d452018-11-16 15:43:41 -0500157
Herb Derby3c4d5332018-09-07 15:27:57 -0400158 fAtlases[index] = GrDrawOpAtlas::Make(
Robert Phillips42dda082019-05-14 13:29:45 -0400159 fProxyProvider, format, grColorType,
160 atlasDimensions.width(), atlasDimensions.height(),
161 plotDimensions.width(), plotDimensions.height(),
Herb Derbya90ed952020-01-28 15:55:58 -0500162 this, fAllowMultitexturing, nullptr);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500163 if (!fAtlases[index]) {
164 return false;
165 }
166 }
167 return true;
168}