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