blob: 10772ef494c1d27dbc45e371d271e269de9f1f5d [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrContextPriv.h"
Robert Phillipsdbaf3172019-02-06 15:12:53 -05009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrContextThreadSafeProxy.h"
11#include "include/gpu/GrTexture.h"
12#include "include/private/GrSkSLFPFactoryCache.h"
13#include "src/core/SkAutoPixmapStorage.h"
14#include "src/gpu/GrClip.h"
15#include "src/gpu/GrContextThreadSafeProxyPriv.h"
16#include "src/gpu/GrDrawingManager.h"
17#include "src/gpu/GrGpu.h"
18#include "src/gpu/GrMemoryPool.h"
19#include "src/gpu/GrRenderTargetContext.h"
20#include "src/gpu/GrSurfacePriv.h"
21#include "src/gpu/GrTextureContext.h"
22#include "src/gpu/SkGr.h"
23#include "src/gpu/text/GrTextBlobCache.h"
24#include "src/image/SkImage_Base.h"
25#include "src/image/SkImage_Gpu.h"
Robert Phillipsdbaf3172019-02-06 15:12:53 -050026
Brian Salomond0503a72019-05-09 09:03:57 -040027#define ASSERT_OWNED_PROXY(P) \
Robert Phillipsdbaf3172019-02-06 15:12:53 -050028 SkASSERT(!(P) || !((P)->peekTexture()) || (P)->peekTexture()->getContext() == fContext)
Brian Salomond0503a72019-05-09 09:03:57 -040029#define ASSERT_SINGLE_OWNER \
Robert Phillipsa41c6852019-02-07 10:44:10 -050030 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fContext->singleOwner());)
Brian Salomond0503a72019-05-09 09:03:57 -040031#define RETURN_VALUE_IF_ABANDONED(value) if (fContext->abandoned()) { return (value); }
32#define RETURN_IF_ABANDONED RETURN_VALUE_IF_ABANDONED(void)
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) {
Brian Salomond0503a72019-05-09 09:03:57 -0400106 ASSERT_SINGLE_OWNER
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500107
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) {
Brian Salomond0503a72019-05-09 09:03:57 -0400125 ASSERT_SINGLE_OWNER
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500126 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) {
Brian Salomond0503a72019-05-09 09:03:57 -0400146 ASSERT_SINGLE_OWNER
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500147
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) {
Brian Salomond0503a72019-05-09 09:03:57 -0400165 ASSERT_SINGLE_OWNER
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500166 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) {
Brian Salomond0503a72019-05-09 09:03:57 -0400180 ASSERT_SINGLE_OWNER
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500181 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
Brian Salomond0503a72019-05-09 09:03:57 -0400192GrSemaphoresSubmitted GrContextPriv::flushSurfaces(GrSurfaceProxy* proxies[], int numProxies,
193 const GrFlushInfo& info) {
194 ASSERT_SINGLE_OWNER
195 RETURN_VALUE_IF_ABANDONED(GrSemaphoresSubmitted::kNo)
196 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "flushSurfaces", fContext);
197 SkASSERT(numProxies >= 0);
198 SkASSERT(!numProxies || proxies);
199 for (int i = 0; i < numProxies; ++i) {
200 SkASSERT(proxies[i]);
201 ASSERT_OWNED_PROXY(proxies[i]);
202 }
203 return fContext->drawingManager()->flushSurfaces(
204 proxies, numProxies, SkSurface::BackendSurfaceAccess::kNoAccess, info);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500205}
206
Brian Salomond0503a72019-05-09 09:03:57 -0400207void GrContextPriv::flushSurface(GrSurfaceProxy* proxy) { this->flushSurfaces(&proxy, 1, {}); }
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500208
209static bool valid_premul_color_type(GrColorType ct) {
210 switch (ct) {
Brian Osmand0626aa2019-03-11 15:28:06 -0400211 case GrColorType::kUnknown: return false;
212 case GrColorType::kAlpha_8: return false;
213 case GrColorType::kRGB_565: return false;
214 case GrColorType::kABGR_4444: return true;
215 case GrColorType::kRGBA_8888: return true;
216 case GrColorType::kRGB_888x: return false;
217 case GrColorType::kRG_88: return false;
218 case GrColorType::kBGRA_8888: return true;
219 case GrColorType::kRGBA_1010102: return true;
220 case GrColorType::kGray_8: return false;
221 case GrColorType::kAlpha_F16: return false;
222 case GrColorType::kRGBA_F16: return true;
223 case GrColorType::kRGBA_F16_Clamped: return true;
224 case GrColorType::kRG_F32: return false;
225 case GrColorType::kRGBA_F32: return true;
226 case GrColorType::kRGB_ETC1: return false;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500227 }
228 SK_ABORT("Invalid GrColorType");
229 return false;
230}
231
232// TODO: This will be removed when GrSurfaceContexts are aware of their color types.
233// (skbug.com/6718)
234static bool valid_premul_config(GrPixelConfig config) {
235 switch (config) {
236 case kUnknown_GrPixelConfig: return false;
237 case kAlpha_8_GrPixelConfig: return false;
238 case kGray_8_GrPixelConfig: return false;
239 case kRGB_565_GrPixelConfig: return false;
240 case kRGBA_4444_GrPixelConfig: return true;
241 case kRGBA_8888_GrPixelConfig: return true;
242 case kRGB_888_GrPixelConfig: return false;
Greg Danielf259b8b2019-02-14 09:03:43 -0500243 case kRGB_888X_GrPixelConfig: return false;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500244 case kRG_88_GrPixelConfig: return false;
245 case kBGRA_8888_GrPixelConfig: return true;
246 case kSRGBA_8888_GrPixelConfig: return true;
247 case kSBGRA_8888_GrPixelConfig: return true;
248 case kRGBA_1010102_GrPixelConfig: return true;
249 case kRGBA_float_GrPixelConfig: return true;
250 case kRG_float_GrPixelConfig: return false;
251 case kAlpha_half_GrPixelConfig: return false;
252 case kRGBA_half_GrPixelConfig: return true;
Brian Osmand0626aa2019-03-11 15:28:06 -0400253 case kRGBA_half_Clamped_GrPixelConfig: return true;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500254 case kRGB_ETC1_GrPixelConfig: return false;
255 case kAlpha_8_as_Alpha_GrPixelConfig: return false;
256 case kAlpha_8_as_Red_GrPixelConfig: return false;
257 case kAlpha_half_as_Red_GrPixelConfig: return false;
258 case kGray_8_as_Lum_GrPixelConfig: return false;
259 case kGray_8_as_Red_GrPixelConfig: return false;
260 }
261 SK_ABORT("Invalid GrPixelConfig");
262 return false;
263}
264
265static bool valid_pixel_conversion(GrColorType cpuColorType, GrPixelConfig gpuConfig,
266 bool premulConversion) {
267 // We only allow premul <-> unpremul conversions for some formats
268 if (premulConversion &&
269 (!valid_premul_color_type(cpuColorType) || !valid_premul_config(gpuConfig))) {
270 return false;
271 }
272 return true;
273}
274
275bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src, int left, int top, int width,
276 int height, GrColorType dstColorType,
277 SkColorSpace* dstColorSpace, void* buffer, size_t rowBytes,
278 uint32_t pixelOpsFlags) {
Brian Salomond0503a72019-05-09 09:03:57 -0400279 ASSERT_SINGLE_OWNER
280 RETURN_VALUE_IF_ABANDONED(false)
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500281 SkASSERT(src);
282 SkASSERT(buffer);
Brian Salomond0503a72019-05-09 09:03:57 -0400283 ASSERT_OWNED_PROXY(src->asSurfaceProxy());
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500284 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "readSurfacePixels", fContext);
285
Robert Phillips8e1529c2019-04-05 08:17:25 -0400286 GrSurfaceProxy* srcProxy = src->asSurfaceProxy();
287
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500288 // MDB TODO: delay this instantiation until later in the method
Robert Phillips8e1529c2019-04-05 08:17:25 -0400289 if (!srcProxy->instantiate(this->resourceProvider())) {
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500290 return false;
291 }
292
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500293 GrSurface* srcSurface = srcProxy->peekSurface();
294
295 if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
296 GrColorTypeBytesPerPixel(dstColorType), &left, &top,
297 &width, &height, &buffer, &rowBytes)) {
298 return false;
299 }
300
301 // TODO: Make GrSurfaceContext know its alpha type and pass dst buffer's alpha type.
302 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
303
304 if (!valid_pixel_conversion(dstColorType, srcProxy->config(), unpremul)) {
305 return false;
306 }
307
Brian Osman4f98dbe2019-03-28 11:49:01 -0400308 bool needColorConversion =
309 SkColorSpaceXformSteps::Required(src->colorSpaceInfo().colorSpace(), dstColorSpace);
310
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500311 // This is the getImageData equivalent to the canvas2D putImageData fast path. We probably don't
312 // care so much about getImageData performance. However, in order to ensure putImageData/
313 // getImageData in "legacy" mode are round-trippable we use the GPU to do the complementary
314 // unpremul step to writeSurfacePixels's premul step (which is determined empirically in
315 // fContext->vaildaPMUPMConversionExists()).
316 bool canvas2DFastPath =
317 unpremul &&
Brian Osman4f98dbe2019-03-28 11:49:01 -0400318 !needColorConversion &&
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500319 (GrColorType::kRGBA_8888 == dstColorType || GrColorType::kBGRA_8888 == dstColorType) &&
320 SkToBool(srcProxy->asTextureProxy()) &&
321 (srcProxy->config() == kRGBA_8888_GrPixelConfig ||
322 srcProxy->config() == kBGRA_8888_GrPixelConfig) &&
323 fContext->priv().caps()->isConfigRenderable(kRGBA_8888_GrPixelConfig) &&
324 fContext->validPMUPMConversionExists();
325
326 if (!fContext->priv().caps()->surfaceSupportsReadPixels(srcSurface) ||
327 canvas2DFastPath) {
328 GrSurfaceDesc desc;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500329 desc.fWidth = width;
330 desc.fHeight = height;
331 desc.fSampleCnt = 1;
332
333 GrBackendFormat format;
334 if (canvas2DFastPath) {
335 desc.fFlags = kRenderTarget_GrSurfaceFlag;
336 desc.fConfig = kRGBA_8888_GrPixelConfig;
337 format = this->caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
338 } else {
339 desc.fFlags = kNone_GrSurfaceFlags;
340 desc.fConfig = srcProxy->config();
341 format = srcProxy->backendFormat().makeTexture2D();
342 if (!format.isValid()) {
343 return false;
344 }
345 }
346
347 auto tempProxy = this->proxyProvider()->createProxy(
348 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
349 if (!tempProxy) {
350 return false;
351 }
352 sk_sp<GrSurfaceContext> tempCtx;
353 if (canvas2DFastPath) {
354 tempCtx = this->drawingManager()->makeRenderTargetContext(std::move(tempProxy), nullptr,
355 nullptr);
356 SkASSERT(tempCtx->asRenderTargetContext());
357 tempCtx->asRenderTargetContext()->discard();
358 } else {
359 tempCtx = this->drawingManager()->makeTextureContext(
360 std::move(tempProxy), src->colorSpaceInfo().refColorSpace());
361 }
362 if (!tempCtx) {
363 return false;
364 }
365 if (canvas2DFastPath) {
366 GrPaint paint;
367 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
368 auto fp = fContext->createPMToUPMEffect(
369 GrSimpleTextureEffect::Make(sk_ref_sp(srcProxy->asTextureProxy()),
370 SkMatrix::I()));
371 if (dstColorType == GrColorType::kBGRA_8888) {
372 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
373 dstColorType = GrColorType::kRGBA_8888;
374 }
375 if (!fp) {
376 return false;
377 }
378 paint.addColorFragmentProcessor(std::move(fp));
379 tempCtx->asRenderTargetContext()->fillRectToRect(
380 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
381 SkRect::MakeWH(width, height), SkRect::MakeXYWH(left, top, width, height));
382 } else if (!tempCtx->copy(srcProxy, SkIRect::MakeXYWH(left, top, width, height), {0, 0})) {
383 return false;
384 }
385 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
386 return this->readSurfacePixels(tempCtx.get(), 0, 0, width, height, dstColorType,
387 dstColorSpace, buffer, rowBytes, flags);
388 }
389
Brian Osman4f98dbe2019-03-28 11:49:01 -0400390 bool convert = unpremul || needColorConversion;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500391
392 bool flip = srcProxy->origin() == kBottomLeft_GrSurfaceOrigin;
393 if (flip) {
394 top = srcSurface->height() - top - height;
395 }
396
397 GrColorType allowedColorType = fContext->priv().caps()->supportedReadPixelsColorType(
398 srcProxy->config(), dstColorType);
399 convert = convert || (dstColorType != allowedColorType);
400
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500401 SkAutoPixmapStorage tempPixmap;
402 SkPixmap finalPixmap;
403 if (convert) {
404 SkColorType srcSkColorType = GrColorTypeToSkColorType(allowedColorType);
405 SkColorType dstSkColorType = GrColorTypeToSkColorType(dstColorType);
406 bool srcAlwaysOpaque = SkColorTypeIsAlwaysOpaque(srcSkColorType);
407 bool dstAlwaysOpaque = SkColorTypeIsAlwaysOpaque(dstSkColorType);
408 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
409 return false;
410 }
411 auto tempAT = srcAlwaysOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
412 auto tempII = SkImageInfo::Make(width, height, srcSkColorType, tempAT,
413 src->colorSpaceInfo().refColorSpace());
414 SkASSERT(!unpremul || !dstAlwaysOpaque);
415 auto finalAT = (srcAlwaysOpaque || dstAlwaysOpaque)
416 ? kOpaque_SkAlphaType
417 : unpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
418 auto finalII =
419 SkImageInfo::Make(width, height, dstSkColorType, finalAT, sk_ref_sp(dstColorSpace));
420 if (!SkImageInfoValidConversion(finalII, tempII)) {
421 return false;
422 }
423 if (!tempPixmap.tryAlloc(tempII)) {
424 return false;
425 }
426 finalPixmap.reset(finalII, buffer, rowBytes);
427 buffer = tempPixmap.writable_addr();
428 rowBytes = tempPixmap.rowBytes();
429 // Chrome msan bots require this.
430 sk_bzero(buffer, tempPixmap.computeByteSize());
431 }
432
Brian Salomond0503a72019-05-09 09:03:57 -0400433 this->flushSurface(srcProxy);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500434
435 if (!fContext->fGpu->readPixels(srcSurface, left, top, width, height, allowedColorType, buffer,
436 rowBytes)) {
437 return false;
438 }
439
440 if (flip) {
441 size_t trimRowBytes = GrColorTypeBytesPerPixel(allowedColorType) * width;
442 std::unique_ptr<char[]> row(new char[trimRowBytes]);
443 char* upper = reinterpret_cast<char*>(buffer);
444 char* lower = reinterpret_cast<char*>(buffer) + (height - 1) * rowBytes;
445 for (int y = 0; y < height / 2; ++y, upper += rowBytes, lower -= rowBytes) {
446 memcpy(row.get(), upper, trimRowBytes);
447 memcpy(upper, lower, trimRowBytes);
448 memcpy(lower, row.get(), trimRowBytes);
449 }
450 }
451 if (convert) {
452 if (!tempPixmap.readPixels(finalPixmap)) {
453 return false;
454 }
455 }
456 return true;
457}
458
459bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst, int left, int top, int width,
460 int height, GrColorType srcColorType,
461 SkColorSpace* srcColorSpace, const void* buffer,
462 size_t rowBytes, uint32_t pixelOpsFlags) {
Brian Salomond0503a72019-05-09 09:03:57 -0400463 ASSERT_SINGLE_OWNER
464 RETURN_VALUE_IF_ABANDONED(false)
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500465 SkASSERT(dst);
466 SkASSERT(buffer);
Brian Salomond0503a72019-05-09 09:03:57 -0400467 ASSERT_OWNED_PROXY(dst->asSurfaceProxy());
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500468 GR_CREATE_TRACE_MARKER_CONTEXT("GrContextPriv", "writeSurfacePixels", fContext);
469
470 if (GrColorType::kUnknown == srcColorType) {
471 return false;
472 }
473
Robert Phillips8e1529c2019-04-05 08:17:25 -0400474 GrSurfaceProxy* dstProxy = dst->asSurfaceProxy();
475 if (!dstProxy->instantiate(this->resourceProvider())) {
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500476 return false;
477 }
478
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500479 GrSurface* dstSurface = dstProxy->peekSurface();
480
481 if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(),
482 GrColorTypeBytesPerPixel(srcColorType), &left, &top,
483 &width, &height, &buffer, &rowBytes)) {
484 return false;
485 }
486
487 // TODO: Make GrSurfaceContext know its alpha type and pass src buffer's alpha type.
488 bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
489
Brian Osman4f98dbe2019-03-28 11:49:01 -0400490 bool needColorConversion =
491 SkColorSpaceXformSteps::Required(srcColorSpace, dst->colorSpaceInfo().colorSpace());
492
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500493 // For canvas2D putImageData performance we have a special code path for unpremul RGBA_8888 srcs
494 // that are premultiplied on the GPU. This is kept as narrow as possible for now.
495 bool canvas2DFastPath =
496 !fContext->priv().caps()->avoidWritePixelsFastPath() &&
497 premul &&
Brian Osman4f98dbe2019-03-28 11:49:01 -0400498 !needColorConversion &&
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500499 (srcColorType == GrColorType::kRGBA_8888 || srcColorType == GrColorType::kBGRA_8888) &&
500 SkToBool(dst->asRenderTargetContext()) &&
501 (dstProxy->config() == kRGBA_8888_GrPixelConfig ||
502 dstProxy->config() == kBGRA_8888_GrPixelConfig) &&
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500503 fContext->priv().caps()->isConfigTexturable(kRGBA_8888_GrPixelConfig) &&
504 fContext->validPMUPMConversionExists();
505
506 const GrCaps* caps = this->caps();
Robert Phillipsba4178e2019-03-28 14:53:27 -0400507 if (!caps->surfaceSupportsWritePixels(dstSurface) || canvas2DFastPath) {
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500508 GrSurfaceDesc desc;
509 desc.fWidth = width;
510 desc.fHeight = height;
511 desc.fSampleCnt = 1;
512
513 GrBackendFormat format;
514 if (canvas2DFastPath) {
515 desc.fConfig = kRGBA_8888_GrPixelConfig;
516 format =
517 fContext->priv().caps()->getBackendFormatFromColorType(kRGBA_8888_SkColorType);
518 } else {
519 desc.fConfig = dstProxy->config();
520 format = dstProxy->backendFormat().makeTexture2D();
521 if (!format.isValid()) {
522 return false;
523 }
524 }
525
526 auto tempProxy = this->proxyProvider()->createProxy(
527 format, desc, kTopLeft_GrSurfaceOrigin, SkBackingFit::kApprox, SkBudgeted::kYes);
528 if (!tempProxy) {
529 return false;
530 }
531 auto tempCtx = this->drawingManager()->makeTextureContext(
532 tempProxy, dst->colorSpaceInfo().refColorSpace());
533 if (!tempCtx) {
534 return false;
535 }
536 uint32_t flags = canvas2DFastPath ? 0 : pixelOpsFlags;
537 // In the fast path we always write the srcData to the temp context as though it were RGBA.
538 // When the data is really BGRA the write will cause the R and B channels to be swapped in
539 // the intermediate surface which gets corrected by a swizzle effect when drawing to the
540 // dst.
541 auto tmpColorType = canvas2DFastPath ? GrColorType::kRGBA_8888 : srcColorType;
542 if (!this->writeSurfacePixels(tempCtx.get(), 0, 0, width, height, tmpColorType,
543 srcColorSpace, buffer, rowBytes, flags)) {
544 return false;
545 }
546 if (canvas2DFastPath) {
547 GrPaint paint;
548 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
549 auto fp = fContext->createUPMToPMEffect(
550 GrSimpleTextureEffect::Make(std::move(tempProxy), SkMatrix::I()));
551 if (srcColorType == GrColorType::kBGRA_8888) {
552 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), GrSwizzle::BGRA());
553 }
554 if (!fp) {
555 return false;
556 }
557 paint.addColorFragmentProcessor(std::move(fp));
558 dst->asRenderTargetContext()->fillRectToRect(
559 GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(),
560 SkRect::MakeXYWH(left, top, width, height), SkRect::MakeWH(width, height));
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500561 } else {
Robert Phillips8e1529c2019-04-05 08:17:25 -0400562 if (!dst->copy(tempProxy.get(), SkIRect::MakeWH(width, height), {left, top})) {
563 return false;
564 }
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500565 }
Robert Phillips8e1529c2019-04-05 08:17:25 -0400566
567 return true;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500568 }
569
Brian Osman4f98dbe2019-03-28 11:49:01 -0400570 bool convert = premul || needColorConversion;
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500571
572 if (!valid_pixel_conversion(srcColorType, dstProxy->config(), premul)) {
573 return false;
574 }
575
576 GrColorType allowedColorType = fContext->priv().caps()->supportedWritePixelsColorType(
577 dstProxy->config(), srcColorType);
578 convert = convert || (srcColorType != allowedColorType);
579
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500580 std::unique_ptr<char[]> tempBuffer;
581 if (convert) {
582 auto srcSkColorType = GrColorTypeToSkColorType(srcColorType);
583 auto dstSkColorType = GrColorTypeToSkColorType(allowedColorType);
584 if (kUnknown_SkColorType == srcSkColorType || kUnknown_SkColorType == dstSkColorType) {
585 return false;
586 }
587 auto srcAlphaType = SkColorTypeIsAlwaysOpaque(srcSkColorType)
588 ? kOpaque_SkAlphaType
589 : (premul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType);
590 SkPixmap src(SkImageInfo::Make(width, height, srcSkColorType, srcAlphaType,
591 sk_ref_sp(srcColorSpace)),
592 buffer, rowBytes);
593 auto tempSrcII = SkImageInfo::Make(width, height, dstSkColorType, kPremul_SkAlphaType,
594 dst->colorSpaceInfo().refColorSpace());
595 auto size = tempSrcII.computeMinByteSize();
596 if (!size) {
597 return false;
598 }
599 tempBuffer.reset(new char[size]);
600 SkPixmap tempSrc(tempSrcII, tempBuffer.get(), tempSrcII.minRowBytes());
601 if (!src.readPixels(tempSrc)) {
602 return false;
603 }
604 srcColorType = allowedColorType;
605 buffer = tempSrc.addr();
606 rowBytes = tempSrc.rowBytes();
607 if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
608 std::unique_ptr<char[]> row(new char[rowBytes]);
609 for (int y = 0; y < height / 2; ++y) {
610 memcpy(row.get(), tempSrc.addr(0, y), rowBytes);
611 memcpy(tempSrc.writable_addr(0, y), tempSrc.addr(0, height - 1 - y), rowBytes);
612 memcpy(tempSrc.writable_addr(0, height - 1 - y), row.get(), rowBytes);
613 }
614 top = dstSurface->height() - top - height;
615 }
616 } else if (dstProxy->origin() == kBottomLeft_GrSurfaceOrigin) {
617 size_t trimRowBytes = GrColorTypeBytesPerPixel(srcColorType) * width;
618 tempBuffer.reset(new char[trimRowBytes * height]);
619 char* dst = reinterpret_cast<char*>(tempBuffer.get()) + trimRowBytes * (height - 1);
620 const char* src = reinterpret_cast<const char*>(buffer);
621 for (int i = 0; i < height; ++i, src += rowBytes, dst -= trimRowBytes) {
622 memcpy(dst, src, trimRowBytes);
623 }
624 buffer = tempBuffer.get();
625 rowBytes = trimRowBytes;
626 top = dstSurface->height() - top - height;
627 }
628
Robert Phillips7ecb8d12019-04-24 11:17:06 -0400629 // On platforms that prefer flushes over VRAM use (i.e., ANGLE) we're better off forcing a
630 // complete flush here. On platforms that prefer VRAM use over flushes we're better off
631 // giving the drawing manager the chance of skipping the flush (i.e., by passing in the
632 // destination proxy)
633 // TODO: should this policy decision just be moved into the drawing manager?
Brian Salomond0503a72019-05-09 09:03:57 -0400634 this->flushSurface(caps->preferVRAMUseOverFlushes() ? dstProxy : nullptr);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500635
636 return this->getGpu()->writePixels(dstSurface, left, top, width, height, srcColorType, buffer,
637 rowBytes);
638}
639
640void GrContextPriv::moveOpListsToDDL(SkDeferredDisplayList* ddl) {
Robert Phillips292a6b22019-02-14 14:49:02 -0500641 fContext->drawingManager()->moveOpListsToDDL(ddl);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500642}
643
644void GrContextPriv::copyOpListsFromDDL(const SkDeferredDisplayList* ddl,
645 GrRenderTargetProxy* newDest) {
Robert Phillips6a6de562019-02-15 15:19:15 -0500646 fContext->drawingManager()->copyOpListsFromDDL(ddl, newDest);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500647}
648
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500649//////////////////////////////////////////////////////////////////////////////
650#ifdef SK_ENABLE_DUMP_GPU
Mike Kleinc0bd9f92019-04-23 12:05:21 -0500651#include "src/utils/SkJSONWriter.h"
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500652SkString GrContextPriv::dump() const {
653 SkDynamicMemoryWStream stream;
654 SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
655 writer.beginObject();
656
657 static const char* kBackendStr[] = {
658 "Metal",
659 "OpenGL",
660 "Vulkan",
661 "Mock",
662 };
663 GR_STATIC_ASSERT(0 == (unsigned)GrBackendApi::kMetal);
664 GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kOpenGL);
665 GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kVulkan);
666 GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kMock);
667 writer.appendString("backend", kBackendStr[(unsigned)fContext->backend()]);
668
669 writer.appendName("caps");
670 fContext->caps()->dumpJSON(&writer);
671
672 writer.appendName("gpu");
673 fContext->fGpu->dumpJSON(&writer);
674
675 // Flush JSON to the memory stream
676 writer.endObject();
677 writer.flush();
678
679 // Null terminate the JSON data in the memory stream
680 stream.write8(0);
681
682 // Allocate a string big enough to hold all the data, then copy out of the stream
683 SkString result(stream.bytesWritten());
684 stream.copyToAndReset(result.writable_str());
685 return result;
686}
687#endif
688
689#if GR_TEST_UTILS
690void GrContextPriv::resetGpuStats() const {
691#if GR_GPU_STATS
692 fContext->fGpu->stats()->reset();
693#endif
694}
695
696void GrContextPriv::dumpCacheStats(SkString* out) const {
697#if GR_CACHE_STATS
698 fContext->fResourceCache->dumpStats(out);
699#endif
700}
701
702void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
703 SkTArray<double>* values) const {
704#if GR_CACHE_STATS
705 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values);
706#endif
707}
708
709void GrContextPriv::printCacheStats() const {
710 SkString out;
711 this->dumpCacheStats(&out);
712 SkDebugf("%s", out.c_str());
713}
714
715void GrContextPriv::dumpGpuStats(SkString* out) const {
716#if GR_GPU_STATS
717 return fContext->fGpu->stats()->dump(out);
718#endif
719}
720
721void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
722 SkTArray<double>* values) const {
723#if GR_GPU_STATS
724 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values);
725#endif
726}
727
728void GrContextPriv::printGpuStats() const {
729 SkString out;
730 this->dumpGpuStats(&out);
731 SkDebugf("%s", out.c_str());
732}
733
734void GrContextPriv::testingOnly_setTextBlobCacheLimit(size_t bytes) {
Robert Phillips2184fb72019-02-21 16:11:41 -0500735 fContext->priv().getTextBlobCache()->setBudget(bytes);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500736}
737
738sk_sp<SkImage> GrContextPriv::testingOnly_getFontAtlasImage(GrMaskFormat format, unsigned int index) {
739 auto atlasManager = this->getAtlasManager();
740 if (!atlasManager) {
741 return nullptr;
742 }
743
744 unsigned int numActiveProxies;
745 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies);
746 if (index >= numActiveProxies || !proxies || !proxies[index]) {
747 return nullptr;
748 }
749
750 SkASSERT(proxies[index]->priv().isExact());
751 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID,
752 kPremul_SkAlphaType, proxies[index], nullptr));
753 return image;
754}
755
756void GrContextPriv::testingOnly_purgeAllUnlockedResources() {
757 fContext->fResourceCache->purgeAllUnlocked();
758}
759
760void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
761 fContext->flush();
Robert Phillips292a6b22019-02-14 14:49:02 -0500762 fContext->drawingManager()->testingOnly_removeOnFlushCallbackObject(cb);
Robert Phillipsdbaf3172019-02-06 15:12:53 -0500763}
764#endif