• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "GrContextPriv.h"
11 #include "SkAtlasTextContext.h"
12 #include "SkAtlasTextRenderer.h"
13 #include "text/GrStrikeCache.h"
14 
SkGetAtlasTextRendererFromInternalContext(class SkInternalAtlasTextContext & internal)15 SkAtlasTextRenderer* SkGetAtlasTextRendererFromInternalContext(
16         class SkInternalAtlasTextContext& internal) {
17     return internal.renderer();
18 }
19 
20 //////////////////////////////////////////////////////////////////////////////
21 
Make(sk_sp<SkAtlasTextRenderer> renderer)22 std::unique_ptr<SkInternalAtlasTextContext> SkInternalAtlasTextContext::Make(
23         sk_sp<SkAtlasTextRenderer> renderer) {
24     return std::unique_ptr<SkInternalAtlasTextContext>(
25             new SkInternalAtlasTextContext(std::move(renderer)));
26 }
27 
SkInternalAtlasTextContext(sk_sp<SkAtlasTextRenderer> renderer)28 SkInternalAtlasTextContext::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;
34     options.fDistanceFieldGlyphVerticesAlwaysHaveW = GrContextOptions::Enable::kYes;
35     fGrContext = GrContext::MakeMock(nullptr, options);
36 }
37 
~SkInternalAtlasTextContext()38 SkInternalAtlasTextContext::~SkInternalAtlasTextContext() {
39     if (fDistanceFieldAtlas.fProxy) {
40 #ifdef SK_DEBUG
41         auto atlasManager = fGrContext->contextPriv().getAtlasManager();
42         if (atlasManager) {
43             unsigned int numProxies;
44             atlasManager->getProxies(kA8_GrMaskFormat, &numProxies);
45             SkASSERT(1 == numProxies);
46         }
47 #endif
48         fRenderer->deleteTexture(fDistanceFieldAtlas.fTextureHandle);
49     }
50 }
51 
glyphCache()52 GrStrikeCache* SkInternalAtlasTextContext::glyphCache() {
53     return fGrContext->contextPriv().getGlyphCache();
54 }
55 
textBlobCache()56 GrTextBlobCache* SkInternalAtlasTextContext::textBlobCache() {
57     return fGrContext->contextPriv().getTextBlobCache();
58 }
59 
addInlineUpload(GrDeferredTextureUploadFn && upload)60 GrDeferredUploadToken SkInternalAtlasTextContext::addInlineUpload(
61         GrDeferredTextureUploadFn&& upload) {
62     auto token = fTokenTracker.nextDrawToken();
63     fInlineUploads.append(&fArena, InlineUpload{std::move(upload), token});
64     return token;
65 }
66 
addASAPUpload(GrDeferredTextureUploadFn && upload)67 GrDeferredUploadToken SkInternalAtlasTextContext::addASAPUpload(
68         GrDeferredTextureUploadFn&& upload) {
69     fASAPUploads.append(&fArena, std::move(upload));
70     return fTokenTracker.nextTokenToFlush();
71 }
72 
recordDraw(const void * srcVertexData,int glyphCnt,const SkMatrix & matrix,void * targetHandle)73 void SkInternalAtlasTextContext::recordDraw(const void* srcVertexData, int glyphCnt,
74                                             const SkMatrix& matrix, void* targetHandle) {
75     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;
80         // GrTextContext encodes a texture index into the lower bit of each texture coord.
81         // This isn't expected by SkAtlasTextRenderer subclasses.
82         vertex->fTextureCoordX /= 2;
83         vertex->fTextureCoordY /= 2;
84         matrix.mapHomogeneousPoints(&vertex->fPosition, &vertex->fPosition, 1);
85     }
86     fDraws.append(&fArena,
87                   Draw{glyphCnt, fTokenTracker.issueDrawToken(), targetHandle, vertexData});
88 }
89 
flush()90 void SkInternalAtlasTextContext::flush() {
91     auto* atlasManager = fGrContext->contextPriv().getAtlasManager();
92     if (!fDistanceFieldAtlas.fProxy) {
93         unsigned int numProxies;
94         fDistanceFieldAtlas.fProxy = atlasManager->getProxies(kA8_GrMaskFormat, &numProxies)->get();
95         SkASSERT(1 == numProxies);
96         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,
103                    GrColorType colorType, const void* data, size_t rowBytes) -> bool {
104         SkASSERT(GrColorType::kAlpha_8 == colorType);
105         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     }
113     auto inlineUpload = fInlineUploads.begin();
114     for (const auto& draw : fDraws) {
115         while (inlineUpload != fInlineUploads.end() && inlineUpload->fToken == draw.fToken) {
116             inlineUpload->fUpload(writePixelsFn);
117             ++inlineUpload;
118         }
119         auto vertices = reinterpret_cast<const SkAtlasTextRenderer::SDFVertex*>(draw.fVertexData);
120         fRenderer->drawSDFGlyphs(draw.fTargetHandle, fDistanceFieldAtlas.fTextureHandle, vertices,
121                                  draw.fGlyphCnt);
122         fTokenTracker.flushToken();
123     }
124     fASAPUploads.reset();
125     fInlineUploads.reset();
126     fDraws.reset();
127     fArena.reset();
128 }
129