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 "GrContextPriv.h"
9
10 #include "GrClip.h"
11 #include "GrContextThreadSafeProxy.h"
12 #include "GrContextThreadSafeProxyPriv.h"
13 #include "GrDrawingManager.h"
14 #include "GrGpu.h"
15 #include "GrMemoryPool.h"
16 #include "GrRenderTargetContext.h"
17 #include "GrSkSLFPFactoryCache.h"
18 #include "GrSurfacePriv.h"
19 #include "GrTexture.h"
20 #include "GrTextureContext.h"
21 #include "SkAutoPixmapStorage.h"
22 #include "SkImage_Base.h"
23 #include "SkImage_Gpu.h"
24 #include "SkGr.h"
25 #include "text/GrTextBlobCache.h"
26
27 #define ASSERT_OWNED_PROXY_PRIV(P) \
28 SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext)
29 #define ASSERT_SINGLE_OWNER_PRIV \
30 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());)
31 #define RETURN_IF_ABANDONED_PRIV if (fContext->abandoned()) { return; }
32 #define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->abandoned()) { return false; }
33
refCaps() const34 sk_sp<const GrCaps> GrContextPriv::refCaps() const {
35 return fContext->refCaps();
36 }
37
fpFactoryCache()38 sk_sp<GrSkSLFPFactoryCache> GrContextPriv::fpFactoryCache() {
39 return fContext->fpFactoryCache();
40 }
41
refOpMemoryPool()42 sk_sp<GrOpMemoryPool> GrContextPriv::refOpMemoryPool() {
43 return fContext->refOpMemoryPool();
44 }
45
addOnFlushCallbackObject(GrOnFlushCallbackObject * onFlushCBObject)46 void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
47 fContext->addOnFlushCallbackObject(onFlushCBObject);
48 }
49
makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)50 sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(
51 sk_sp<GrSurfaceProxy> proxy,
52 sk_sp<SkColorSpace> colorSpace,
53 const SkSurfaceProps* props) {
54 return fContext->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace), props);
55 }
56
makeDeferredSurfaceContext(const GrBackendFormat & format,const GrSurfaceDesc & dstDesc,GrSurfaceOrigin origin,GrMipMapped mipMapped,SkBackingFit fit,SkBudgeted isDstBudgeted,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)57 sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(
58 const GrBackendFormat& format,
59 const GrSurfaceDesc& dstDesc,
60 GrSurfaceOrigin origin,
61 GrMipMapped mipMapped,
62 SkBackingFit fit,
63 SkBudgeted isDstBudgeted,
64 sk_sp<SkColorSpace> colorSpace,
65 const SkSurfaceProps* props) {
66 return fContext->makeDeferredSurfaceContext(format, dstDesc, origin, mipMapped, fit,
67 isDstBudgeted, std::move(colorSpace), props);
68 }
69
makeDeferredRenderTargetContext(const GrBackendFormat & format,SkBackingFit fit,int width,int height,GrPixelConfig config,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted)70 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContext(
71 const GrBackendFormat& format,
72 SkBackingFit fit,
73 int width, int height,
74 GrPixelConfig config,
75 sk_sp<SkColorSpace> colorSpace,
76 int sampleCnt,
77 GrMipMapped mipMapped,
78 GrSurfaceOrigin origin,
79 const SkSurfaceProps* surfaceProps,
80 SkBudgeted budgeted) {
81 return fContext->makeDeferredRenderTargetContext(format, fit, width, height, config,
82 std::move(colorSpace), sampleCnt, mipMapped,
83 origin, surfaceProps, budgeted);
84 }
85
makeDeferredRenderTargetContextWithFallback(const GrBackendFormat & format,SkBackingFit fit,int width,int height,GrPixelConfig config,sk_sp<SkColorSpace> colorSpace,int sampleCnt,GrMipMapped mipMapped,GrSurfaceOrigin origin,const SkSurfaceProps * surfaceProps,SkBudgeted budgeted)86 sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContextWithFallback(
87 const GrBackendFormat& format,
88 SkBackingFit fit,
89 int width, int height,
90 GrPixelConfig config,
91 sk_sp<SkColorSpace> colorSpace,
92 int sampleCnt,
93 GrMipMapped mipMapped,
94 GrSurfaceOrigin origin,
95 const SkSurfaceProps* surfaceProps,
96 SkBudgeted budgeted) {
97 return fContext->makeDeferredRenderTargetContextWithFallback(format, fit, width, height, config,
98 std::move(colorSpace), sampleCnt,
99 mipMapped, origin, surfaceProps,
100 budgeted);
101 }
102
makeBackendTextureContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,sk_sp<SkColorSpace> colorSpace)103 sk_sp<GrTextureContext> GrContextPriv::makeBackendTextureContext(const GrBackendTexture& tex,
104 GrSurfaceOrigin origin,
105 sk_sp<SkColorSpace> colorSpace) {
106 ASSERT_SINGLE_OWNER_PRIV
107
108 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendTexture(
109 tex, origin, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, kRW_GrIOType);
110 if (!proxy) {
111 return nullptr;
112 }
113
114 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
115 }
116
makeBackendTextureRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props,ReleaseProc releaseProc,ReleaseContext releaseCtx)117 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
118 const GrBackendTexture& tex,
119 GrSurfaceOrigin origin,
120 int sampleCnt,
121 sk_sp<SkColorSpace> colorSpace,
122 const SkSurfaceProps* props,
123 ReleaseProc releaseProc,
124 ReleaseContext releaseCtx) {
125 ASSERT_SINGLE_OWNER_PRIV
126 SkASSERT(sampleCnt > 0);
127
128 sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture(
129 tex, origin, sampleCnt, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, releaseProc,
130 releaseCtx));
131 if (!proxy) {
132 return nullptr;
133 }
134
135 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
136 std::move(colorSpace), props);
137 }
138
makeBackendRenderTargetRenderTargetContext(const GrBackendRenderTarget & backendRT,GrSurfaceOrigin origin,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * surfaceProps,ReleaseProc releaseProc,ReleaseContext releaseCtx)139 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
140 const GrBackendRenderTarget& backendRT,
141 GrSurfaceOrigin origin,
142 sk_sp<SkColorSpace> colorSpace,
143 const SkSurfaceProps* surfaceProps,
144 ReleaseProc releaseProc,
145 ReleaseContext releaseCtx) {
146 ASSERT_SINGLE_OWNER_PRIV
147
148 sk_sp<GrSurfaceProxy> proxy = this->proxyProvider()->wrapBackendRenderTarget(
149 backendRT, origin, releaseProc, releaseCtx);
150 if (!proxy) {
151 return nullptr;
152 }
153
154 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
155 std::move(colorSpace),
156 surfaceProps);
157 }
158
makeBackendTextureAsRenderTargetRenderTargetContext(const GrBackendTexture & tex,GrSurfaceOrigin origin,int sampleCnt,sk_sp<SkColorSpace> colorSpace,const SkSurfaceProps * props)159 sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
160 const GrBackendTexture& tex,
161 GrSurfaceOrigin origin,
162 int sampleCnt,
163 sk_sp<SkColorSpace> colorSpace,
164 const SkSurfaceProps* props) {
165 ASSERT_SINGLE_OWNER_PRIV
166 SkASSERT(sampleCnt > 0);
167 sk_sp<GrSurfaceProxy> proxy(
168 this->proxyProvider()->wrapBackendTextureAsRenderTarget(tex, origin, sampleCnt));
169 if (!proxy) {
170 return nullptr;
171 }
172
173 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
174 std::move(colorSpace),
175 props);
176 }
177
makeVulkanSecondaryCBRenderTargetContext(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo,const SkSurfaceProps * props)178 sk_sp<GrRenderTargetContext> GrContextPriv::makeVulkanSecondaryCBRenderTargetContext(
179 const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo, const SkSurfaceProps* props) {
180 ASSERT_SINGLE_OWNER_PRIV
181 sk_sp<GrSurfaceProxy> proxy(
182 this->proxyProvider()->wrapVulkanSecondaryCBAsRenderTarget(imageInfo, vkInfo));
183 if (!proxy) {
184 return nullptr;
185 }
186
187 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
188 imageInfo.refColorSpace(),
189 props);
190 }
191
flush(GrSurfaceProxy * proxy)192 void GrContextPriv::flush(GrSurfaceProxy* proxy) {
193 ASSERT_SINGLE_OWNER_PRIV
194 RETURN_IF_ABANDONED_PRIV
195 ASSERT_OWNED_PROXY_PRIV(proxy);
196
197 fContext->drawingManager()->flush(proxy, SkSurface::BackendSurfaceAccess::kNoAccess,
198 kNone_GrFlushFlags, 0, nullptr, nullptr, nullptr);
199 }
200
flushSurfaceWrites(GrSurfaceProxy * proxy)201 void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) {
202 ASSERT_SINGLE_OWNER_PRIV
203 RETURN_IF_ABANDONED_PRIV
204 SkASSERT(proxy);
205 ASSERT_OWNED_PROXY_PRIV(proxy);
206 if (proxy->priv().hasPendingWrite()) {
207 this->flush(proxy);
208 }
209 }
210
flushSurfaceIO(GrSurfaceProxy * proxy)211 void GrContextPriv::flushSurfaceIO(GrSurfaceProxy* proxy) {
212 ASSERT_SINGLE_OWNER_PRIV
213 RETURN_IF_ABANDONED_PRIV
214 SkASSERT(proxy);
215 ASSERT_OWNED_PROXY_PRIV(proxy);
216 if (proxy->priv().hasPendingIO()) {
217 this->flush(proxy);
218 }
219 }
220
prepareSurfaceForExternalIO(GrSurfaceProxy * proxy)221 void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
222 ASSERT_SINGLE_OWNER_PRIV
223 RETURN_IF_ABANDONED_PRIV
224 SkASSERT(proxy);
225 ASSERT_OWNED_PROXY_PRIV(proxy);
226 fContext->drawingManager()->prepareSurfaceForExternalIO(proxy,
227 SkSurface::BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags, 0, nullptr,
228 nullptr, nullptr);
229 }
230
valid_premul_color_type(GrColorType ct)231 static bool valid_premul_color_type(GrColorType ct) {
232 switch (ct) {
233 case GrColorType::kUnknown: return false;
234 case GrColorType::kAlpha_8: return false;
235 case GrColorType::kRGB_565: return false;
236 case GrColorType::kABGR_4444: return true;
237 case GrColorType::kRGBA_8888: return true;
238 case GrColorType::kRGB_888x: return false;
239 case GrColorType::kRG_88: return false;
240 case GrColorType::kBGRA_8888: return true;
241 case GrColorType::kRGBA_1010102: return true;
242 case GrColorType::kGray_8: return false;
243 case GrColorType::kAlpha_F16: return false;
244 case GrColorType::kRGBA_F16: return true;
245 case GrColorType::kRGBA_F16_Clamped: return true;
246 case GrColorType::kRG_F32: return false;
247 case GrColorType::kRGBA_F32: return true;
248 case GrColorType::kRGB_ETC1: return false;
249 }
250 SK_ABORT("Invalid GrColorType");
251 return false;
252 }
253
254 // TODO: This will be removed when GrSurfaceContexts are aware of their color types.
255 // (skbug.com/6718)
valid_premul_config(GrPixelConfig config)256 static bool valid_premul_config(GrPixelConfig config) {
257 switch (config) {
258 case kUnknown_GrPixelConfig: return false;
259 case kAlpha_8_GrPixelConfig: return false;
260 case kGray_8_GrPixelConfig: return false;
261 case kRGB_565_GrPixelConfig: return false;
262 case kRGBA_4444_GrPixelConfig: return true;
263 case kRGBA_8888_GrPixelConfig: return true;
264 case kRGB_888_GrPixelConfig: return false;
265 case kRGB_888X_GrPixelConfig: return false;
266 case kRG_88_GrPixelConfig: return false;
267 case kBGRA_8888_GrPixelConfig: return true;
268 case kSRGBA_8888_GrPixelConfig: return true;
269 case kSBGRA_8888_GrPixelConfig: return true;
270 case kRGBA_1010102_GrPixelConfig: return true;
271 case kRGBA_float_GrPixelConfig: return true;
272 case kRG_float_GrPixelConfig: return false;
273 case kAlpha_half_GrPixelConfig: return false;
274 case kRGBA_half_GrPixelConfig: return true;
275 case kRGBA_half_Clamped_GrPixelConfig: return true;
276 case kRGB_ETC1_GrPixelConfig: return false;
277 case kAlpha_8_as_Alpha_GrPixelConfig: return false;
278 case kAlpha_8_as_Red_GrPixelConfig: return false;
279 case kAlpha_half_as_Red_GrPixelConfig: return false;
280 case kGray_8_as_Lum_GrPixelConfig: return false;
281 case kGray_8_as_Red_GrPixelConfig: return false;
282 }
283 SK_ABORT("Invalid GrPixelConfig");
284 return false;
285 }
286
valid_pixel_conversion(GrColorType cpuColorType,GrPixelConfig gpuConfig,bool premulConversion)287 static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuConfig,
288 bool premulConversion) {
289 // We only allow premul <-> unpremul conversions for some formats
290 if (premulConversion &&
291 (!valid_premul_color_type(cpuColorType) || !valid_premul_config(gpuConfig))) {
292 return false;
293 }
294 return true;
295 }
296
readSurfacePixels(GrSurfaceContext * src,int left,int top,int width,int height,GrColorType dstColorType,SkColorSpace * dstColorSpace,void * buffer,size_t rowBytes,uint32_t pixelOpsFlags)297 bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width,
298 int height, GrColorType dstColorType,
299 SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
300 uint32_t pixelOpsFlags) {
301 ASSERT_SINGLE_OWNER_PRIV
302 RETURN_FALSE_IF_ABANDONED_PRIV
303 SkASSERT(src);
304 SkASSERT(buffer);
305 ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
306 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext);
307
308 SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag));
309 if (pixelOpsFlags & kDontFlush_PixelOpsFlag) {
310 return false;
311 }
312
313 // MDB TODO: delay this instantiation until later in the method
314 if (!src->asSurfaceProxy()->instantiate(this->resourceProvider())) {
315 return false;
316 }
317
318 GrSurfaceProxy* srcProxy = src->asSurfaceProxy();
319 GrSurface* srcSurface = srcProxy->peekSurface();
320
321 if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
322 GrColorTypeBytesPerPixel(dstColorType), &left, &top,
323 &width, &height, &buffer, &rowBytes)) {
324 return false;
325 }
326
327 // TODO: Make GrSurfaceContext know its alpha type and pass dst buffer's alpha type.
328 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
329
330 if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) {
331 return false;
332 }
333
334 // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't
335 // care so much about getImageData performance. However, in order to ensure putImageData/
336 // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary
337 // unpremul step to writeSurfacePixels's premul step (which is determined empirically in
338 // fContext->vaildaPMUPMConversionExists()).
339 bool canvas2DFastPath =
340 unpremul &&
341 !src->colorSpaceInfo().colorSpace() &&
342 (GrColorType::kRGBA_8888 == dstColorType || GrColorType::kBGRA_8888 == dstColorType) &&
343 SkToBool(srcProxy->asTextureProxy()) &&
344 (srcProxy->config() == kRGBA_8888_GrPixelConfig ||
345 srcProxy->config() == kBGRA_8888_GrPixelConfig) &&
346 fContext->priv().caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig) &&
347 fContext->validPMUPMConversionExists();
348
349 if (!fContext->priv().caps()->surfaceSupportsReadPixels(srcSurface) ||
350 canvas2DFastPath) {
351 GrSurfaceDesc desc;
352 desc.fFlags = canvas2DFastPath ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
353 desc.fConfig = canvas2DFastPath ? kRGBA_8888_GrPixelConfig : srcProxy->config();
354 desc.fWidth = width;
355 desc.fHeight = height;
356 desc.fSampleCnt = 1;
357
358 GrBackendFormat format;
359 if (canvas2DFastPath) {
360 desc.fFlags = kRenderTarget_GrSurfaceFlag;
361 desc.fConfig = kRGBA_8888_GrPixelConfig;
362 format = this->caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
363 } else {
364 desc.fFlags = kNone_GrSurfaceFlags;
365 desc.fConfig = srcProxy->config();
366 format = srcProxy->backendFormat().makeTexture2D();
367 if (!format.isValid()) {
368 return false;
369 }
370 }
371
372 auto tempProxy = this->proxyProvider()->createProxy(
373 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
374 if (!tempProxy) {
375 return false;
376 }
377 sk_sp<GrSurfaceContext> tempCtx;
378 if (canvas2DFastPath) {
379 tempCtx = this->drawingManager()->makeRenderTargetContext(std::move(tempProxy), nullptr,
380 nullptr);
381 SkASSERT(tempCtx->asRenderTargetContext());
382 tempCtx->asRenderTargetContext()->discard();
383 } else {
384 tempCtx = this->drawingManager()->makeTextureContext(
385 std::move(tempProxy), src->colorSpaceInfo().refColorSpace());
386 }
387 if (!tempCtx) {
388 return false;
389 }
390 if (canvas2DFastPath) {
391 GrPaint paint;
392 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
393 auto fp = fContext->createPMToUPMEffect(
394 GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()),
395 SkMatrix::I()));
396 if (dstColorType == GrColorType::kBGRA_8888) {
397 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
398 dstColorType = GrColorType::kRGBA_8888;
399 }
400 if (!fp) {
401 return false;
402 }
403 paint.addColorFragmentProcessor(std::move(fp));
404 tempCtx->asRenderTargetContext()->fillRectToRect(
405 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
406 SkRect::MakeWH(width, height), SkRect::MakeXYWH(left, top, width, height));
407 } else if (!tempCtx->copy(srcProxy, SkIRect::MakeXYWH(left, top, width, height), {0, 0})) {
408 return false;
409 }
410 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
411 return this->readSurfacePixels(tempCtx.get(), 0, 0, width, height, dstColorType,
412 dstColorSpace, buffer, rowBytes, flags);
413 }
414
415 bool convert = unpremul;
416
417 bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
418 if (flip) {
419 top = srcSurface->height() - top - height;
420 }
421
422 GrColorType allowedColorType = fContext->priv().caps()->supportedReadPixelsColorType(
423 srcProxy->config(), dstColorType);
424 convert = convert || (dstColorType != allowedColorType);
425
426 if (!src->colorSpaceInfo().colorSpace()) {
427 // "Legacy" mode - no color space conversions.
428 dstColorSpace = nullptr;
429 }
430 convert = convert || !SkColorSpace::Equals(dstColorSpace, src->colorSpaceInfo().colorSpace());
431
432 SkAutoPixmapStorage tempPixmap;
433 SkPixmap finalPixmap;
434 if (convert) {
435 SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
436 SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
437 bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType);
438 bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType);
439 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
440 return false;
441 }
442 auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
443 auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
444 src->colorSpaceInfo().refColorSpace());
445 SkASSERT(!unpremul || !dstAlwaysOpaque);
446 auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque)
447 ? kOpaque_SkAlphaType
448 : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
449 auto finalII =
450 SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace));
451 if (!SkImageInfoValidConversion(finalII, tempII)) {
452 return false;
453 }
454 if (!tempPixmap.tryAlloc(tempII)) {
455 return false;
456 }
457 finalPixmap.reset(finalII, buffer, rowBytes);
458 buffer = tempPixmap.writable_addr();
459 rowBytes = tempPixmap.rowBytes();
460 // Chrome msan bots require this.
461 sk_bzero(buffer, tempPixmap.computeByteSize());
462 }
463
464 if (srcSurface->surfacePriv().hasPendingWrite()) {
465 this->flush(nullptr); // MDB TODO: tighten this
466 }
467
468 if (!fContext->fGpu->readPixels(srcSurface, left, top, width, height, allowedColorType, buffer,
469 rowBytes)) {
470 return false;
471 }
472
473 if (flip) {
474 size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
475 std::unique_ptr<char[]> row(new char[trimRowBytes]);
476 char* upper = reinterpret_cast<char*>(buffer);
477 char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes;
478 for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) {
479 memcpy(row.get(), upper, trimRowBytes);
480 memcpy(upper, lower, trimRowBytes);
481 memcpy(lower, row.get(), trimRowBytes);
482 }
483 }
484 if (convert) {
485 if (!tempPixmap.readPixels(finalPixmap)) {
486 return false;
487 }
488 }
489 return true;
490 }
491
writeSurfacePixels(GrSurfaceContext * dst,int left,int top,int width,int height,GrColorType srcColorType,SkColorSpace * srcColorSpace,const void * buffer,size_t rowBytes,uint32_t pixelOpsFlags)492 bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width,
493 int height, GrColorType srcColorType,
494 SkColorSpace* srcColorSpace, const void* buffer,
495 size_t rowBytes, uint32_t pixelOpsFlags) {
496 ASSERT_SINGLE_OWNER_PRIV
497 RETURN_FALSE_IF_ABANDONED_PRIV
498 SkASSERT(dst);
499 SkASSERT(buffer);
500 ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy());
501 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext);
502
503 if (GrColorType::kUnknown == srcColorType) {
504 return false;
505 }
506
507 if (!dst->asSurfaceProxy()->instantiate(this->resourceProvider())) {
508 return false;
509 }
510
511 GrSurfaceProxy* dstProxy = dst->asSurfaceProxy();
512 GrSurface* dstSurface = dstProxy->peekSurface();
513
514 if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(),
515 GrColorTypeBytesPerPixel(srcColorType), &left, &top,
516 &width, &height, &buffer, &rowBytes)) {
517 return false;
518 }
519
520 // TODO: Make GrSurfaceContext know its alpha type and pass src buffer's alpha type.
521 bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
522
523 // For canvas2D putImageData performance we have a special code path for unpremul RGBA_8888 srcs
524 // that are premultiplied on the GPU. This is kept as narrow as possible for now.
525 bool canvas2DFastPath =
526 !fContext->priv().caps()->avoidWritePixelsFastPath() &&
527 premul &&
528 !dst->colorSpaceInfo().colorSpace() &&
529 (srcColorType == GrColorType::kRGBA_8888 || srcColorType == GrColorType::kBGRA_8888) &&
530 SkToBool(dst->asRenderTargetContext()) &&
531 (dstProxy->config() == kRGBA_8888_GrPixelConfig ||
532 dstProxy->config() == kBGRA_8888_GrPixelConfig) &&
533 !(pixelOpsFlags & kDontFlush_PixelOpsFlag) &&
534 fContext->priv().caps()->isConfigTexturable(kRGBA_8888_GrPixelConfig) &&
535 fContext->validPMUPMConversionExists();
536
537 const GrCaps* caps = this->caps();
538 if (!caps->surfaceSupportsWritePixels(dstSurface) ||
539 canvas2DFastPath) {
540 // We don't expect callers that are skipping flushes to require an intermediate draw.
541 SkASSERT(!(pixelOpsFlags & kDontFlush_PixelOpsFlag));
542 if (pixelOpsFlags & kDontFlush_PixelOpsFlag) {
543 return false;
544 }
545
546 GrSurfaceDesc desc;
547 desc.fWidth = width;
548 desc.fHeight = height;
549 desc.fSampleCnt = 1;
550
551 GrBackendFormat format;
552 if (canvas2DFastPath) {
553 desc.fConfig = kRGBA_8888_GrPixelConfig;
554 format =
555 fContext->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
556 } else {
557 desc.fConfig = dstProxy->config();
558 format = dstProxy->backendFormat().makeTexture2D();
559 if (!format.isValid()) {
560 return false;
561 }
562 }
563
564 auto tempProxy = this->proxyProvider()->createProxy(
565 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
566 if (!tempProxy) {
567 return false;
568 }
569 auto tempCtx = this->drawingManager()->makeTextureContext(
570 tempProxy, dst->colorSpaceInfo().refColorSpace());
571 if (!tempCtx) {
572 return false;
573 }
574 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
575 // In the fast path we always write the srcData to the temp context as though it were RGBA.
576 // When the data is really BGRA the write will cause the R and B channels to be swapped in
577 // the intermediate surface which gets corrected by a swizzle effect when drawing to the
578 // dst.
579 auto tmpColorType = canvas2DFastPath ? GrColorType::kRGBA_8888 : srcColorType;
580 if (!this->writeSurfacePixels(tempCtx.get(), 0, 0, width, height, tmpColorType,
581 srcColorSpace, buffer, rowBytes, flags)) {
582 return false;
583 }
584 if (canvas2DFastPath) {
585 GrPaint paint;
586 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
587 auto fp = fContext->createUPMToPMEffect(
588 GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I()));
589 if (srcColorType == GrColorType::kBGRA_8888) {
590 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
591 }
592 if (!fp) {
593 return false;
594 }
595 paint.addColorFragmentProcessor(std::move(fp));
596 dst->asRenderTargetContext()->fillRectToRect(
597 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
598 SkRect::MakeXYWH(left, top, width, height), SkRect::MakeWH(width, height));
599 return true;
600 } else {
601 return dst->copy(tempProxy.get(), SkIRect::MakeWH(width, height), {left, top});
602 }
603 }
604
605 bool convert = premul;
606
607 if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
608 return false;
609 }
610
611 GrColorType allowedColorType = fContext->priv().caps()->supportedWritePixelsColorType(
612 dstProxy->config(), srcColorType);
613 convert = convert || (srcColorType != allowedColorType);
614
615 if (!dst->colorSpaceInfo().colorSpace()) {
616 // "Legacy" mode - no color space conversions.
617 srcColorSpace = nullptr;
618 }
619 convert = convert || !SkColorSpace::Equals(srcColorSpace, dst->colorSpaceInfo().colorSpace());
620
621 std::unique_ptr<char[]> tempBuffer;
622 if (convert) {
623 auto srcSkColorType = GrColorTypeToSkColorType(srcColorType);
624 auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType);
625 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
626 return false;
627 }
628 auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType)
629 ? kOpaque_SkAlphaType
630 : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
631 SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType,
632 sk_ref_sp(srcColorSpace)),
633 buffer, rowBytes);
634 auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType,
635 dst->colorSpaceInfo().refColorSpace());
636 auto size = tempSrcII.computeMinByteSize();
637 if (!size) {
638 return false;
639 }
640 tempBuffer.reset(new char[size]);
641 SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes());
642 if (!src.readPixels(tempSrc)) {
643 return false;
644 }
645 srcColorType = allowedColorType;
646 buffer = tempSrc.addr();
647 rowBytes = tempSrc.rowBytes();
648 if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
649 std::unique_ptr<char[]> row(new char[rowBytes]);
650 for (int y = 0; y < height / 2; ++y) {
651 memcpy(row.get(), tempSrc.addr(0, y), rowBytes);
652 memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), rowBytes);
653 memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), rowBytes);
654 }
655 top = dstSurface->height() - top - height;
656 }
657 } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
658 size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
659 tempBuffer.reset(new char[trimRowBytes * height]);
660 char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1);
661 const char* src = reinterpret_cast<const char*>(buffer);
662 for (int i = 0; i < height; ++i, src += rowBytes, dst -= trimRowBytes) {
663 memcpy(dst, src, trimRowBytes);
664 }
665 buffer = tempBuffer.get();
666 rowBytes = trimRowBytes;
667 top = dstSurface->height() - top - height;
668 }
669
670 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && dstSurface->surfacePriv().hasPendingIO()) {
671 this->flush(nullptr); // MDB TODO: tighten this
672 }
673
674 return this->getGpu()->writePixels(dstSurface, left, top, width, height, srcColorType, buffer,
675 rowBytes);
676 }
677
moveOpListsToDDL(SkDeferredDisplayList * ddl)678 void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
679 fContext->drawingManager()->moveOpListsToDDL(ddl);
680 }
681
copyOpListsFromDDL(const SkDeferredDisplayList * ddl,GrRenderTargetProxy * newDest)682 void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
683 GrRenderTargetProxy* newDest) {
684 fContext->drawingManager()->copyOpListsFromDDL(ddl, newDest);
685 }
686
687 //////////////////////////////////////////////////////////////////////////////
688 #ifdef SK_ENABLE_DUMP_GPU
689 #include "SkJSONWriter.h"
dump() const690 SkString GrContextPriv::dump() const {
691 SkDynamicMemoryWStream stream;
692 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
693 writer.beginObject();
694
695 static const char* kBackendStr[] = {
696 "Metal",
697 "OpenGL",
698 "Vulkan",
699 "Mock",
700 };
701 GR_STATIC_ASSERT(0 == (unsigned)GrBackendApi::kMetal);
702 GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kOpenGL);
703 GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kVulkan);
704 GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kMock);
705 writer.appendString("backend", kBackendStr[(unsigned)fContext->backend()]);
706
707 writer.appendName("caps");
708 fContext->caps()->dumpJSON(&writer);
709
710 writer.appendName("gpu");
711 fContext->fGpu->dumpJSON(&writer);
712
713 // Flush JSON to the memory stream
714 writer.endObject();
715 writer.flush();
716
717 // Null terminate the JSON data in the memory stream
718 stream.write8(0);
719
720 // Allocate a string big enough to hold all the data, then copy out of the stream
721 SkString result(stream.bytesWritten());
722 stream.copyToAndReset(result.writable_str());
723 return result;
724 }
725 #endif
726
727 #if GR_TEST_UTILS
resetGpuStats() const728 void GrContextPriv::resetGpuStats() const {
729 #if GR_GPU_STATS
730 fContext->fGpu->stats()->reset();
731 #endif
732 }
733
dumpCacheStats(SkString * out) const734 void GrContextPriv::dumpCacheStats(SkString* out) const {
735 #if GR_CACHE_STATS
736 fContext->fResourceCache->dumpStats(out);
737 #endif
738 }
739
dumpCacheStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const740 void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
741 SkTArray<double>* values) const {
742 #if GR_CACHE_STATS
743 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values);
744 #endif
745 }
746
printCacheStats() const747 void GrContextPriv::printCacheStats() const {
748 SkString out;
749 this->dumpCacheStats(&out);
750 SkDebugf("%s", out.c_str());
751 }
752
dumpGpuStats(SkString * out) const753 void GrContextPriv::dumpGpuStats(SkString* out) const {
754 #if GR_GPU_STATS
755 return fContext->fGpu->stats()->dump(out);
756 #endif
757 }
758
dumpGpuStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const759 void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
760 SkTArray<double>* values) const {
761 #if GR_GPU_STATS
762 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values);
763 #endif
764 }
765
printGpuStats() const766 void GrContextPriv::printGpuStats() const {
767 SkString out;
768 this->dumpGpuStats(&out);
769 SkDebugf("%s", out.c_str());
770 }
771
testingOnly_setTextBlobCacheLimit(size_t bytes)772 void GrContextPriv::testingOnly_setTextBlobCacheLimit(size_t bytes) {
773 fContext->priv().getTextBlobCache()->setBudget(bytes);
774 }
775
testingOnly_getFontAtlasImage(GrMaskFormat format,unsigned int index)776 sk_sp<SkImage> GrContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index) {
777 auto atlasManager = this->getAtlasManager();
778 if (!atlasManager) {
779 return nullptr;
780 }
781
782 unsigned int numActiveProxies;
783 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies);
784 if (index >= numActiveProxies || !proxies || !proxies[index]) {
785 return nullptr;
786 }
787
788 SkASSERT(proxies[index]->priv().isExact());
789 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID,
790 kPremul_SkAlphaType, proxies[index], nullptr));
791 return image;
792 }
793
testingOnly_purgeAllUnlockedResources()794 void GrContextPriv::testingOnly_purgeAllUnlockedResources() {
795 fContext->fResourceCache->purgeAllUnlocked();
796 }
797
testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject * cb)798 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
799 fContext->flush();
800 fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
801 }
802 #endif
803
804