blob: f545e9076406343bfb346ef69f0650246efef7a8 [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 Phillipsa9162df2019-02-11 14:12:03 -050031#define RETURN_IF_ABANDONED_PRIV if (fContext->abandoned()) { return; }
32#define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->abandoned()) { return false; }
Robert Phillipsdbaf3172019-02-06 15:12:53 -050033
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
Robert Phillipsc5058a62019-02-15 12:52:59 -050046void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
47 fContext->addOnFlushCallbackObject(onFlushCBObject);
48}
49
Robert Phillips292a6b22019-02-14 14:49:02 -050050sk_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
57sk_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
Robert Phillipsb97da532019-02-12 15:24:12 -050070sk_sp<GrRenderTargetContext> GrContextPriv::makeDeferredRenderTargetContext(
Robert Phillips6f0e02f2019-02-13 11:02:28 -050071 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) {
Robert Phillipsb97da532019-02-12 15:24:12 -050081 return fContext->makeDeferredRenderTargetContext(format, fit, width, height, config,
82 std::move(colorSpace), sampleCnt, mipMapped,
83 origin, surfaceProps, budgeted);
84}
85
Robert Phillips6f0e02f2019-02-13 11:02:28 -050086sk_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
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500103sk_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
117sk_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
139sk_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
159sk_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
178sk_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
192void GrContextPriv::flush(GrSurfaceProxy* proxy) {
193 ASSERT_SINGLE_OWNER_PRIV
194 RETURN_IF_ABANDONED_PRIV
195 ASSERT_OWNED_PROXY_PRIV(proxy);
196
Greg Danielbae71212019-03-01 15:24:35 -0500197 fContext->drawingManager()->flush(proxy, SkSurface::BackendSurfaceAccess::kNoAccess,
Greg Danielb9990e42019-04-10 16:28:52 -0400198 kNone_GrFlushFlags, 0, nullptr);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500199}
200
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500201void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
202 ASSERT_SINGLE_OWNER_PRIV
203 RETURN_IF_ABANDONED_PRIV
204 SkASSERT(proxy);
205 ASSERT_OWNED_PROXY_PRIV(proxy);
Greg Danielbae71212019-03-01 15:24:35 -0500206 fContext->drawingManager()->prepareSurfaceForExternalIO(proxy,
Greg Danielb9990e42019-04-10 16:28:52 -0400207 SkSurface::BackendSurfaceAccess::kNoAccess, kNone_GrFlushFlags, 0, nullptr);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500208}
209
210static bool valid_premul_color_type(GrColorType ct) {
211 switch (ct) {
Brian Osmand0626aa2019-03-11 15:28:06 -0400212 case GrColorType::kUnknown: return false;
213 case GrColorType::kAlpha_8: return false;
214 case GrColorType::kRGB_565: return false;
215 case GrColorType::kABGR_4444: return true;
216 case GrColorType::kRGBA_8888: return true;
217 case GrColorType::kRGB_888x: return false;
218 case GrColorType::kRG_88: return false;
219 case GrColorType::kBGRA_8888: return true;
220 case GrColorType::kRGBA_1010102: return true;
221 case GrColorType::kGray_8: return false;
222 case GrColorType::kAlpha_F16: return false;
223 case GrColorType::kRGBA_F16: return true;
224 case GrColorType::kRGBA_F16_Clamped: return true;
225 case GrColorType::kRG_F32: return false;
226 case GrColorType::kRGBA_F32: return true;
227 case GrColorType::kRGB_ETC1: return false;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500228 }
229 SK_ABORT("Invalid GrColorType");
230 return false;
231}
232
233// TODO: This will be removed when GrSurfaceContexts are aware of their color types.
234// (skbug.com/6718)
235static bool valid_premul_config(GrPixelConfig config) {
236 switch (config) {
237 case kUnknown_GrPixelConfig: return false;
238 case kAlpha_8_GrPixelConfig: return false;
239 case kGray_8_GrPixelConfig: return false;
240 case kRGB_565_GrPixelConfig: return false;
241 case kRGBA_4444_GrPixelConfig: return true;
242 case kRGBA_8888_GrPixelConfig: return true;
243 case kRGB_888_GrPixelConfig: return false;
Greg Danielf259b8b2019-02-14 09:03:43 -0500244 case kRGB_888X_GrPixelConfig: return false;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500245 case kRG_88_GrPixelConfig: return false;
246 case kBGRA_8888_GrPixelConfig: return true;
247 case kSRGBA_8888_GrPixelConfig: return true;
248 case kSBGRA_8888_GrPixelConfig: return true;
249 case kRGBA_1010102_GrPixelConfig: return true;
250 case kRGBA_float_GrPixelConfig: return true;
251 case kRG_float_GrPixelConfig: return false;
252 case kAlpha_half_GrPixelConfig: return false;
253 case kRGBA_half_GrPixelConfig: return true;
Brian Osmand0626aa2019-03-11 15:28:06 -0400254 case kRGBA_half_Clamped_GrPixelConfig: return true;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500255 case kRGB_ETC1_GrPixelConfig: return false;
256 case kAlpha_8_as_Alpha_GrPixelConfig: return false;
257 case kAlpha_8_as_Red_GrPixelConfig: return false;
258 case kAlpha_half_as_Red_GrPixelConfig: return false;
259 case kGray_8_as_Lum_GrPixelConfig: return false;
260 case kGray_8_as_Red_GrPixelConfig: return false;
261 }
262 SK_ABORT("Invalid GrPixelConfig");
263 return false;
264}
265
266static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuConfig,
267 bool premulConversion) {
268 // We only allow premul <-> unpremul conversions for some formats
269 if (premulConversion &&
270 (!valid_premul_color_type(cpuColorType) || !valid_premul_config(gpuConfig))) {
271 return false;
272 }
273 return true;
274}
275
276bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width,
277 int height, GrColorType dstColorType,
278 SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
279 uint32_t pixelOpsFlags) {
280 ASSERT_SINGLE_OWNER_PRIV
281 RETURN_FALSE_IF_ABANDONED_PRIV
282 SkASSERT(src);
283 SkASSERT(buffer);
284 ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
285 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext);
286
Robert Phillips8e1529c2019-04-05 08:17:25 -0400287 GrSurfaceProxy* srcProxy = src->asSurfaceProxy();
288
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500289 // MDB TODO: delay this instantiation until later in the method
Robert Phillips8e1529c2019-04-05 08:17:25 -0400290 if (!srcProxy->instantiate(this->resourceProvider())) {
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500291 return false;
292 }
293
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500294 GrSurface* srcSurface = srcProxy->peekSurface();
295
296 if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
297 GrColorTypeBytesPerPixel(dstColorType), &left, &top,
298 &width, &height, &buffer, &rowBytes)) {
299 return false;
300 }
301
302 // TODO: Make GrSurfaceContext know its alpha type and pass dst buffer's alpha type.
303 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
304
305 if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) {
306 return false;
307 }
308
Brian Osman4f98dbe2019-03-28 11:49:01 -0400309 bool needColorConversion =
310 SkColorSpaceXformSteps::Required(src->colorSpaceInfo().colorSpace(), dstColorSpace);
311
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500312 // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't
313 // care so much about getImageData performance. However, in order to ensure putImageData/
314 // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary
315 // unpremul step to writeSurfacePixels's premul step (which is determined empirically in
316 // fContext->vaildaPMUPMConversionExists()).
317 bool canvas2DFastPath =
318 unpremul &&
Brian Osman4f98dbe2019-03-28 11:49:01 -0400319 !needColorConversion &&
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500320 (GrColorType::kRGBA_8888 == dstColorType || GrColorType::kBGRA_8888 == dstColorType) &&
321 SkToBool(srcProxy->asTextureProxy()) &&
322 (srcProxy->config() == kRGBA_8888_GrPixelConfig ||
323 srcProxy->config() == kBGRA_8888_GrPixelConfig) &&
324 fContext->priv().caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig) &&
325 fContext->validPMUPMConversionExists();
326
327 if (!fContext->priv().caps()->surfaceSupportsReadPixels(srcSurface) ||
328 canvas2DFastPath) {
329 GrSurfaceDesc desc;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500330 desc.fWidth = width;
331 desc.fHeight = height;
332 desc.fSampleCnt = 1;
333
334 GrBackendFormat format;
335 if (canvas2DFastPath) {
336 desc.fFlags = kRenderTarget_GrSurfaceFlag;
337 desc.fConfig = kRGBA_8888_GrPixelConfig;
338 format = this->caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
339 } else {
340 desc.fFlags = kNone_GrSurfaceFlags;
341 desc.fConfig = srcProxy->config();
342 format = srcProxy->backendFormat().makeTexture2D();
343 if (!format.isValid()) {
344 return false;
345 }
346 }
347
348 auto tempProxy = this->proxyProvider()->createProxy(
349 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
350 if (!tempProxy) {
351 return false;
352 }
353 sk_sp<GrSurfaceContext> tempCtx;
354 if (canvas2DFastPath) {
355 tempCtx = this->drawingManager()->makeRenderTargetContext(std::move(tempProxy), nullptr,
356 nullptr);
357 SkASSERT(tempCtx->asRenderTargetContext());
358 tempCtx->asRenderTargetContext()->discard();
359 } else {
360 tempCtx = this->drawingManager()->makeTextureContext(
361 std::move(tempProxy), src->colorSpaceInfo().refColorSpace());
362 }
363 if (!tempCtx) {
364 return false;
365 }
366 if (canvas2DFastPath) {
367 GrPaint paint;
368 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
369 auto fp = fContext->createPMToUPMEffect(
370 GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()),
371 SkMatrix::I()));
372 if (dstColorType == GrColorType::kBGRA_8888) {
373 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
374 dstColorType = GrColorType::kRGBA_8888;
375 }
376 if (!fp) {
377 return false;
378 }
379 paint.addColorFragmentProcessor(std::move(fp));
380 tempCtx->asRenderTargetContext()->fillRectToRect(
381 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
382 SkRect::MakeWH(width, height), SkRect::MakeXYWH(left, top, width, height));
383 } else if (!tempCtx->copy(srcProxy, SkIRect::MakeXYWH(left, top, width, height), {0, 0})) {
384 return false;
385 }
386 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
387 return this->readSurfacePixels(tempCtx.get(), 0, 0, width, height, dstColorType,
388 dstColorSpace, buffer, rowBytes, flags);
389 }
390
Brian Osman4f98dbe2019-03-28 11:49:01 -0400391 bool convert = unpremul || needColorConversion;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500392
393 bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
394 if (flip) {
395 top = srcSurface->height() - top - height;
396 }
397
398 GrColorType allowedColorType = fContext->priv().caps()->supportedReadPixelsColorType(
399 srcProxy->config(), dstColorType);
400 convert = convert || (dstColorType != allowedColorType);
401
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500402 SkAutoPixmapStorage tempPixmap;
403 SkPixmap finalPixmap;
404 if (convert) {
405 SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
406 SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
407 bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType);
408 bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType);
409 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
410 return false;
411 }
412 auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
413 auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
414 src->colorSpaceInfo().refColorSpace());
415 SkASSERT(!unpremul || !dstAlwaysOpaque);
416 auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque)
417 ? kOpaque_SkAlphaType
418 : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
419 auto finalII =
420 SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace));
421 if (!SkImageInfoValidConversion(finalII, tempII)) {
422 return false;
423 }
424 if (!tempPixmap.tryAlloc(tempII)) {
425 return false;
426 }
427 finalPixmap.reset(finalII, buffer, rowBytes);
428 buffer = tempPixmap.writable_addr();
429 rowBytes = tempPixmap.rowBytes();
430 // Chrome msan bots require this.
431 sk_bzero(buffer, tempPixmap.computeByteSize());
432 }
433
Robert Phillips8e1529c2019-04-05 08:17:25 -0400434 this->flush(srcProxy);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500435
436 if (!fContext->fGpu->readPixels(srcSurface, left, top, width, height, allowedColorType, buffer,
437 rowBytes)) {
438 return false;
439 }
440
441 if (flip) {
442 size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
443 std::unique_ptr<char[]> row(new char[trimRowBytes]);
444 char* upper = reinterpret_cast<char*>(buffer);
445 char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes;
446 for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) {
447 memcpy(row.get(), upper, trimRowBytes);
448 memcpy(upper, lower, trimRowBytes);
449 memcpy(lower, row.get(), trimRowBytes);
450 }
451 }
452 if (convert) {
453 if (!tempPixmap.readPixels(finalPixmap)) {
454 return false;
455 }
456 }
457 return true;
458}
459
460bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width,
461 int height, GrColorType srcColorType,
462 SkColorSpace* srcColorSpace, const void* buffer,
463 size_t rowBytes, uint32_t pixelOpsFlags) {
464 ASSERT_SINGLE_OWNER_PRIV
465 RETURN_FALSE_IF_ABANDONED_PRIV
466 SkASSERT(dst);
467 SkASSERT(buffer);
468 ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy());
469 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext);
470
471 if (GrColorType::kUnknown == srcColorType) {
472 return false;
473 }
474
Robert Phillips8e1529c2019-04-05 08:17:25 -0400475 GrSurfaceProxy* dstProxy = dst->asSurfaceProxy();
476 if (!dstProxy->instantiate(this->resourceProvider())) {
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500477 return false;
478 }
479
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500480 GrSurface* dstSurface = dstProxy->peekSurface();
481
482 if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(),
483 GrColorTypeBytesPerPixel(srcColorType), &left, &top,
484 &width, &height, &buffer, &rowBytes)) {
485 return false;
486 }
487
488 // TODO: Make GrSurfaceContext know its alpha type and pass src buffer's alpha type.
489 bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
490
Brian Osman4f98dbe2019-03-28 11:49:01 -0400491 bool needColorConversion =
492 SkColorSpaceXformSteps::Required(srcColorSpace, dst->colorSpaceInfo().colorSpace());
493
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500494 // For canvas2D putImageData performance we have a special code path for unpremul RGBA_8888 srcs
495 // that are premultiplied on the GPU. This is kept as narrow as possible for now.
496 bool canvas2DFastPath =
497 !fContext->priv().caps()->avoidWritePixelsFastPath() &&
498 premul &&
Brian Osman4f98dbe2019-03-28 11:49:01 -0400499 !needColorConversion &&
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500500 (srcColorType == GrColorType::kRGBA_8888 || srcColorType == GrColorType::kBGRA_8888) &&
501 SkToBool(dst->asRenderTargetContext()) &&
502 (dstProxy->config() == kRGBA_8888_GrPixelConfig ||
503 dstProxy->config() == kBGRA_8888_GrPixelConfig) &&
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500504 fContext->priv().caps()->isConfigTexturable(kRGBA_8888_GrPixelConfig) &&
505 fContext->validPMUPMConversionExists();
506
507 const GrCaps* caps = this->caps();
Robert Phillipsba4178e2019-03-28 14:53:27 -0400508 if (!caps->surfaceSupportsWritePixels(dstSurface) || canvas2DFastPath) {
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500509 GrSurfaceDesc desc;
510 desc.fWidth = width;
511 desc.fHeight = height;
512 desc.fSampleCnt = 1;
513
514 GrBackendFormat format;
515 if (canvas2DFastPath) {
516 desc.fConfig = kRGBA_8888_GrPixelConfig;
517 format =
518 fContext->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
519 } else {
520 desc.fConfig = dstProxy->config();
521 format = dstProxy->backendFormat().makeTexture2D();
522 if (!format.isValid()) {
523 return false;
524 }
525 }
526
527 auto tempProxy = this->proxyProvider()->createProxy(
528 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
529 if (!tempProxy) {
530 return false;
531 }
532 auto tempCtx = this->drawingManager()->makeTextureContext(
533 tempProxy, dst->colorSpaceInfo().refColorSpace());
534 if (!tempCtx) {
535 return false;
536 }
537 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
538 // In the fast path we always write the srcData to the temp context as though it were RGBA.
539 // When the data is really BGRA the write will cause the R and B channels to be swapped in
540 // the intermediate surface which gets corrected by a swizzle effect when drawing to the
541 // dst.
542 auto tmpColorType = canvas2DFastPath ? GrColorType::kRGBA_8888 : srcColorType;
543 if (!this->writeSurfacePixels(tempCtx.get(), 0, 0, width, height, tmpColorType,
544 srcColorSpace, buffer, rowBytes, flags)) {
545 return false;
546 }
547 if (canvas2DFastPath) {
548 GrPaint paint;
549 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
550 auto fp = fContext->createUPMToPMEffect(
551 GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I()));
552 if (srcColorType == GrColorType::kBGRA_8888) {
553 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
554 }
555 if (!fp) {
556 return false;
557 }
558 paint.addColorFragmentProcessor(std::move(fp));
559 dst->asRenderTargetContext()->fillRectToRect(
560 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
561 SkRect::MakeXYWH(left, top, width, height), SkRect::MakeWH(width, height));
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500562 } else {
Robert Phillips8e1529c2019-04-05 08:17:25 -0400563 if (!dst->copy(tempProxy.get(), SkIRect::MakeWH(width, height), {left, top})) {
564 return false;
565 }
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500566 }
Robert Phillips8e1529c2019-04-05 08:17:25 -0400567
568 return true;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500569 }
570
Brian Osman4f98dbe2019-03-28 11:49:01 -0400571 bool convert = premul || needColorConversion;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500572
573 if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
574 return false;
575 }
576
577 GrColorType allowedColorType = fContext->priv().caps()->supportedWritePixelsColorType(
578 dstProxy->config(), srcColorType);
579 convert = convert || (srcColorType != allowedColorType);
580
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500581 std::unique_ptr<char[]> tempBuffer;
582 if (convert) {
583 auto srcSkColorType = GrColorTypeToSkColorType(srcColorType);
584 auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType);
585 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
586 return false;
587 }
588 auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType)
589 ? kOpaque_SkAlphaType
590 : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
591 SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType,
592 sk_ref_sp(srcColorSpace)),
593 buffer, rowBytes);
594 auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType,
595 dst->colorSpaceInfo().refColorSpace());
596 auto size = tempSrcII.computeMinByteSize();
597 if (!size) {
598 return false;
599 }
600 tempBuffer.reset(new char[size]);
601 SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes());
602 if (!src.readPixels(tempSrc)) {
603 return false;
604 }
605 srcColorType = allowedColorType;
606 buffer = tempSrc.addr();
607 rowBytes = tempSrc.rowBytes();
608 if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
609 std::unique_ptr<char[]> row(new char[rowBytes]);
610 for (int y = 0; y < height / 2; ++y) {
611 memcpy(row.get(), tempSrc.addr(0, y), rowBytes);
612 memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), rowBytes);
613 memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), rowBytes);
614 }
615 top = dstSurface->height() - top - height;
616 }
617 } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
618 size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
619 tempBuffer.reset(new char[trimRowBytes * height]);
620 char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1);
621 const char* src = reinterpret_cast<const char*>(buffer);
622 for (int i = 0; i < height; ++i, src += rowBytes, dst -= trimRowBytes) {
623 memcpy(dst, src, trimRowBytes);
624 }
625 buffer = tempBuffer.get();
626 rowBytes = trimRowBytes;
627 top = dstSurface->height() - top - height;
628 }
629
Robert Phillips8e1529c2019-04-05 08:17:25 -0400630 this->flush(dstProxy);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500631
632 return this->getGpu()->writePixels(dstSurface, left, top, width, height, srcColorType, buffer,
633 rowBytes);
634}
635
636void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
Robert Phillips292a6b22019-02-14 14:49:02 -0500637 fContext->drawingManager()->moveOpListsToDDL(ddl);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500638}
639
640void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
641 GrRenderTargetProxy* newDest) {
Robert Phillips6a6de562019-02-15 15:19:15 -0500642 fContext->drawingManager()->copyOpListsFromDDL(ddl, newDest);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500643}
644
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500645//////////////////////////////////////////////////////////////////////////////
646#ifdef SK_ENABLE_DUMP_GPU
647#include "SkJSONWriter.h"
648SkString GrContextPriv::dump() const {
649 SkDynamicMemoryWStream stream;
650 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
651 writer.beginObject();
652
653 static const char* kBackendStr[] = {
654 "Metal",
655 "OpenGL",
656 "Vulkan",
657 "Mock",
658 };
659 GR_STATIC_ASSERT(0 == (unsigned)GrBackendApi::kMetal);
660 GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kOpenGL);
661 GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kVulkan);
662 GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kMock);
663 writer.appendString("backend", kBackendStr[(unsigned)fContext->backend()]);
664
665 writer.appendName("caps");
666 fContext->caps()->dumpJSON(&writer);
667
668 writer.appendName("gpu");
669 fContext->fGpu->dumpJSON(&writer);
670
671 // Flush JSON to the memory stream
672 writer.endObject();
673 writer.flush();
674
675 // Null terminate the JSON data in the memory stream
676 stream.write8(0);
677
678 // Allocate a string big enough to hold all the data, then copy out of the stream
679 SkString result(stream.bytesWritten());
680 stream.copyToAndReset(result.writable_str());
681 return result;
682}
683#endif
684
685#if GR_TEST_UTILS
686void GrContextPriv::resetGpuStats() const {
687#if GR_GPU_STATS
688 fContext->fGpu->stats()->reset();
689#endif
690}
691
692void GrContextPriv::dumpCacheStats(SkString* out) const {
693#if GR_CACHE_STATS
694 fContext->fResourceCache->dumpStats(out);
695#endif
696}
697
698void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
699 SkTArray<double>* values) const {
700#if GR_CACHE_STATS
701 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values);
702#endif
703}
704
705void GrContextPriv::printCacheStats() const {
706 SkString out;
707 this->dumpCacheStats(&out);
708 SkDebugf("%s", out.c_str());
709}
710
711void GrContextPriv::dumpGpuStats(SkString* out) const {
712#if GR_GPU_STATS
713 return fContext->fGpu->stats()->dump(out);
714#endif
715}
716
717void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
718 SkTArray<double>* values) const {
719#if GR_GPU_STATS
720 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values);
721#endif
722}
723
724void GrContextPriv::printGpuStats() const {
725 SkString out;
726 this->dumpGpuStats(&out);
727 SkDebugf("%s", out.c_str());
728}
729
730void GrContextPriv::testingOnly_setTextBlobCacheLimit(size_t bytes) {
Robert Phillips2184fb72019-02-21 16:11:41 -0500731 fContext->priv().getTextBlobCache()->setBudget(bytes);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500732}
733
734sk_sp<SkImage> GrContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index) {
735 auto atlasManager = this->getAtlasManager();
736 if (!atlasManager) {
737 return nullptr;
738 }
739
740 unsigned int numActiveProxies;
741 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies);
742 if (index >= numActiveProxies || !proxies || !proxies[index]) {
743 return nullptr;
744 }
745
746 SkASSERT(proxies[index]->priv().isExact());
747 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID,
748 kPremul_SkAlphaType, proxies[index], nullptr));
749 return image;
750}
751
752void GrContextPriv::testingOnly_purgeAllUnlockedResources() {
753 fContext->fResourceCache->purgeAllUnlocked();
754}
755
756void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
757 fContext->flush();
Robert Phillips292a6b22019-02-14 14:49:02 -0500758 fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500759}
760#endif
761