blob: 2c9cddcc7712d6b7b8e76db7c6861e270b9c17ef [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
8#include "SkInternalAtlasTextContext.h"
9#include "GrContext.h"
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050010#include "GrContextPriv.h"
Brian Salomoncbcb0a12017-11-19 13:20:13 -050011#include "SkAtlasTextContext.h"
12#include "SkAtlasTextRenderer.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050013#include "text/GrGlyphCache.h"
Brian Salomoncbcb0a12017-11-19 13:20:13 -050014
15SkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(
16 class SkInternalAtlasTextContext& internal) {
17 return internal.renderer();
18}
19
20//////////////////////////////////////////////////////////////////////////////
21
22std::unique_ptr<SkInternalAtlasTextContext> SkInternalAtlasTextContext::Make(
23 sk_sp<SkAtlasTextRenderer> renderer) {
24 return std::unique_ptr<SkInternalAtlasTextContext>(
25 new SkInternalAtlasTextContext(std::move(renderer)));
26}
27
28SkInternalAtlasTextContext::SkInternalAtlasTextContext(sk_sp<SkAtlasTextRenderer> renderer)
29 : fRenderer(std::move(renderer)) {
30 GrContextOptions options;
31 options.fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo;
32 options.fMinDistanceFieldFontSize = 0.f;
33 options.fGlyphsAsPathsFontSize = SK_ScalarInfinity;
Brian Salomonb5086962017-12-13 10:59:33 -050034 options.fDistanceFieldGlyphVerticesAlwaysHaveW = GrContextOptions::Enable::kYes;
Brian Salomoncbcb0a12017-11-19 13:20:13 -050035 fGrContext = GrContext::MakeMock(nullptr, options);
36}
37
38SkInternalAtlasTextContext::~SkInternalAtlasTextContext() {
39 if (fDistanceFieldAtlas.fProxy) {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050040#ifdef SK_DEBUG
Robert Phillips5a66efb2018-03-07 15:13:18 -050041 auto atlasManager = fGrContext->contextPriv().getAtlasManager();
42 if (atlasManager) {
43 unsigned int numProxies;
44 atlasManager->getProxies(kA8_GrMaskFormat, &numProxies);
45 SkASSERT(1 == numProxies);
46 }
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050047#endif
Brian Salomoncbcb0a12017-11-19 13:20:13 -050048 fRenderer->deleteTexture(fDistanceFieldAtlas.fTextureHandle);
49 }
50}
51
Robert Phillipsc4039ea2018-03-01 11:36:45 -050052GrGlyphCache* SkInternalAtlasTextContext::glyphCache() {
53 return fGrContext->contextPriv().getGlyphCache();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050054}
55
56GrTextBlobCache* SkInternalAtlasTextContext::textBlobCache() {
Robert Phillipsf35fd8d2018-01-22 10:48:15 -050057 return fGrContext->contextPriv().getTextBlobCache();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050058}
59
60GrDeferredUploadToken SkInternalAtlasTextContext::addInlineUpload(
61 GrDeferredTextureUploadFn&& upload) {
Robert Phillips40a29d72018-01-18 12:59:22 -050062 auto token = fTokenTracker.nextDrawToken();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050063 fInlineUploads.append(&fArena, InlineUpload{std::move(upload), token});
64 return token;
65}
66
67GrDeferredUploadToken SkInternalAtlasTextContext::addASAPUpload(
68 GrDeferredTextureUploadFn&& upload) {
69 fASAPUploads.append(&fArena, std::move(upload));
Robert Phillips40a29d72018-01-18 12:59:22 -050070 return fTokenTracker.nextTokenToFlush();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050071}
72
73void SkInternalAtlasTextContext::recordDraw(const void* srcVertexData, int glyphCnt,
Brian Salomonb5086962017-12-13 10:59:33 -050074 const SkMatrix& matrix, void* targetHandle) {
Brian Salomoncbcb0a12017-11-19 13:20:13 -050075 auto vertexDataSize = sizeof(SkAtlasTextRenderer::SDFVertex) * 4 * glyphCnt;
76 auto vertexData = fArena.makeArrayDefault<char>(vertexDataSize);
77 memcpy(vertexData, srcVertexData, vertexDataSize);
78 for (int i = 0; i < 4 * glyphCnt; ++i) {
79 auto* vertex = reinterpret_cast<SkAtlasTextRenderer::SDFVertex*>(vertexData) + i;
Herb Derby26cbe512018-05-24 14:39:01 -040080 // GrTextContext encodes a texture index into the lower bit of each texture coord.
Brian Salomoncbcb0a12017-11-19 13:20:13 -050081 // This isn't expected by SkAtlasTextRenderer subclasses.
Mike Reed1fda0242018-04-04 15:39:46 -040082 vertex->fTextureCoordX /= 2;
83 vertex->fTextureCoordY /= 2;
Brian Salomonb5086962017-12-13 10:59:33 -050084 matrix.mapHomogeneousPoints(&vertex->fPosition, &vertex->fPosition, 1);
Brian Salomoncbcb0a12017-11-19 13:20:13 -050085 }
Robert Phillips40a29d72018-01-18 12:59:22 -050086 fDraws.append(&fArena,
87 Draw{glyphCnt, fTokenTracker.issueDrawToken(), targetHandle, vertexData});
Brian Salomoncbcb0a12017-11-19 13:20:13 -050088}
89
90void SkInternalAtlasTextContext::flush() {
Robert Phillips5a66efb2018-03-07 15:13:18 -050091 auto* atlasManager = fGrContext->contextPriv().getAtlasManager();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050092 if (!fDistanceFieldAtlas.fProxy) {
Robert Phillipsf3690dd2018-02-20 15:18:59 -050093 unsigned int numProxies;
Robert Phillips5a66efb2018-03-07 15:13:18 -050094 fDistanceFieldAtlas.fProxy = atlasManager->getProxies(kA8_GrMaskFormat, &numProxies)->get();
Robert Phillipsf3690dd2018-02-20 15:18:59 -050095 SkASSERT(1 == numProxies);
Brian Salomoncbcb0a12017-11-19 13:20:13 -050096 fDistanceFieldAtlas.fTextureHandle =
97 fRenderer->createTexture(SkAtlasTextRenderer::AtlasFormat::kA8,
98 fDistanceFieldAtlas.fProxy->width(),
99 fDistanceFieldAtlas.fProxy->height());
100 }
101 GrDeferredTextureUploadWritePixelsFn writePixelsFn =
102 [this](GrTextureProxy* proxy, int left, int top, int width, int height,
Brian Salomonc320b152018-02-20 14:05:36 -0500103 GrColorType colorType, const void* data, size_t rowBytes) -> bool {
104 SkASSERT(GrColorType::kAlpha_8 == colorType);
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500105 SkASSERT(proxy == this->fDistanceFieldAtlas.fProxy);
106 void* handle = fDistanceFieldAtlas.fTextureHandle;
107 this->fRenderer->setTextureData(handle, data, left, top, width, height, rowBytes);
108 return true;
109 };
110 for (const auto& upload : fASAPUploads) {
111 upload(writePixelsFn);
112 }
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500113 auto inlineUpload = fInlineUploads.begin();
Brian Salomoncf1aa532017-11-29 14:58:59 -0500114 for (const auto& draw : fDraws) {
115 while (inlineUpload != fInlineUploads.end() && inlineUpload->fToken == draw.fToken) {
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500116 inlineUpload->fUpload(writePixelsFn);
117 ++inlineUpload;
118 }
Brian Salomoncf1aa532017-11-29 14:58:59 -0500119 auto vertices = reinterpret_cast<const SkAtlasTextRenderer::SDFVertex*>(draw.fVertexData);
120 fRenderer->drawSDFGlyphs(draw.fTargetHandle, fDistanceFieldAtlas.fTextureHandle, vertices,
121 draw.fGlyphCnt);
Robert Phillips40a29d72018-01-18 12:59:22 -0500122 fTokenTracker.flushToken();
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500123 }
124 fASAPUploads.reset();
125 fInlineUploads.reset();
126 fDraws.reset();
127 fArena.reset();
128}