1 /*
2  * Copyright 2019 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 "include/private/GrRecordingContext.h"
9 
10 #include "include/gpu/GrContext.h"
11 #include "src/gpu/GrAuditTrail.h"
12 #include "src/gpu/GrCaps.h"
13 #include "src/gpu/GrDrawingManager.h"
14 #include "src/gpu/GrMemoryPool.h"
15 #include "src/gpu/GrProxyProvider.h"
16 #include "src/gpu/GrRecordingContextPriv.h"
17 #include "src/gpu/GrRenderTargetContext.h"
18 #include "src/gpu/GrSkSLFPFactoryCache.h"
19 #include "src/gpu/GrTextureContext.h"
20 #include "src/gpu/SkGr.h"
21 #include "src/gpu/text/GrTextBlobCache.h"
22 
23 #define ASSERT_SINGLE_OWNER_PRIV \
24     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
25 
GrRecordingContext(GrBackendApi backend,const GrContextOptions & options,uint32_t contextID)26 GrRecordingContext::GrRecordingContext(GrBackendApi backend,
27                                        const GrContextOptions& options,
28                                        uint32_t contextID)
29         : INHERITED(backend, options, contextID)
30         , fAuditTrail(new GrAuditTrail()) {
31 }
32 
~GrRecordingContext()33 GrRecordingContext::~GrRecordingContext() { }
34 
35 /**
36  * TODO: move textblob draw calls below context (see comment below)
37  */
textblobcache_overbudget_CB(void * data)38 static void textblobcache_overbudget_CB(void* data) {
39     SkASSERT(data);
40     GrRecordingContext* context = reinterpret_cast<GrRecordingContext*>(data);
41 
42     GrContext* direct = context->priv().asDirectContext();
43     if (!direct) {
44         return;
45     }
46 
47     // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
48     // GrRenderTargetContext to perform a necessary flush.  The solution is to move drawText calls
49     // to below the GrContext level, but this is not trivial because they call drawPath on
50     // SkGpuDevice.
51     direct->flush();
52 }
53 
init(sk_sp<const GrCaps> caps,sk_sp<GrSkSLFPFactoryCache> cache)54 bool GrRecordingContext::init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> cache) {
55 
56     if (!INHERITED::init(std::move(caps), std::move(cache))) {
57         return false;
58     }
59 
60     fStrikeCache.reset(new GrStrikeCache(this->caps(),
61                                         this->options().fGlyphCacheTextureMaximumBytes));
62 
63     fTextBlobCache.reset(new GrTextBlobCache(textblobcache_overbudget_CB, this,
64                                              this->contextID()));
65 
66     return true;
67 }
68 
setupDrawingManager(bool sortOpsTasks,bool reduceOpsTaskSplitting)69 void GrRecordingContext::setupDrawingManager(bool sortOpsTasks, bool reduceOpsTaskSplitting) {
70     GrPathRendererChain::Options prcOptions;
71     prcOptions.fAllowPathMaskCaching = this->options().fAllowPathMaskCaching;
72 #if GR_TEST_UTILS
73     prcOptions.fGpuPathRenderers = this->options().fGpuPathRenderers;
74 #endif
75     // FIXME: Once this is removed from Chrome and Android, rename to fEnable"".
76     if (!this->options().fDisableCoverageCountingPaths) {
77         prcOptions.fGpuPathRenderers |= GpuPathRenderers::kCoverageCounting;
78     }
79     if (this->options().fDisableDistanceFieldPaths) {
80         prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
81     }
82 
83     if (!this->proxyProvider()->renderingDirectly()) {
84         // DDL TODO: remove this crippling of the path renderer chain
85         // Disable the small path renderer bc of the proxies in the atlas. They need to be
86         // unified when the opsTasks are added back to the destination drawing manager.
87         prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
88     }
89 
90     GrTextContext::Options textContextOptions;
91     textContextOptions.fMaxDistanceFieldFontSize = this->options().fGlyphsAsPathsFontSize;
92     textContextOptions.fMinDistanceFieldFontSize = this->options().fMinDistanceFieldFontSize;
93     textContextOptions.fDistanceFieldVerticesAlwaysHaveW = false;
94 #if SK_SUPPORT_ATLAS_TEXT
95     if (GrContextOptions::Enable::kYes == this->options().fDistanceFieldGlyphVerticesAlwaysHaveW) {
96         textContextOptions.fDistanceFieldVerticesAlwaysHaveW = true;
97     }
98 #endif
99 
100     fDrawingManager.reset(new GrDrawingManager(this,
101                                                prcOptions,
102                                                textContextOptions,
103                                                sortOpsTasks,
104                                                reduceOpsTaskSplitting));
105 }
106 
abandonContext()107 void GrRecordingContext::abandonContext() {
108     INHERITED::abandonContext();
109 
110     fStrikeCache->freeAll();
111     fTextBlobCache->freeAll();
112 }
113 
drawingManager()114 GrDrawingManager* GrRecordingContext::drawingManager() {
115     return fDrawingManager.get();
116 }
117 
refOpMemoryPool()118 sk_sp<GrOpMemoryPool> GrRecordingContext::refOpMemoryPool() {
119     if (!fOpMemoryPool) {
120         // DDL TODO: should the size of the memory pool be decreased in DDL mode? CPU-side memory
121         // consumed in DDL mode vs. normal mode for a single skp might be a good metric of wasted
122         // memory.
123         fOpMemoryPool = sk_sp<GrOpMemoryPool>(new GrOpMemoryPool(16384, 16384));
124     }
125 
126     SkASSERT(fOpMemoryPool);
127     return fOpMemoryPool;
128 }
129 
opMemoryPool()130 GrOpMemoryPool* GrRecordingContext::opMemoryPool() {
131     return this->refOpMemoryPool().get();
132 }
133 
getTextBlobCache()134 GrTextBlobCache* GrRecordingContext::getTextBlobCache() {
135     return fTextBlobCache.get();
136 }
137 
getTextBlobCache() const138 const GrTextBlobCache* GrRecordingContext::getTextBlobCache() const {
139     return fTextBlobCache.get();
140 }
141 
addOnFlushCallbackObject(GrOnFlushCallbackObject * onFlushCBObject)142 void GrRecordingContext::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
143     this->drawingManager()->addOnFlushCallbackObject(onFlushCBObject);
144 }
145 
makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)146 std::unique_ptr<GrSurfaceContext> GrRecordingContext::makeWrappedSurfaceContext(
147         sk_sp<GrSurfaceProxy> proxy,
148         GrColorType colorType,
149         SkAlphaType alphaType,
150         sk_sp<SkColorSpace> colorSpace,
151         const SkSurfaceProps* props) {
152     ASSERT_SINGLE_OWNER_PRIV
153 
154     SkASSERT(proxy);
155 
156     if (proxy->asRenderTargetProxy()) {
157         SkASSERT(kPremul_SkAlphaType == alphaType || kOpaque_SkAlphaType == alphaType);
158         return this->drawingManager()->makeRenderTargetContext(std::move(proxy), colorType,
159                                                                std::move(colorSpace), props);
160     } else {
161         SkASSERT(proxy->asTextureProxy());
162         SkASSERT(!props);
163         return this->drawingManager()->makeTextureContext(std::move(proxy), colorType, alphaType,
164                                                           std::move(colorSpace));
165     }
166 }
167 
makeDeferredTextureContext(SkBackingFit fit,int width,int height,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,GrMipMapped mipMapped,GrSurfaceOrigin origin,SkBudgeted budgeted,GrProtected isProtected)168 std::unique_ptr<GrTextureContext> GrRecordingContext::makeDeferredTextureContext(
169         SkBackingFit fit,
170         int width,
171         int height,
172         GrColorType colorType,
173         SkAlphaType alphaType,
174         sk_sp<SkColorSpace> colorSpace,
175         GrMipMapped mipMapped,
176         GrSurfaceOrigin origin,
177         SkBudgeted budgeted,
178         GrProtected isProtected) {
179     auto format = this->caps()->getDefaultBackendFormat(colorType, GrRenderable::kNo);
180     if (!format.isValid()) {
181         return nullptr;
182     }
183     auto config = this->caps()->getConfigFromBackendFormat(format, colorType);
184     if (config == kUnknown_GrPixelConfig) {
185         return nullptr;
186     }
187 
188     GrSurfaceDesc desc;
189     desc.fWidth = width;
190     desc.fHeight = height;
191     desc.fConfig = config;
192 
193     sk_sp<GrTextureProxy> texture = this->proxyProvider()->createProxy(
194             format, desc, GrRenderable::kNo, 1, origin, mipMapped, fit, budgeted, isProtected);
195     if (!texture) {
196         return nullptr;
197     }
198 
199     auto drawingManager = this->drawingManager();
200 
201     return drawingManager->makeTextureContext(std::move(texture), colorType, alphaType,
202                                               std::move(colorSpace));
203 }
204 
makeDeferredRenderTargetContext(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted,GrProtected isProtected)205 std::unique_ptr<GrRenderTargetContext> GrRecordingContext::makeDeferredRenderTargetContext(
206         SkBackingFit fit,
207         int width,
208         int height,
209         GrColorType colorType,
210         sk_sp<SkColorSpace> colorSpace,
211         int sampleCnt,
212         GrMipMapped mipMapped,
213         GrSurfaceOrigin origin,
214         const SkSurfaceProps* surfaceProps,
215         SkBudgeted budgeted,
216         GrProtected isProtected) {
217     SkASSERT(sampleCnt > 0);
218     if (this->abandoned()) {
219         return nullptr;
220     }
221 
222     auto format = this->caps()->getDefaultBackendFormat(colorType, GrRenderable::kYes);
223     if (!format.isValid()) {
224         return nullptr;
225     }
226     auto config = this->caps()->getConfigFromBackendFormat(format, colorType);
227     if (config == kUnknown_GrPixelConfig) {
228         return nullptr;
229     }
230 
231     GrSurfaceDesc desc;
232     desc.fWidth = width;
233     desc.fHeight = height;
234     desc.fConfig = config;
235 
236     sk_sp<GrTextureProxy> rtp =
237             this->proxyProvider()->createProxy(format, desc, GrRenderable::kYes, sampleCnt, origin,
238                                                mipMapped, fit, budgeted, isProtected);
239     if (!rtp) {
240         return nullptr;
241     }
242 
243     auto drawingManager = this->drawingManager();
244 
245     auto renderTargetContext = drawingManager->makeRenderTargetContext(
246             std::move(rtp), colorType, std::move(colorSpace), surfaceProps);
247     if (!renderTargetContext) {
248         return nullptr;
249     }
250 
251     renderTargetContext->discard();
252 
253     return renderTargetContext;
254 }
255 
color_type_fallback(GrColorType ct)256 static inline GrColorType color_type_fallback(GrColorType ct) {
257     switch (ct) {
258         // kRGBA_8888 is our default fallback for many color types that may not have renderable
259         // backend formats.
260         case GrColorType::kAlpha_8:
261         case GrColorType::kBGR_565:
262         case GrColorType::kABGR_4444:
263         case GrColorType::kBGRA_8888:
264         case GrColorType::kRGBA_1010102:
265         case GrColorType::kRGBA_F16:
266         case GrColorType::kRGBA_F16_Clamped:
267             return GrColorType::kRGBA_8888;
268         case GrColorType::kAlpha_F16:
269             return GrColorType::kRGBA_F16;
270         case GrColorType::kGray_8:
271             return GrColorType::kRGB_888x;
272         default:
273             return GrColorType::kUnknown;
274     }
275 }
276 
277 std::unique_ptr<GrRenderTargetContext>
makeDeferredRenderTargetContextWithFallback(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted,GrProtected isProtected)278 GrRecordingContext::makeDeferredRenderTargetContextWithFallback(SkBackingFit fit,
279                                                                 int width,
280                                                                 int height,
281                                                                 GrColorType colorType,
282                                                                 sk_sp<SkColorSpace> colorSpace,
283                                                                 int sampleCnt,
284                                                                 GrMipMapped mipMapped,
285                                                                 GrSurfaceOrigin origin,
286                                                                 const SkSurfaceProps* surfaceProps,
287                                                                 SkBudgeted budgeted,
288                                                                 GrProtected isProtected) {
289     SkASSERT(sampleCnt > 0);
290     std::unique_ptr<GrRenderTargetContext> rtc;
291     do {
292         rtc = this->makeDeferredRenderTargetContext(fit, width, height, colorType, colorSpace,
293                                                     sampleCnt, mipMapped, origin, surfaceProps,
294                                                     budgeted, isProtected);
295         colorType = color_type_fallback(colorType);
296     } while (!rtc && colorType != GrColorType::kUnknown);
297     return rtc;
298 }
299 
300 ///////////////////////////////////////////////////////////////////////////////////////////////////
refCaps() const301 sk_sp<const GrCaps> GrRecordingContextPriv::refCaps() const {
302     return fContext->refCaps();
303 }
304 
fpFactoryCache()305 sk_sp<GrSkSLFPFactoryCache> GrRecordingContextPriv::fpFactoryCache() {
306     return fContext->fpFactoryCache();
307 }
308 
refOpMemoryPool()309 sk_sp<GrOpMemoryPool> GrRecordingContextPriv::refOpMemoryPool() {
310     return fContext->refOpMemoryPool();
311 }
312 
addOnFlushCallbackObject(GrOnFlushCallbackObject * onFlushCBObject)313 void GrRecordingContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
314     fContext->addOnFlushCallbackObject(onFlushCBObject);
315 }
316 
makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)317 std::unique_ptr<GrSurfaceContext> GrRecordingContextPriv::makeWrappedSurfaceContext(
318         sk_sp<GrSurfaceProxy> proxy,
319         GrColorType colorType,
320         SkAlphaType alphaType,
321         sk_sp<SkColorSpace> colorSpace,
322         const SkSurfaceProps* props) {
323     return fContext->makeWrappedSurfaceContext(std::move(proxy), colorType, alphaType,
324                                                std::move(colorSpace), props);
325 }
326 
makeDeferredTextureContext(SkBackingFit fit,int width,int height,GrColorType colorType,SkAlphaType alphaType,sk_sp<SkColorSpace> colorSpace,GrMipMapped mipMapped,GrSurfaceOrigin origin,SkBudgeted budgeted,GrProtected isProtected)327 std::unique_ptr<GrTextureContext> GrRecordingContextPriv::makeDeferredTextureContext(
328         SkBackingFit fit,
329         int width,
330         int height,
331         GrColorType colorType,
332         SkAlphaType alphaType,
333         sk_sp<SkColorSpace> colorSpace,
334         GrMipMapped mipMapped,
335         GrSurfaceOrigin origin,
336         SkBudgeted budgeted,
337         GrProtected isProtected) {
338     return fContext->makeDeferredTextureContext(fit, width, height, colorType, alphaType,
339                                                 std::move(colorSpace), mipMapped, origin, budgeted,
340                                                 isProtected);
341 }
342 
makeDeferredRenderTargetContext(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted,GrProtected isProtected)343 std::unique_ptr<GrRenderTargetContext> GrRecordingContextPriv::makeDeferredRenderTargetContext(
344         SkBackingFit fit,
345         int width,
346         int height,
347         GrColorType colorType,
348         sk_sp<SkColorSpace> colorSpace,
349         int sampleCnt,
350         GrMipMapped mipMapped,
351         GrSurfaceOrigin origin,
352         const SkSurfaceProps* surfaceProps,
353         SkBudgeted budgeted,
354         GrProtected isProtected) {
355     return fContext->makeDeferredRenderTargetContext(fit, width, height, colorType,
356                                                      std::move(colorSpace), sampleCnt, mipMapped,
357                                                      origin, surfaceProps, budgeted, isProtected);
358 }
359 
360 std::unique_ptr<GrRenderTargetContext>
makeDeferredRenderTargetContextWithFallback(SkBackingFit fit,int width,int height,GrColorType colorType,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted,GrProtected isProtected)361 GrRecordingContextPriv::makeDeferredRenderTargetContextWithFallback(
362         SkBackingFit fit,
363         int width,
364         int height,
365         GrColorType colorType,
366         sk_sp<SkColorSpace> colorSpace,
367         int sampleCnt,
368         GrMipMapped mipMapped,
369         GrSurfaceOrigin origin,
370         const SkSurfaceProps* surfaceProps,
371         SkBudgeted budgeted,
372         GrProtected isProtected) {
373     return fContext->makeDeferredRenderTargetContextWithFallback(fit,
374                                                                  width,
375                                                                  height,
376                                                                  colorType,
377                                                                  std::move(colorSpace),
378                                                                  sampleCnt,
379                                                                  mipMapped,
380                                                                  origin,
381                                                                  surfaceProps,
382                                                                  budgeted,
383                                                                  isProtected);
384 }
385 
backdoor()386 GrContext* GrRecordingContextPriv::backdoor() {
387     return (GrContext*) fContext;
388 }
389 
390