blob: fc3036e083a238adc23a4fb7c2b0e820620bfec7 [file] [log] [blame]
Brian Salomoncbcb0a12017-11-19 13:20:13 -05001/*
2 * Copyright 2017 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 "include/atlastext/SkAtlasTextContext.h"
9#include "include/atlastext/SkAtlasTextRenderer.h"
10#include "include/gpu/GrContext.h"
11#include "src/atlastext/SkInternalAtlasTextContext.h"
12#include "src/gpu/GrContextPriv.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040013#include "src/gpu/text/GrAtlasManager.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/text/GrStrikeCache.h"
Brian Salomoncbcb0a12017-11-19 13:20:13 -050015
16SkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(
17 class SkInternalAtlasTextContext& internal) {
18 return internal.renderer();
19}
20
21//////////////////////////////////////////////////////////////////////////////
22
23std::unique_ptr<SkInternalAtlasTextContext> SkInternalAtlasTextContext::Make(
24 sk_sp<SkAtlasTextRenderer> renderer) {
25 return std::unique_ptr<SkInternalAtlasTextContext>(
26 new SkInternalAtlasTextContext(std::move(renderer)));
27}
28
29SkInternalAtlasTextContext::SkInternalAtlasTextContext(sk_sp<SkAtlasTextRenderer> renderer)
30 : fRenderer(std::move(renderer)) {
31 GrContextOptions options;
32 options.fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo;
33 options.fMinDistanceFieldFontSize = 0.f;
34 options.fGlyphsAsPathsFontSize = SK_ScalarInfinity;
Brian Salomonb5086962017-12-13 10:59:33 -050035 options.fDistanceFieldGlyphVerticesAlwaysHaveW = GrContextOptions::Enable::kYes;
Brian Salomoncbcb0a12017-11-19 13:20:13 -050036 fGrContext = GrContext::MakeMock(nullptr, options);
37}
38
39SkInternalAtlasTextContext::~SkInternalAtlasTextContext() {
40 if (fDistanceFieldAtlas.fProxy) {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050041#ifdef SK_DEBUG
Robert Phillips9da87e02019-02-04 13:26:26 -050042 auto atlasManager = fGrContext->priv().getAtlasManager();
Robert Phillips5a66efb2018-03-07 15:13:18 -050043 if (atlasManager) {
44 unsigned int numProxies;
Greg Daniel9715b6c2019-12-10 15:03:10 -050045 atlasManager->getViews(kA8_GrMaskFormat, &numProxies);
Robert Phillips5a66efb2018-03-07 15:13:18 -050046 SkASSERT(1 == numProxies);
47 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050048#endif
Brian Salomoncbcb0a12017-11-19 13:20:13 -050049 fRenderer->deleteTexture(fDistanceFieldAtlas.fTextureHandle);
50 }
51}
52
Herb Derby081e6f32019-01-16 13:46:02 -050053GrStrikeCache* SkInternalAtlasTextContext::glyphCache() {
Herb Derbya00da612019-03-04 17:10:01 -050054 return fGrContext->priv().getGrStrikeCache();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050055}
56
57GrTextBlobCache* SkInternalAtlasTextContext::textBlobCache() {
Robert Phillips9da87e02019-02-04 13:26:26 -050058 return fGrContext->priv().getTextBlobCache();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050059}
60
61GrDeferredUploadToken SkInternalAtlasTextContext::addInlineUpload(
62 GrDeferredTextureUploadFn&& upload) {
Robert Phillips40a29d72018-01-18 12:59:22 -050063 auto token = fTokenTracker.nextDrawToken();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050064 fInlineUploads.append(&fArena, InlineUpload{std::move(upload), token});
65 return token;
66}
67
68GrDeferredUploadToken SkInternalAtlasTextContext::addASAPUpload(
69 GrDeferredTextureUploadFn&& upload) {
70 fASAPUploads.append(&fArena, std::move(upload));
Robert Phillips40a29d72018-01-18 12:59:22 -050071 return fTokenTracker.nextTokenToFlush();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050072}
73
74void SkInternalAtlasTextContext::recordDraw(const void* srcVertexData, int glyphCnt,
Brian Salomonb5086962017-12-13 10:59:33 -050075 const SkMatrix& matrix, void* targetHandle) {
Brian Salomoncbcb0a12017-11-19 13:20:13 -050076 auto vertexDataSize = sizeof(SkAtlasTextRenderer::SDFVertex) * 4 * glyphCnt;
77 auto vertexData = fArena.makeArrayDefault<char>(vertexDataSize);
78 memcpy(vertexData, srcVertexData, vertexDataSize);
79 for (int i = 0; i < 4 * glyphCnt; ++i) {
80 auto* vertex = reinterpret_cast<SkAtlasTextRenderer::SDFVertex*>(vertexData) + i;
Jim Van Verth2f2c77a2020-01-24 15:48:23 +000081 // GrTextContext encodes a texture index into the lower bit of each texture coord.
82 // This isn't expected by SkAtlasTextRenderer subclasses.
83 vertex->fTextureCoordX /= 2;
84 vertex->fTextureCoordY /= 2;
Brian Salomonb5086962017-12-13 10:59:33 -050085 matrix.mapHomogeneousPoints(&vertex->fPosition, &vertex->fPosition, 1);
Brian Salomoncbcb0a12017-11-19 13:20:13 -050086 }
Robert Phillips40a29d72018-01-18 12:59:22 -050087 fDraws.append(&fArena,
88 Draw{glyphCnt, fTokenTracker.issueDrawToken(), targetHandle, vertexData});
Brian Salomoncbcb0a12017-11-19 13:20:13 -050089}
90
91void SkInternalAtlasTextContext::flush() {
Robert Phillips9da87e02019-02-04 13:26:26 -050092 auto* atlasManager = fGrContext->priv().getAtlasManager();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050093 if (!fDistanceFieldAtlas.fProxy) {
Robert Phillipsf3690dd2018-02-20 15:18:59 -050094 unsigned int numProxies;
Greg Daniel9715b6c2019-12-10 15:03:10 -050095 fDistanceFieldAtlas.fProxy =
96 atlasManager->getViews(kA8_GrMaskFormat, &numProxies)->asTextureProxy();
Robert Phillipsf3690dd2018-02-20 15:18:59 -050097 SkASSERT(1 == numProxies);
Brian Salomoncbcb0a12017-11-19 13:20:13 -050098 fDistanceFieldAtlas.fTextureHandle =
99 fRenderer->createTexture(SkAtlasTextRenderer::AtlasFormat::kA8,
100 fDistanceFieldAtlas.fProxy->width(),
101 fDistanceFieldAtlas.fProxy->height());
102 }
103 GrDeferredTextureUploadWritePixelsFn writePixelsFn =
104 [this](GrTextureProxy* proxy, int left, int top, int width, int height,
Brian Salomonc320b152018-02-20 14:05:36 -0500105 GrColorType colorType, const void* data, size_t rowBytes) -> bool {
106 SkASSERT(GrColorType::kAlpha_8 == colorType);
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500107 SkASSERT(proxy == this->fDistanceFieldAtlas.fProxy);
108 void* handle = fDistanceFieldAtlas.fTextureHandle;
109 this->fRenderer->setTextureData(handle, data, left, top, width, height, rowBytes);
110 return true;
111 };
112 for (const auto& upload : fASAPUploads) {
113 upload(writePixelsFn);
114 }
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500115 auto inlineUpload = fInlineUploads.begin();
Brian Salomoncf1aa532017-11-29 14:58:59 -0500116 for (const auto& draw : fDraws) {
117 while (inlineUpload != fInlineUploads.end() && inlineUpload->fToken == draw.fToken) {
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500118 inlineUpload->fUpload(writePixelsFn);
119 ++inlineUpload;
120 }
Brian Salomoncf1aa532017-11-29 14:58:59 -0500121 auto vertices = reinterpret_cast<const SkAtlasTextRenderer::SDFVertex*>(draw.fVertexData);
122 fRenderer->drawSDFGlyphs(draw.fTargetHandle, fDistanceFieldAtlas.fTextureHandle, vertices,
123 draw.fGlyphCnt);
Robert Phillips40a29d72018-01-18 12:59:22 -0500124 fTokenTracker.flushToken();
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500125 }
126 fASAPUploads.reset();
127 fInlineUploads.reset();
128 fDraws.reset();
129 fArena.reset();
130}