blob: fba0cbcdbe58d916169899ffa092767fd807def3 [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"
10#include "SkAtlasTextContext.h"
11#include "SkAtlasTextRenderer.h"
12#include "text/GrAtlasGlyphCache.h"
13
14SkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(
15 class SkInternalAtlasTextContext& internal) {
16 return internal.renderer();
17}
18
19//////////////////////////////////////////////////////////////////////////////
20
21std::unique_ptr<SkInternalAtlasTextContext> SkInternalAtlasTextContext::Make(
22 sk_sp<SkAtlasTextRenderer> renderer) {
23 return std::unique_ptr<SkInternalAtlasTextContext>(
24 new SkInternalAtlasTextContext(std::move(renderer)));
25}
26
27SkInternalAtlasTextContext::SkInternalAtlasTextContext(sk_sp<SkAtlasTextRenderer> renderer)
28 : fRenderer(std::move(renderer)) {
29 GrContextOptions options;
30 options.fAllowMultipleGlyphCacheTextures = GrContextOptions::Enable::kNo;
31 options.fMinDistanceFieldFontSize = 0.f;
32 options.fGlyphsAsPathsFontSize = SK_ScalarInfinity;
Brian Salomonb5086962017-12-13 10:59:33 -050033 options.fDistanceFieldGlyphVerticesAlwaysHaveW = GrContextOptions::Enable::kYes;
Brian Salomoncbcb0a12017-11-19 13:20:13 -050034 fGrContext = GrContext::MakeMock(nullptr, options);
35}
36
37SkInternalAtlasTextContext::~SkInternalAtlasTextContext() {
38 if (fDistanceFieldAtlas.fProxy) {
39 SkASSERT(1 == fGrContext->getAtlasGlyphCache()->getAtlasPageCount(kA8_GrMaskFormat));
40 fRenderer->deleteTexture(fDistanceFieldAtlas.fTextureHandle);
41 }
42}
43
44GrAtlasGlyphCache* SkInternalAtlasTextContext::atlasGlyphCache() {
45 return fGrContext->getAtlasGlyphCache();
46}
47
48GrTextBlobCache* SkInternalAtlasTextContext::textBlobCache() {
49 return fGrContext->getTextBlobCache();
50}
51
52GrDeferredUploadToken SkInternalAtlasTextContext::addInlineUpload(
53 GrDeferredTextureUploadFn&& upload) {
Robert Phillips40a29d72018-01-18 12:59:22 -050054 auto token = fTokenTracker.nextDrawToken();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050055 fInlineUploads.append(&fArena, InlineUpload{std::move(upload), token});
56 return token;
57}
58
59GrDeferredUploadToken SkInternalAtlasTextContext::addASAPUpload(
60 GrDeferredTextureUploadFn&& upload) {
61 fASAPUploads.append(&fArena, std::move(upload));
Robert Phillips40a29d72018-01-18 12:59:22 -050062 return fTokenTracker.nextTokenToFlush();
Brian Salomoncbcb0a12017-11-19 13:20:13 -050063}
64
65void SkInternalAtlasTextContext::recordDraw(const void* srcVertexData, int glyphCnt,
Brian Salomonb5086962017-12-13 10:59:33 -050066 const SkMatrix& matrix, void* targetHandle) {
Brian Salomoncbcb0a12017-11-19 13:20:13 -050067 auto vertexDataSize = sizeof(SkAtlasTextRenderer::SDFVertex) * 4 * glyphCnt;
68 auto vertexData = fArena.makeArrayDefault<char>(vertexDataSize);
69 memcpy(vertexData, srcVertexData, vertexDataSize);
70 for (int i = 0; i < 4 * glyphCnt; ++i) {
71 auto* vertex = reinterpret_cast<SkAtlasTextRenderer::SDFVertex*>(vertexData) + i;
72 // GrAtlasTextContext encodes a texture index into the lower bit of each texture coord.
73 // This isn't expected by SkAtlasTextRenderer subclasses.
74 vertex->fTextureCoord.fX /= 2;
75 vertex->fTextureCoord.fY /= 2;
Brian Salomonb5086962017-12-13 10:59:33 -050076 matrix.mapHomogeneousPoints(&vertex->fPosition, &vertex->fPosition, 1);
Brian Salomoncbcb0a12017-11-19 13:20:13 -050077 }
Robert Phillips40a29d72018-01-18 12:59:22 -050078 fDraws.append(&fArena,
79 Draw{glyphCnt, fTokenTracker.issueDrawToken(), targetHandle, vertexData});
Brian Salomoncbcb0a12017-11-19 13:20:13 -050080}
81
82void SkInternalAtlasTextContext::flush() {
83 auto* atlasGlyphCache = fGrContext->getAtlasGlyphCache();
84 if (!fDistanceFieldAtlas.fProxy) {
85 SkASSERT(1 == atlasGlyphCache->getAtlasPageCount(kA8_GrMaskFormat));
86 fDistanceFieldAtlas.fProxy = atlasGlyphCache->getProxies(kA8_GrMaskFormat)->get();
87 fDistanceFieldAtlas.fTextureHandle =
88 fRenderer->createTexture(SkAtlasTextRenderer::AtlasFormat::kA8,
89 fDistanceFieldAtlas.fProxy->width(),
90 fDistanceFieldAtlas.fProxy->height());
91 }
92 GrDeferredTextureUploadWritePixelsFn writePixelsFn =
93 [this](GrTextureProxy* proxy, int left, int top, int width, int height,
94 GrPixelConfig config, const void* data, size_t rowBytes) -> bool {
95 SkASSERT(kAlpha_8_GrPixelConfig == config);
96 SkASSERT(proxy == this->fDistanceFieldAtlas.fProxy);
97 void* handle = fDistanceFieldAtlas.fTextureHandle;
98 this->fRenderer->setTextureData(handle, data, left, top, width, height, rowBytes);
99 return true;
100 };
101 for (const auto& upload : fASAPUploads) {
102 upload(writePixelsFn);
103 }
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500104 auto inlineUpload = fInlineUploads.begin();
Brian Salomoncf1aa532017-11-29 14:58:59 -0500105 for (const auto& draw : fDraws) {
106 while (inlineUpload != fInlineUploads.end() && inlineUpload->fToken == draw.fToken) {
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500107 inlineUpload->fUpload(writePixelsFn);
108 ++inlineUpload;
109 }
Brian Salomoncf1aa532017-11-29 14:58:59 -0500110 auto vertices = reinterpret_cast<const SkAtlasTextRenderer::SDFVertex*>(draw.fVertexData);
111 fRenderer->drawSDFGlyphs(draw.fTargetHandle, fDistanceFieldAtlas.fTextureHandle, vertices,
112 draw.fGlyphCnt);
Robert Phillips40a29d72018-01-18 12:59:22 -0500113 fTokenTracker.flushToken();
Brian Salomoncbcb0a12017-11-19 13:20:13 -0500114 }
115 fASAPUploads.reset();
116 fInlineUploads.reset();
117 fDraws.reset();
118 fArena.reset();
119}