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