blob: 7adb94867658d4d6e2acf42ebbdbef537e10a80a [file] [log] [blame]
Robert Phillips4217ea72019-01-30 13:08:28 -05001/*
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 "GrRecordingContext.h"
9
Robert Phillipsa41c6852019-02-07 10:44:10 -050010#include "GrCaps.h"
Robert Phillips0d075de2019-03-04 11:08:13 -050011#include "GrContext.h"
Robert Phillipsb97da532019-02-12 15:24:12 -050012#include "GrDrawingManager.h"
Robert Phillipsd6841482019-02-08 10:29:20 -050013#include "GrMemoryPool.h"
Robert Phillipsb97da532019-02-12 15:24:12 -050014#include "GrProxyProvider.h"
Robert Phillipsa41c6852019-02-07 10:44:10 -050015#include "GrRecordingContextPriv.h"
Robert Phillipsb97da532019-02-12 15:24:12 -050016#include "GrRenderTargetContext.h"
Robert Phillipsa41c6852019-02-07 10:44:10 -050017#include "GrSkSLFPFactoryCache.h"
Robert Phillips292a6b22019-02-14 14:49:02 -050018#include "GrTextureContext.h"
Robert Phillips6f0e02f2019-02-13 11:02:28 -050019#include "SkGr.h"
Robert Phillips2184fb72019-02-21 16:11:41 -050020#include "text/GrTextBlobCache.h"
Robert Phillipsa41c6852019-02-07 10:44:10 -050021
Robert Phillips292a6b22019-02-14 14:49:02 -050022#define ASSERT_SINGLE_OWNER_PRIV \
23 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(this->singleOwner());)
24
Robert Phillipsc1541ae2019-02-04 12:05:37 -050025GrRecordingContext::GrRecordingContext(GrBackendApi backend,
26 const GrContextOptions& options,
Robert Phillipsa41c6852019-02-07 10:44:10 -050027 uint32_t contextID)
28 : INHERITED(backend, options, contextID) {
Robert Phillips4217ea72019-01-30 13:08:28 -050029}
30
31GrRecordingContext::~GrRecordingContext() { }
32
Robert Phillips2184fb72019-02-21 16:11:41 -050033/**
34 * TODO: move textblob draw calls below context (see comment below)
35 */
36static void textblobcache_overbudget_CB(void* data) {
37 SkASSERT(data);
38 GrRecordingContext* context = reinterpret_cast<GrRecordingContext*>(data);
39
40 GrContext* direct = context->priv().asDirectContext();
41 if (!direct) {
42 return;
43 }
44
45 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
46 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls
47 // to below the GrContext level, but this is not trivial because they call drawPath on
48 // SkGpuDevice.
49 direct->flush();
50}
51
Robert Phillips292a6b22019-02-14 14:49:02 -050052bool GrRecordingContext::init(sk_sp<const GrCaps> caps, sk_sp<GrSkSLFPFactoryCache> cache) {
53
54 if (!INHERITED::init(std::move(caps), std::move(cache))) {
55 return false;
56 }
57
Herb Derbya00da612019-03-04 17:10:01 -050058 fStrikeCache.reset(new GrStrikeCache(this->caps(),
Robert Phillips2184fb72019-02-21 16:11:41 -050059 this->options().fGlyphCacheTextureMaximumBytes));
60
61 fTextBlobCache.reset(new GrTextBlobCache(textblobcache_overbudget_CB, this,
62 this->contextID()));
63
Robert Phillips56181ba2019-03-08 12:00:45 -050064 return true;
65}
66
Robert Phillips60dd62b2019-03-12 16:28:59 +000067void GrRecordingContext::setupDrawingManager(bool explicitlyAllocate, bool sortOpLists) {
Robert Phillips69893702019-02-22 11:16:30 -050068 GrPathRendererChain::Options prcOptions;
69 prcOptions.fAllowPathMaskCaching = this->options().fAllowPathMaskCaching;
70#if GR_TEST_UTILS
71 prcOptions.fGpuPathRenderers = this->options().fGpuPathRenderers;
72#endif
Chris Daltonf7748182019-03-18 16:22:30 +000073 // FIXME: Once this is removed from Chrome and Android, rename to fEnable"".
74 if (!this->options().fDisableCoverageCountingPaths) {
75 prcOptions.fGpuPathRenderers |= GpuPathRenderers::kCoverageCounting;
Robert Phillips69893702019-02-22 11:16:30 -050076 }
77 if (this->options().fDisableDistanceFieldPaths) {
78 prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
79 }
80
81 if (!this->proxyProvider()->renderingDirectly()) {
82 // DDL TODO: remove this crippling of the path renderer chain
83 // Disable the small path renderer bc of the proxies in the atlas. They need to be
84 // unified when the opLists are added back to the destination drawing manager.
85 prcOptions.fGpuPathRenderers &= ~GpuPathRenderers::kSmall;
86 }
87
88 GrTextContext::Options textContextOptions;
89 textContextOptions.fMaxDistanceFieldFontSize = this->options().fGlyphsAsPathsFontSize;
90 textContextOptions.fMinDistanceFieldFontSize = this->options().fMinDistanceFieldFontSize;
91 textContextOptions.fDistanceFieldVerticesAlwaysHaveW = false;
92#if SK_SUPPORT_ATLAS_TEXT
93 if (GrContextOptions::Enable::kYes == this->options().fDistanceFieldGlyphVerticesAlwaysHaveW) {
94 textContextOptions.fDistanceFieldVerticesAlwaysHaveW = true;
95 }
96#endif
97
Robert Phillips60dd62b2019-03-12 16:28:59 +000098 // SHORT TERM TODO: until intermediate flushes at allocation time are added we need to obey the
99 // reduceOpListSplitting flag. Once that lands we should always reduce opList splitting in
100 // DDL contexts/drawing managers. We should still obey the options for non-DDL drawing managers
101 // until predictive intermediate flushes are added (i.e., we can't reorder forever).
Robert Phillips69893702019-02-22 11:16:30 -0500102 fDrawingManager.reset(new GrDrawingManager(this,
Robert Phillips60dd62b2019-03-12 16:28:59 +0000103 prcOptions,
104 textContextOptions,
105 explicitlyAllocate,
106 sortOpLists,
107 this->options().fReduceOpListSplitting));
Robert Phillips292a6b22019-02-14 14:49:02 -0500108}
109
Robert Phillipsa9162df2019-02-11 14:12:03 -0500110void GrRecordingContext::abandonContext() {
111 INHERITED::abandonContext();
Robert Phillips2184fb72019-02-21 16:11:41 -0500112
Herb Derbya00da612019-03-04 17:10:01 -0500113 fStrikeCache->freeAll();
Robert Phillips2184fb72019-02-21 16:11:41 -0500114 fTextBlobCache->freeAll();
Robert Phillipsa9162df2019-02-11 14:12:03 -0500115}
116
Robert Phillips69893702019-02-22 11:16:30 -0500117GrDrawingManager* GrRecordingContext::drawingManager() {
118 return fDrawingManager.get();
119}
120
Robert Phillipsd6841482019-02-08 10:29:20 -0500121sk_sp<GrOpMemoryPool> GrRecordingContext::refOpMemoryPool() {
122 if (!fOpMemoryPool) {
123 // DDL TODO: should the size of the memory pool be decreased in DDL mode? CPU-side memory
124 // consumed in DDL mode vs. normal mode for a single skp might be a good metric of wasted
125 // memory.
126 fOpMemoryPool = sk_sp<GrOpMemoryPool>(new GrOpMemoryPool(16384, 16384));
127 }
128
129 SkASSERT(fOpMemoryPool);
130 return fOpMemoryPool;
131}
132
133GrOpMemoryPool* GrRecordingContext::opMemoryPool() {
134 return this->refOpMemoryPool().get();
135}
136
Robert Phillips2184fb72019-02-21 16:11:41 -0500137GrTextBlobCache* GrRecordingContext::getTextBlobCache() {
138 return fTextBlobCache.get();
139}
140
141const GrTextBlobCache* GrRecordingContext::getTextBlobCache() const {
142 return fTextBlobCache.get();
143}
144
Robert Phillipsc5058a62019-02-15 12:52:59 -0500145void GrRecordingContext::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
146 this->drawingManager()->addOnFlushCallbackObject(onFlushCBObject);
147}
148
Robert Phillips292a6b22019-02-14 14:49:02 -0500149sk_sp<GrSurfaceContext> GrRecordingContext::makeWrappedSurfaceContext(
150 sk_sp<GrSurfaceProxy> proxy,
151 sk_sp<SkColorSpace> colorSpace,
152 const SkSurfaceProps* props) {
153 ASSERT_SINGLE_OWNER_PRIV
154
155 if (proxy->asRenderTargetProxy()) {
156 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
157 std::move(colorSpace), props);
158 } else {
159 SkASSERT(proxy->asTextureProxy());
160 SkASSERT(!props);
161 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
162 }
163}
164
165sk_sp<GrSurfaceContext> GrRecordingContext::makeDeferredSurfaceContext(
166 const GrBackendFormat& format,
167 const GrSurfaceDesc& dstDesc,
168 GrSurfaceOrigin origin,
169 GrMipMapped mipMapped,
170 SkBackingFit fit,
171 SkBudgeted isDstBudgeted,
172 sk_sp<SkColorSpace> colorSpace,
173 const SkSurfaceProps* props) {
174 sk_sp<GrTextureProxy> proxy;
175 if (GrMipMapped::kNo == mipMapped) {
176 proxy = this->proxyProvider()->createProxy(format, dstDesc, origin, fit, isDstBudgeted);
177 } else {
178 SkASSERT(SkBackingFit::kExact == fit);
179 proxy = this->proxyProvider()->createMipMapProxy(format, dstDesc, origin, isDstBudgeted);
180 }
181 if (!proxy) {
182 return nullptr;
183 }
184
185 sk_sp<GrSurfaceContext> sContext = this->makeWrappedSurfaceContext(std::move(proxy),
186 std::move(colorSpace),
187 props);
188 if (sContext && sContext->asRenderTargetContext()) {
189 sContext->asRenderTargetContext()->discard();
190 }
191
192 return sContext;
193}
194
Robert Phillipsb97da532019-02-12 15:24:12 -0500195sk_sp<GrRenderTargetContext> GrRecordingContext::makeDeferredRenderTargetContext(
196 const GrBackendFormat& format,
197 SkBackingFit fit,
198 int width, int height,
199 GrPixelConfig config,
200 sk_sp<SkColorSpace> colorSpace,
201 int sampleCnt,
202 GrMipMapped mipMapped,
203 GrSurfaceOrigin origin,
204 const SkSurfaceProps* surfaceProps,
205 SkBudgeted budgeted) {
206 SkASSERT(sampleCnt > 0);
207 if (this->abandoned()) {
208 return nullptr;
209 }
210
211 GrSurfaceDesc desc;
212 desc.fFlags = kRenderTarget_GrSurfaceFlag;
213 desc.fWidth = width;
214 desc.fHeight = height;
215 desc.fConfig = config;
216 desc.fSampleCnt = sampleCnt;
217
218 sk_sp<GrTextureProxy> rtp;
219 if (GrMipMapped::kNo == mipMapped) {
220 rtp = this->proxyProvider()->createProxy(format, desc, origin, fit, budgeted);
221 } else {
222 rtp = this->proxyProvider()->createMipMapProxy(format, desc, origin, budgeted);
223 }
224 if (!rtp) {
225 return nullptr;
226 }
227
Robert Phillipsb97da532019-02-12 15:24:12 -0500228 auto drawingManager = this->drawingManager();
229
230 sk_sp<GrRenderTargetContext> renderTargetContext =
231 drawingManager->makeRenderTargetContext(std::move(rtp), std::move(colorSpace),
232 surfaceProps);
233 if (!renderTargetContext) {
234 return nullptr;
235 }
236
237 renderTargetContext->discard();
238
239 return renderTargetContext;
240}
Robert Phillipsd6841482019-02-08 10:29:20 -0500241
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500242static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
243 switch (config) {
244 case kAlpha_8_GrPixelConfig:
245 case kAlpha_8_as_Alpha_GrPixelConfig:
246 case kAlpha_8_as_Red_GrPixelConfig:
247 case kRGB_565_GrPixelConfig:
248 case kRGBA_4444_GrPixelConfig:
249 case kBGRA_8888_GrPixelConfig:
250 case kRGBA_1010102_GrPixelConfig:
251 case kRGBA_half_GrPixelConfig:
Brian Osmand0626aa2019-03-11 15:28:06 -0400252 case kRGBA_half_Clamped_GrPixelConfig:
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500253 return kRGBA_8888_GrPixelConfig;
254 case kSBGRA_8888_GrPixelConfig:
255 return kSRGBA_8888_GrPixelConfig;
256 case kAlpha_half_GrPixelConfig:
257 case kAlpha_half_as_Red_GrPixelConfig:
258 return kRGBA_half_GrPixelConfig;
259 case kGray_8_GrPixelConfig:
260 case kGray_8_as_Lum_GrPixelConfig:
261 case kGray_8_as_Red_GrPixelConfig:
262 return kRGB_888_GrPixelConfig;
263 default:
264 return kUnknown_GrPixelConfig;
265 }
266}
267
268sk_sp<GrRenderTargetContext> GrRecordingContext::makeDeferredRenderTargetContextWithFallback(
269 const GrBackendFormat& format,
270 SkBackingFit fit,
271 int width, int height,
272 GrPixelConfig config,
273 sk_sp<SkColorSpace> colorSpace,
274 int sampleCnt,
275 GrMipMapped mipMapped,
276 GrSurfaceOrigin origin,
277 const SkSurfaceProps* surfaceProps,
278 SkBudgeted budgeted) {
279 GrBackendFormat localFormat = format;
280 SkASSERT(sampleCnt > 0);
281 if (0 == this->caps()->getRenderTargetSampleCount(sampleCnt, config)) {
282 config = GrPixelConfigFallback(config);
283 // TODO: First we should be checking the getRenderTargetSampleCount from the GrBackendFormat
284 // and not GrPixelConfig. Besides that, we should implement the fallback in the caps, but
285 // for now we just convert the fallback pixel config to an SkColorType and then get the
286 // GrBackendFormat from that.
287 SkColorType colorType;
288 if (!GrPixelConfigToColorType(config, &colorType)) {
289 return nullptr;
290 }
291 localFormat = this->caps()->getBackendFormatFromColorType(colorType);
292 }
293
294 return this->makeDeferredRenderTargetContext(localFormat, fit, width, height, config,
295 std::move(colorSpace), sampleCnt, mipMapped,
296 origin, surfaceProps, budgeted);
297}
298
Robert Phillipsa41c6852019-02-07 10:44:10 -0500299///////////////////////////////////////////////////////////////////////////////////////////////////
300sk_sp<const GrCaps> GrRecordingContextPriv::refCaps() const {
301 return fContext->refCaps();
302}
303
304sk_sp<GrSkSLFPFactoryCache> GrRecordingContextPriv::fpFactoryCache() {
305 return fContext->fpFactoryCache();
306}
Robert Phillipsd6841482019-02-08 10:29:20 -0500307
308sk_sp<GrOpMemoryPool> GrRecordingContextPriv::refOpMemoryPool() {
309 return fContext->refOpMemoryPool();
310}
Robert Phillipsb97da532019-02-12 15:24:12 -0500311
Robert Phillipsc5058a62019-02-15 12:52:59 -0500312void GrRecordingContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
313 fContext->addOnFlushCallbackObject(onFlushCBObject);
314}
315
Robert Phillips292a6b22019-02-14 14:49:02 -0500316sk_sp<GrSurfaceContext> GrRecordingContextPriv::makeWrappedSurfaceContext(
317 sk_sp<GrSurfaceProxy> proxy,
318 sk_sp<SkColorSpace> colorSpace,
319 const SkSurfaceProps* props) {
320 return fContext->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace), props);
321}
322
323sk_sp<GrSurfaceContext> GrRecordingContextPriv::makeDeferredSurfaceContext(
324 const GrBackendFormat& format,
325 const GrSurfaceDesc& dstDesc,
326 GrSurfaceOrigin origin,
327 GrMipMapped mipMapped,
328 SkBackingFit fit,
329 SkBudgeted isDstBudgeted,
330 sk_sp<SkColorSpace> colorSpace,
331 const SkSurfaceProps* props) {
332 return fContext->makeDeferredSurfaceContext(format, dstDesc, origin, mipMapped, fit,
333 isDstBudgeted, std::move(colorSpace), props);
334}
335
Robert Phillipsb97da532019-02-12 15:24:12 -0500336sk_sp<GrRenderTargetContext> GrRecordingContextPriv::makeDeferredRenderTargetContext(
337 const GrBackendFormat& format,
338 SkBackingFit fit,
339 int width, int height,
340 GrPixelConfig config,
341 sk_sp<SkColorSpace> colorSpace,
342 int sampleCnt,
343 GrMipMapped mipMapped,
344 GrSurfaceOrigin origin,
345 const SkSurfaceProps* surfaceProps,
346 SkBudgeted budgeted) {
347 return fContext->makeDeferredRenderTargetContext(format, fit, width, height, config,
348 std::move(colorSpace), sampleCnt, mipMapped,
349 origin, surfaceProps, budgeted);
350}
Robert Phillips6f0e02f2019-02-13 11:02:28 -0500351
352sk_sp<GrRenderTargetContext> GrRecordingContextPriv::makeDeferredRenderTargetContextWithFallback(
353 const GrBackendFormat& format,
354 SkBackingFit fit,
355 int width, int height,
356 GrPixelConfig config,
357 sk_sp<SkColorSpace> colorSpace,
358 int sampleCnt,
359 GrMipMapped mipMapped,
360 GrSurfaceOrigin origin,
361 const SkSurfaceProps* surfaceProps,
362 SkBudgeted budgeted) {
363 return fContext->makeDeferredRenderTargetContextWithFallback(format, fit, width, height, config,
364 std::move(colorSpace), sampleCnt,
365 mipMapped, origin, surfaceProps,
366 budgeted);
367}
Robert Phillips9338c602019-02-19 12:52:29 -0500368
369GrContext* GrRecordingContextPriv::backdoor() {
370 return (GrContext*) fContext;
371}