blob: 53ec06c2515c8c24ebc464ad7702623dde1d0ac8 [file] [log] [blame]
bsalomon@google.com27847de2011-02-22 20:59:41 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 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.
bsalomon@google.com27847de2011-02-22 20:59:41 +00006 */
7
bsalomon@google.com1fadb202011-12-12 16:10:08 +00008#include "GrContext.h"
robertphillips4fd74ae2016-08-03 14:26:53 -07009#include "GrContextPriv.h"
bsalomon682c2692015-05-22 14:01:46 -070010#include "GrContextOptions.h"
robertphillips77a2e522015-10-17 07:43:27 -070011#include "GrDrawingManager.h"
Brian Osman11052242016-10-27 14:47:55 -040012#include "GrRenderTargetContext.h"
bsalomon0ea80f42015-02-11 10:49:59 -080013#include "GrResourceCache.h"
bsalomond309e7a2015-04-30 14:18:54 -070014#include "GrResourceProvider.h"
Robert Phillipsc7635fa2016-10-28 13:25:24 -040015#include "GrRenderTargetProxy.h"
robertphillips@google.com72176b22012-05-23 13:19:12 +000016#include "GrSoftwarePathRenderer.h"
bsalomonafbf2d62014-09-30 12:18:44 -070017#include "GrSurfacePriv.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070018
bsalomon81beccc2014-10-13 12:32:55 -070019#include "SkConfig8888.h"
bsalomonf276ac52015-10-09 13:36:42 -070020#include "SkGrPriv.h"
joshualitt74417822015-08-07 11:42:16 -070021
bsalomonb8fea972016-02-16 07:34:17 -080022#include "batches/GrCopySurfaceBatch.h"
joshualitt5478d422014-11-14 16:00:38 -080023#include "effects/GrConfigConversionEffect.h"
brianosman2d1ee792016-05-05 12:24:31 -070024#include "effects/GrGammaEffect.h"
joshualitte8042922015-12-11 06:11:21 -080025#include "text/GrTextBlobCache.h"
joshualitt5478d422014-11-14 16:00:38 -080026
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000027#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
joshualitt1de610a2016-01-06 08:26:09 -080028#define ASSERT_SINGLE_OWNER \
29 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);)
robertphillips4fd74ae2016-08-03 14:26:53 -070030#define ASSERT_SINGLE_OWNER_PRIV \
31 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070032#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
33#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
34#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000035
robertphillipsea461502015-05-26 11:38:03 -070036////////////////////////////////////////////////////////////////////////////////
37
bsalomon682c2692015-05-22 14:01:46 -070038GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
39 GrContextOptions defaultOptions;
40 return Create(backend, backendContext, defaultOptions);
41}
bsalomonf28cff72015-05-22 12:25:41 -070042
bsalomon682c2692015-05-22 14:01:46 -070043GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
44 const GrContextOptions& options) {
halcanary385fe4d2015-08-26 13:07:48 -070045 GrContext* context = new GrContext;
bsalomon682c2692015-05-22 14:01:46 -070046
47 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000048 return context;
49 } else {
50 context->unref();
halcanary96fcdcc2015-08-27 07:41:13 -070051 return nullptr;
bsalomon@google.com27847de2011-02-22 20:59:41 +000052 }
bsalomon@google.com27847de2011-02-22 20:59:41 +000053}
54
joshualitt0acd0d32015-05-07 08:23:19 -070055static int32_t gNextID = 1;
56static int32_t next_id() {
57 int32_t id;
58 do {
59 id = sk_atomic_inc(&gNextID);
60 } while (id == SK_InvalidGenID);
61 return id;
62}
63
bsalomon682c2692015-05-22 14:01:46 -070064GrContext::GrContext() : fUniqueID(next_id()) {
halcanary96fcdcc2015-08-27 07:41:13 -070065 fGpu = nullptr;
66 fCaps = nullptr;
67 fResourceCache = nullptr;
68 fResourceProvider = nullptr;
halcanary96fcdcc2015-08-27 07:41:13 -070069 fBatchFontCache = nullptr;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000070}
71
bsalomon682c2692015-05-22 14:01:46 -070072bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
73 const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080074 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -070075 SkASSERT(!fGpu);
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000076
bsalomon682c2692015-05-22 14:01:46 -070077 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -070078 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000079 return false;
80 }
bsalomon69cfe952015-11-30 13:27:47 -080081 this->initCommon(options);
bsalomon33435572014-11-05 14:47:41 -080082 return true;
83}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000084
bsalomon69cfe952015-11-30 13:27:47 -080085void GrContext::initCommon(const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080086 ASSERT_SINGLE_OWNER
87
bsalomon76228632015-05-29 08:02:10 -070088 fCaps = SkRef(fGpu->caps());
halcanary385fe4d2015-08-26 13:07:48 -070089 fResourceCache = new GrResourceCache(fCaps);
joshualitt6d0872d2016-01-11 08:27:48 -080090 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +000091
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000092 fDidTestPMConversions = false;
93
Robert Phillipsf2361d22016-10-25 14:20:06 -040094 GrRenderTargetOpList::Options rtOpListOptions;
95 rtOpListOptions.fClipBatchToBounds = options.fClipBatchToBounds;
96 rtOpListOptions.fDrawBatchBounds = options.fDrawBatchBounds;
97 rtOpListOptions.fMaxBatchLookback = options.fMaxBatchLookback;
98 rtOpListOptions.fMaxBatchLookahead = options.fMaxBatchLookahead;
bsalomon6b2552f2016-09-15 13:50:26 -070099 GrPathRendererChain::Options prcOptions;
100 prcOptions.fDisableDistanceFieldRenderer = options.fDisableDistanceFieldPaths;
bsalomon39ef7fb2016-09-21 11:16:05 -0700101 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching;
102 prcOptions.fDisableAllPathRenderers = options.fForceSWPathMasks;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400103 fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions,
104 options.fImmediateMode, &fSingleOwner));
joshualitt7c3a2f82015-03-31 13:32:05 -0700105
106 // GrBatchFontCache will eventually replace GrFontCache
halcanary385fe4d2015-08-26 13:07:48 -0700107 fBatchFontCache = new GrBatchFontCache(this);
joshualittb7133be2015-04-08 09:08:31 -0700108
halcanary385fe4d2015-08-26 13:07:48 -0700109 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000110}
111
bsalomon@google.com27847de2011-02-22 20:59:41 +0000112GrContext::~GrContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800113 ASSERT_SINGLE_OWNER
114
robertphillipsea461502015-05-26 11:38:03 -0700115 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700116 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000117 return;
118 }
119
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000120 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000121
robertphillips77a2e522015-10-17 07:43:27 -0700122 fDrawingManager->cleanup();
robertphillips2334fb62015-06-17 05:43:33 -0700123
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000124 for (int i = 0; i < fCleanUpData.count(); ++i) {
125 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
126 }
127
halcanary385fe4d2015-08-26 13:07:48 -0700128 delete fResourceProvider;
129 delete fResourceCache;
130 delete fBatchFontCache;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000131
bsalomon@google.com205d4602011-04-25 12:43:45 +0000132 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700133 fCaps->unref();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000134}
135
bungeman6bd52842016-10-27 09:30:08 -0700136sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
bsalomon41b952c2016-03-11 06:46:33 -0800137 if (!fThreadSafeProxy) {
bungeman6bd52842016-10-27 09:30:08 -0700138 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(sk_ref_sp(fCaps), this->uniqueID()));
bsalomon41b952c2016-03-11 06:46:33 -0800139 }
bungeman6bd52842016-10-27 09:30:08 -0700140 return fThreadSafeProxy;
bsalomon41b952c2016-03-11 06:46:33 -0800141}
142
bsalomon2354f842014-07-28 13:48:36 -0700143void GrContext::abandonContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800144 ASSERT_SINGLE_OWNER
145
bsalomond309e7a2015-04-30 14:18:54 -0700146 fResourceProvider->abandon();
robertphillips0dfa62c2015-11-16 06:23:31 -0800147
148 // Need to abandon the drawing manager first so all the render targets
149 // will be released/forgotten before they too are abandoned.
150 fDrawingManager->abandon();
151
bsalomon@google.com205d4602011-04-25 12:43:45 +0000152 // abandon first to so destructors
153 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800154 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700155
bsalomon6e2aad42016-04-01 11:54:31 -0700156 fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
157
158 fBatchFontCache->freeAll();
bsalomon6e2aad42016-04-01 11:54:31 -0700159 fTextBlobCache->freeAll();
160}
161
162void GrContext::releaseResourcesAndAbandonContext() {
163 ASSERT_SINGLE_OWNER
164
165 fResourceProvider->abandon();
166
167 // Need to abandon the drawing manager first so all the render targets
168 // will be released/forgotten before they too are abandoned.
169 fDrawingManager->abandon();
170
171 // Release all resources in the backend 3D API.
172 fResourceCache->releaseAll();
173
174 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000175
joshualitt7c3a2f82015-03-31 13:32:05 -0700176 fBatchFontCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700177 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000178}
179
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000180void GrContext::resetContext(uint32_t state) {
joshualitt1de610a2016-01-06 08:26:09 -0800181 ASSERT_SINGLE_OWNER
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000182 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000183}
184
185void GrContext::freeGpuResources() {
joshualitt1de610a2016-01-06 08:26:09 -0800186 ASSERT_SINGLE_OWNER
187
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000188 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000189
joshualitt7c3a2f82015-03-31 13:32:05 -0700190 fBatchFontCache->freeAll();
robertphillips68737822015-10-29 12:12:21 -0700191
192 fDrawingManager->freeGpuResources();
bsalomon3033b9f2015-04-13 11:09:56 -0700193
194 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000195}
196
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000197void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800198 ASSERT_SINGLE_OWNER
199
bsalomon71cb0c22014-11-14 12:10:14 -0800200 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800201 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800202 }
203 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800204 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800205 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000206}
207
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000208////////////////////////////////////////////////////////////////////////////////
209
joshualitt0db6dfa2015-04-10 07:01:30 -0700210void GrContext::TextBlobCacheOverBudgetCB(void* data) {
211 SkASSERT(data);
Brian Osman11052242016-10-27 14:47:55 -0400212 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
213 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls
214 // to below the GrContext level, but this is not trivial because they call drawPath on
215 // SkGpuDevice.
joshualitt0db6dfa2015-04-10 07:01:30 -0700216 GrContext* context = reinterpret_cast<GrContext*>(data);
217 context->flush();
218}
219
bsalomon@google.com27847de2011-02-22 20:59:41 +0000220////////////////////////////////////////////////////////////////////////////////
221
bsalomonb77a9072016-09-07 10:02:04 -0700222void GrContext::flush() {
joshualitt1de610a2016-01-06 08:26:09 -0800223 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700224 RETURN_IF_ABANDONED
bsalomonb77a9072016-09-07 10:02:04 -0700225 fDrawingManager->flush();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000226}
227
bsalomon81beccc2014-10-13 12:32:55 -0700228bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
229 const void* inPixels, size_t outRowBytes, void* outPixels) {
230 SkSrcPixelInfo srcPI;
brianosman396fcdb2016-07-22 06:26:11 -0700231 if (!GrPixelConfigToColorType(srcConfig, &srcPI.fColorType)) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000232 return false;
233 }
bsalomon81beccc2014-10-13 12:32:55 -0700234 srcPI.fAlphaType = kUnpremul_SkAlphaType;
235 srcPI.fPixels = inPixels;
236 srcPI.fRowBytes = inRowBytes;
237
238 SkDstPixelInfo dstPI;
239 dstPI.fColorType = srcPI.fColorType;
240 dstPI.fAlphaType = kPremul_SkAlphaType;
241 dstPI.fPixels = outPixels;
242 dstPI.fRowBytes = outRowBytes;
243
244 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000245}
246
bsalomon81beccc2014-10-13 12:32:55 -0700247bool GrContext::writeSurfacePixels(GrSurface* surface,
248 int left, int top, int width, int height,
249 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
250 uint32_t pixelOpsFlags) {
joshualitt1de610a2016-01-06 08:26:09 -0800251 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800252 RETURN_FALSE_IF_ABANDONED
bsalomon6c6f6582015-09-10 08:12:46 -0700253 ASSERT_OWNED_RESOURCE(surface);
254 SkASSERT(surface);
joshualittbc907352016-01-13 06:45:40 -0800255 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels");
bsalomon6c6f6582015-09-10 08:12:46 -0700256
257 this->testPMConversionsIfNecessary(pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700258
bsalomone8d21e82015-07-16 08:23:13 -0700259 // Trim the params here so that if we wind up making a temporary surface it can be as small as
bsalomonf0674512015-07-28 13:26:15 -0700260 // necessary and because GrGpu::getWritePixelsInfo requires it.
bsalomone8d21e82015-07-16 08:23:13 -0700261 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
262 GrBytesPerPixel(srcConfig), &left, &top, &width,
263 &height, &buffer, &rowBytes)) {
264 return false;
265 }
266
bsalomonf0674512015-07-28 13:26:15 -0700267 bool applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700268 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
269 if (!GrPixelConfigIs8888(srcConfig)) {
270 return false;
271 }
bsalomonf0674512015-07-28 13:26:15 -0700272 applyPremulToSrc = true;
273 }
bsalomon636e8022015-07-29 06:08:46 -0700274
275 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
276 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
277 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
278 if (applyPremulToSrc && !this->didFailPMUPMConversionTest()) {
279 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
280 }
281
bsalomonf0674512015-07-28 13:26:15 -0700282 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
cblumeed828002016-02-16 13:00:01 -0800283 if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700284 &tempDrawInfo)) {
285 return false;
286 }
287
288 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
289 this->flush();
290 }
291
292 SkAutoTUnref<GrTexture> tempTexture;
293 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomoneae62002015-07-31 13:59:30 -0700294 tempTexture.reset(
295 this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
bsalomonf0674512015-07-28 13:26:15 -0700296 if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
297 return false;
298 }
299 }
300
301 // temp buffer for doing sw premul conversion, if needed.
302 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
303 if (tempTexture) {
bungeman06ca8ec2016-06-09 08:01:03 -0700304 sk_sp<GrFragmentProcessor> fp;
bsalomonf0674512015-07-28 13:26:15 -0700305 SkMatrix textureMatrix;
306 textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
bsalomonf0674512015-07-28 13:26:15 -0700307 if (applyPremulToSrc) {
bungeman06ca8ec2016-06-09 08:01:03 -0700308 fp = this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwizzle, textureMatrix);
bsalomonf0674512015-07-28 13:26:15 -0700309 // If premultiplying was the only reason for the draw, fall back to a straight write.
310 if (!fp) {
311 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
halcanary96fcdcc2015-08-27 07:41:13 -0700312 tempTexture.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700313 }
314 } else {
315 applyPremulToSrc = false;
316 }
317 }
318 if (tempTexture) {
319 if (!fp) {
bungeman06ca8ec2016-06-09 08:01:03 -0700320 fp = GrConfigConversionEffect::Make(tempTexture, tempDrawInfo.fSwizzle,
321 GrConfigConversionEffect::kNone_PMConversion,
322 textureMatrix);
bsalomonf0674512015-07-28 13:26:15 -0700323 if (!fp) {
324 return false;
325 }
326 }
327 GrRenderTarget* renderTarget = surface->asRenderTarget();
328 SkASSERT(renderTarget);
329 if (tempTexture->surfacePriv().hasPendingIO()) {
330 this->flush();
331 }
332 if (applyPremulToSrc) {
333 size_t tmpRowBytes = 4 * width;
334 tmpPixels.reset(width * height);
335 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
336 tmpPixels.get())) {
337 return false;
338 }
339 rowBytes = tmpRowBytes;
340 buffer = tmpPixels.get();
341 applyPremulToSrc = false;
342 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700343 if (!fGpu->writePixels(tempTexture, 0, 0, width, height,
bsalomon6c9cd552016-01-22 07:17:34 -0800344 tempDrawInfo.fWriteConfig, buffer,
bsalomon6cb3cbe2015-07-30 07:34:27 -0700345 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700346 return false;
347 }
348 SkMatrix matrix;
349 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
brianosmandfe4f2e2016-07-21 13:28:36 -0700350 // TODO: Need to decide the semantics of this function for color spaces. Do we support
351 // conversion from a passed-in color space? For now, specifying nullptr means that this
352 // path will do no conversion, so it will match the behavior of the non-draw path.
Brian Osman11052242016-10-27 14:47:55 -0400353 sk_sp<GrRenderTargetContext> renderTargetContext(
354 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(renderTarget),
355 nullptr));
356 if (!renderTargetContext) {
bsalomonf0674512015-07-28 13:26:15 -0700357 return false;
358 }
egdanielc4b72722015-11-23 13:20:41 -0800359 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700360 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700361 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700362 paint.setAllowSRGBInputs(true);
bsalomonf0674512015-07-28 13:26:15 -0700363 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Osman11052242016-10-27 14:47:55 -0400364 renderTargetContext->drawRect(GrNoClip(), paint, matrix, rect, nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700365
366 if (kFlushWrites_PixelOp & pixelOpsFlags) {
367 this->flushSurfaceWrites(surface);
368 }
369 }
370 }
371 if (!tempTexture) {
bsalomonf0674512015-07-28 13:26:15 -0700372 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700373 size_t tmpRowBytes = 4 * width;
374 tmpPixels.reset(width * height);
375 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
376 tmpPixels.get())) {
377 return false;
378 }
379 rowBytes = tmpRowBytes;
380 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700381 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700382 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700383 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700384 }
bsalomon81beccc2014-10-13 12:32:55 -0700385 return true;
386}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000387
bsalomone8d21e82015-07-16 08:23:13 -0700388bool GrContext::readSurfacePixels(GrSurface* src,
389 int left, int top, int width, int height,
390 GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
391 uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800392 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800393 RETURN_FALSE_IF_ABANDONED
bsalomone8d21e82015-07-16 08:23:13 -0700394 ASSERT_OWNED_RESOURCE(src);
395 SkASSERT(src);
joshualittbc907352016-01-13 06:45:40 -0800396 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700397
bsalomon6c6f6582015-09-10 08:12:46 -0700398 this->testPMConversionsIfNecessary(flags);
399 SkAutoMutexAcquire ama(fReadPixelsMutex);
400
bsalomone8d21e82015-07-16 08:23:13 -0700401 // Adjust the params so that if we wind up using an intermediate surface we've already done
402 // all the trimming and the temporary can be the min size required.
403 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
404 GrBytesPerPixel(dstConfig), &left,
405 &top, &width, &height, &buffer, &rowBytes)) {
406 return false;
407 }
408
409 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000410 this->flush();
411 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000412
bsalomone8d21e82015-07-16 08:23:13 -0700413 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
bsalomon@google.com9c680582013-02-06 18:17:50 +0000414 if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
bsalomon39826022015-07-23 08:07:21 -0700415 // The unpremul flag is only allowed for 8888 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000416 return false;
417 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000418
bsalomon636e8022015-07-29 06:08:46 -0700419 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
420 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
421 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
422 if (unpremul && !this->didFailPMUPMConversionTest()) {
423 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
424 }
425
bsalomon39826022015-07-23 08:07:21 -0700426 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
427 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference,
428 &tempDrawInfo)) {
429 return false;
430 }
bsalomon191bcc02014-11-14 11:31:13 -0800431
bsalomon6cb3cbe2015-07-30 07:34:27 -0700432 SkAutoTUnref<GrSurface> surfaceToRead(SkRef(src));
bsalomon39826022015-07-23 08:07:21 -0700433 bool didTempDraw = false;
434 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomonb117ff12016-07-19 07:24:40 -0700435 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) {
bsalomon39826022015-07-23 08:07:21 -0700436 // We only respect this when the entire src is being read. Otherwise we can trigger too
437 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700438 if (width != src->width() || height != src->height()) {
bsalomonb117ff12016-07-19 07:24:40 -0700439 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox;
bsalomon39826022015-07-23 08:07:21 -0700440 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000441 }
brianosmandfe4f2e2016-07-21 13:28:36 -0700442 // TODO: Need to decide the semantics of this function for color spaces. Do we support
443 // conversion to a passed-in color space? For now, specifying nullptr means that this
444 // path will do no conversion, so it will match the behavior of the non-draw path.
Brian Osman693a5402016-10-27 15:13:22 -0400445 sk_sp<GrRenderTargetContext> tempRTC = this->makeRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400446 tempDrawInfo.fTempSurfaceFit,
bsalomonb117ff12016-07-19 07:24:40 -0700447 tempDrawInfo.fTempSurfaceDesc.fWidth,
448 tempDrawInfo.fTempSurfaceDesc.fHeight,
449 tempDrawInfo.fTempSurfaceDesc.fConfig,
brianosmandfe4f2e2016-07-21 13:28:36 -0700450 nullptr,
bsalomonb117ff12016-07-19 07:24:40 -0700451 tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
452 tempDrawInfo.fTempSurfaceDesc.fOrigin);
Brian Osman693a5402016-10-27 15:13:22 -0400453 if (tempRTC) {
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000454 SkMatrix textureMatrix;
bsalomon39826022015-07-23 08:07:21 -0700455 textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000456 textureMatrix.postIDiv(src->width(), src->height());
bungeman06ca8ec2016-06-09 08:01:03 -0700457 sk_sp<GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000458 if (unpremul) {
bungeman06ca8ec2016-06-09 08:01:03 -0700459 fp = this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle,
460 textureMatrix);
joshualittb0a8a372014-09-23 09:50:21 -0700461 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000462 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon39826022015-07-23 08:07:21 -0700463 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
464 // We only wanted to do the draw in order to perform the unpremul so don't
465 // bother.
Brian Osman693a5402016-10-27 15:13:22 -0400466 tempRTC.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000467 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000468 }
Brian Osman693a5402016-10-27 15:13:22 -0400469 if (!fp && tempRTC) {
bungeman06ca8ec2016-06-09 08:01:03 -0700470 fp = GrConfigConversionEffect::Make(src->asTexture(), tempDrawInfo.fSwizzle,
471 GrConfigConversionEffect::kNone_PMConversion,
472 textureMatrix);
bsalomon39826022015-07-23 08:07:21 -0700473 }
474 if (fp) {
egdanielc4b72722015-11-23 13:20:41 -0800475 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700476 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700477 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700478 paint.setAllowSRGBInputs(true);
bsalomon39826022015-07-23 08:07:21 -0700479 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Osman693a5402016-10-27 15:13:22 -0400480 tempRTC->drawRect(GrNoClip(), paint, SkMatrix::I(), rect, nullptr);
481 surfaceToRead.reset(tempRTC->asTexture().release());
bsalomon39826022015-07-23 08:07:21 -0700482 left = 0;
483 top = 0;
484 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000485 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000486 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000487 }
joshualitt5c55fef2014-10-31 14:04:35 -0700488
bsalomon39826022015-07-23 08:07:21 -0700489 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000490 return false;
491 }
bsalomon39826022015-07-23 08:07:21 -0700492 GrPixelConfig configToRead = dstConfig;
493 if (didTempDraw) {
bsalomon6cb3cbe2015-07-30 07:34:27 -0700494 this->flushSurfaceWrites(surfaceToRead);
bsalomon6c9cd552016-01-22 07:17:34 -0800495 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700496 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700497 if (!fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead, buffer,
498 rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700499 return false;
500 }
501
502 // Perform umpremul conversion if we weren't able to perform it as a draw.
503 if (unpremul) {
reed@google.com7111d462014-03-25 16:20:24 +0000504 SkDstPixelInfo dstPI;
brianosman396fcdb2016-07-22 06:26:11 -0700505 if (!GrPixelConfigToColorType(dstConfig, &dstPI.fColorType)) {
reed@google.com7111d462014-03-25 16:20:24 +0000506 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000507 }
reed@google.com7111d462014-03-25 16:20:24 +0000508 dstPI.fAlphaType = kUnpremul_SkAlphaType;
509 dstPI.fPixels = buffer;
510 dstPI.fRowBytes = rowBytes;
511
512 SkSrcPixelInfo srcPI;
bsalomon39826022015-07-23 08:07:21 -0700513 srcPI.fColorType = dstPI.fColorType;
reed@google.com7111d462014-03-25 16:20:24 +0000514 srcPI.fAlphaType = kPremul_SkAlphaType;
515 srcPI.fPixels = buffer;
516 srcPI.fRowBytes = rowBytes;
517
518 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000519 }
520 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000521}
522
bsalomonc49e8682015-06-30 11:37:35 -0700523void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800524 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800525 RETURN_IF_ABANDONED
bsalomon87a94eb2014-11-03 14:28:32 -0800526 SkASSERT(surface);
527 ASSERT_OWNED_RESOURCE(surface);
bsalomon6a2b1942016-09-08 11:28:59 -0700528 fDrawingManager->prepareSurfaceForExternalIO(surface);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000529}
530
bsalomonb8fea972016-02-16 07:34:17 -0800531bool GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
532 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800533 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800534 RETURN_FALSE_IF_ABANDONED
joshualittbc907352016-01-13 06:45:40 -0800535 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::copySurface");
536
robertphillipsea461502015-05-26 11:38:03 -0700537 if (!src || !dst) {
bsalomonb8fea972016-02-16 07:34:17 -0800538 return false;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000539 }
bsalomone3d4bf22014-09-23 09:15:03 -0700540 ASSERT_OWNED_RESOURCE(src);
junov2bb52102014-09-29 10:18:59 -0700541 ASSERT_OWNED_RESOURCE(dst);
Brian Salomon34a98952014-09-24 11:41:24 -0400542
robertphillipsea461502015-05-26 11:38:03 -0700543 if (!dst->asRenderTarget()) {
bsalomonb8fea972016-02-16 07:34:17 -0800544 SkIRect clippedSrcRect;
545 SkIPoint clippedDstPoint;
546 if (!GrCopySurfaceBatch::ClipSrcRectAndDstPoint(dst, src, srcRect, dstPoint,
547 &clippedSrcRect, &clippedDstPoint)) {
548 return false;
549 }
Brian Osman11052242016-10-27 14:47:55 -0400550 // If we don't have an RT for the dst then we won't have a GrRenderTargetContext to insert
bsalomonb8fea972016-02-16 07:34:17 -0800551 // the copy surface into. In the future we plan to have a more limited Context type
Brian Osman11052242016-10-27 14:47:55 -0400552 // (GrCopyContext?) that has the subset of GrRenderTargetContext operations that should be
bsalomonb8fea972016-02-16 07:34:17 -0800553 // allowed on textures that aren't render targets.
554 // For now we just flush any writes to the src and issue an immediate copy to the dst.
555 src->flushWrites();
556 return fGpu->copySurface(dst, src, clippedSrcRect, clippedDstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700557 }
Brian Osman11052242016-10-27 14:47:55 -0400558 sk_sp<GrRenderTargetContext> renderTargetContext(
559 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(dst->asRenderTarget()),
560 nullptr));
561 if (!renderTargetContext) {
bsalomonb8fea972016-02-16 07:34:17 -0800562 return false;
bsalomonf80bfed2014-10-07 05:56:02 -0700563 }
kjlubick0eed9452016-02-11 12:05:24 -0800564
Brian Osman11052242016-10-27 14:47:55 -0400565 if (!renderTargetContext->copySurface(src, srcRect, dstPoint)) {
bsalomonb8fea972016-02-16 07:34:17 -0800566 return false;
kjlubick0eed9452016-02-11 12:05:24 -0800567 }
bsalomonb8fea972016-02-16 07:34:17 -0800568 return true;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000569}
570
bsalomonf80bfed2014-10-07 05:56:02 -0700571void GrContext::flushSurfaceWrites(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800572 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800573 RETURN_IF_ABANDONED
bsalomonf80bfed2014-10-07 05:56:02 -0700574 if (surface->surfacePriv().hasPendingWrite()) {
575 this->flush();
576 }
577}
578
ajuma95243eb2016-08-24 08:19:02 -0700579void GrContext::flushSurfaceIO(GrSurface* surface) {
580 ASSERT_SINGLE_OWNER
581 RETURN_IF_ABANDONED
582 if (surface->surfacePriv().hasPendingIO()) {
583 this->flush();
584 }
585}
586
bsalomon@google.com27847de2011-02-22 20:59:41 +0000587////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000588int GrContext::getRecommendedSampleCount(GrPixelConfig config,
589 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800590 ASSERT_SINGLE_OWNER
591
bsalomon76228632015-05-29 08:02:10 -0700592 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000593 return 0;
594 }
595 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700596 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000597 if (dpi >= 250.0f) {
598 chosenSampleCount = 4;
599 } else {
600 chosenSampleCount = 16;
601 }
602 }
egdanieleed519e2016-01-15 11:36:18 -0800603 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000604}
605
Brian Osman11052242016-10-27 14:47:55 -0400606sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext(
607 sk_sp<GrRenderTarget> rt,
608 sk_sp<SkColorSpace> colorSpace,
609 const SkSurfaceProps* surfaceProps) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700610 ASSERT_SINGLE_OWNER_PRIV
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400611
612 sk_sp<GrRenderTargetProxy> rtp(GrRenderTargetProxy::Make(*fContext->caps(), std::move(rt)));
613
614 return this->drawingManager()->makeRenderTargetContext(std::move(rtp),
615 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400616 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700617}
robertphillips77a2e522015-10-17 07:43:27 -0700618
Brian Osman11052242016-10-27 14:47:55 -0400619sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
620 const GrBackendTextureDesc& desc,
621 sk_sp<SkColorSpace> colorSpace,
622 const SkSurfaceProps* props,
623 GrWrapOwnership ownership) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700624 ASSERT_SINGLE_OWNER_PRIV
625 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
626
627 sk_sp<GrSurface> surface(fContext->textureProvider()->wrapBackendTexture(desc, ownership));
628 if (!surface) {
629 return nullptr;
630 }
631
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400632 sk_sp<GrRenderTargetProxy> rtp(GrRenderTargetProxy::Make(*fContext->caps(),
633 sk_ref_sp(surface->asRenderTarget())));
634
635 return this->drawingManager()->makeRenderTargetContext(std::move(rtp),
Brian Osman11052242016-10-27 14:47:55 -0400636 std::move(colorSpace), props);
robertphillips4fd74ae2016-08-03 14:26:53 -0700637}
638
Brian Osman11052242016-10-27 14:47:55 -0400639sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
robertphillips4fd74ae2016-08-03 14:26:53 -0700640 const GrBackendRenderTargetDesc& desc,
641 sk_sp<SkColorSpace> colorSpace,
642 const SkSurfaceProps* surfaceProps) {
643 ASSERT_SINGLE_OWNER_PRIV
644
645 sk_sp<GrRenderTarget> rt(fContext->textureProvider()->wrapBackendRenderTarget(desc));
646 if (!rt) {
647 return nullptr;
648 }
649
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400650 sk_sp<GrRenderTargetProxy> rtp(GrRenderTargetProxy::Make(*fContext->caps(), std::move(rt)));
651
652 return this->drawingManager()->makeRenderTargetContext(std::move(rtp),
653 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400654 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700655}
656
Brian Osman11052242016-10-27 14:47:55 -0400657sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
egdaniela95d46b2016-08-15 08:06:29 -0700658 const GrBackendTextureDesc& desc,
robertphillips4fd74ae2016-08-03 14:26:53 -0700659 sk_sp<SkColorSpace> colorSpace,
660 const SkSurfaceProps* surfaceProps) {
661 ASSERT_SINGLE_OWNER_PRIV
662 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
663
664 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
665 if (!surface) {
666 return nullptr;
667 }
668
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400669 sk_sp<GrRenderTargetProxy> rtp(GrRenderTargetProxy::Make(*fContext->caps(),
670 sk_ref_sp(surface->asRenderTarget())));
671
672 return this->drawingManager()->makeRenderTargetContext(std::move(rtp),
673 std::move(colorSpace),
674 surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700675}
676
robertphillips48fde9c2016-09-06 05:20:20 -0700677static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
678 static const GrPixelConfig kFallback[] = {
679 kUnknown_GrPixelConfig, // kUnknown_GrPixelConfig
680 kRGBA_8888_GrPixelConfig, // kAlpha_8_GrPixelConfig
681 kUnknown_GrPixelConfig, // kIndex_8_GrPixelConfig
682 kRGBA_8888_GrPixelConfig, // kRGB_565_GrPixelConfig
683 kRGBA_8888_GrPixelConfig, // kRGBA_4444_GrPixelConfig
684 kUnknown_GrPixelConfig, // kRGBA_8888_GrPixelConfig
685 kRGBA_8888_GrPixelConfig, // kBGRA_8888_GrPixelConfig
686 kUnknown_GrPixelConfig, // kSRGBA_8888_GrPixelConfig
687 kSRGBA_8888_GrPixelConfig, // kSBGRA_8888_GrPixelConfig
688 kUnknown_GrPixelConfig, // kETC1_GrPixelConfig
689 kUnknown_GrPixelConfig, // kLATC_GrPixelConfig
690 kUnknown_GrPixelConfig, // kR11_EAC_GrPixelConfig
691 kUnknown_GrPixelConfig, // kASTC_12x12_GrPixelConfig
692 kUnknown_GrPixelConfig, // kRGBA_float_GrPixelConfig
693 kRGBA_half_GrPixelConfig, // kAlpha_half_GrPixelConfig
694 kUnknown_GrPixelConfig, // kRGBA_half_GrPixelConfig
695 };
696 return kFallback[config];
697
698 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
699 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
700 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
701 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
702 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
703 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
704 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
705 GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig);
706 GR_STATIC_ASSERT(8 == kSBGRA_8888_GrPixelConfig);
707 GR_STATIC_ASSERT(9 == kETC1_GrPixelConfig);
708 GR_STATIC_ASSERT(10 == kLATC_GrPixelConfig);
709 GR_STATIC_ASSERT(11 == kR11_EAC_GrPixelConfig);
710 GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig);
711 GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig);
712 GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig);
713 GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig);
714 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFallback) == kGrPixelConfigCnt);
715}
716
Brian Osman11052242016-10-27 14:47:55 -0400717sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContextWithFallback(
718 SkBackingFit fit,
719 int width, int height,
720 GrPixelConfig config,
721 sk_sp<SkColorSpace> colorSpace,
722 int sampleCnt,
723 GrSurfaceOrigin origin,
724 const SkSurfaceProps* surfaceProps,
725 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700726 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
727 config = GrPixelConfigFallback(config);
728 }
729
Brian Osman11052242016-10-27 14:47:55 -0400730 return this->makeRenderTargetContext(fit, width, height, config, std::move(colorSpace),
731 sampleCnt, origin, surfaceProps, budgeted);
robertphillips48fde9c2016-09-06 05:20:20 -0700732}
733
Brian Osman11052242016-10-27 14:47:55 -0400734sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContext(SkBackingFit fit,
735 int width, int height,
736 GrPixelConfig config,
737 sk_sp<SkColorSpace> colorSpace,
738 int sampleCnt,
739 GrSurfaceOrigin origin,
740 const SkSurfaceProps* surfaceProps,
741 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700742 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
743 return nullptr;
744 }
745
robertphillipsd4c741e2016-04-28 09:55:15 -0700746 GrSurfaceDesc desc;
747 desc.fFlags = kRenderTarget_GrSurfaceFlag;
748 desc.fOrigin = origin;
749 desc.fWidth = width;
750 desc.fHeight = height;
751 desc.fConfig = config;
752 desc.fSampleCnt = sampleCnt;
753
754 sk_sp<GrTexture> tex;
robertphillips76948d42016-05-04 12:47:41 -0700755 if (SkBackingFit::kExact == fit) {
robertphillipsca6eafc2016-05-17 09:57:46 -0700756 tex.reset(this->textureProvider()->createTexture(desc, budgeted));
robertphillipsd4c741e2016-04-28 09:55:15 -0700757 } else {
758 tex.reset(this->textureProvider()->createApproxTexture(desc));
759 }
760 if (!tex) {
761 return nullptr;
762 }
763
Brian Osman11052242016-10-27 14:47:55 -0400764 sk_sp<GrRenderTargetContext> renderTargetContext(
765 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(tex->asRenderTarget()),
robertphillips6738c702016-07-27 12:13:51 -0700766 std::move(colorSpace), surfaceProps));
Brian Osman11052242016-10-27 14:47:55 -0400767 if (!renderTargetContext) {
robertphillipsd4c741e2016-04-28 09:55:15 -0700768 return nullptr;
769 }
770
Brian Osman11052242016-10-27 14:47:55 -0400771 return renderTargetContext;
robertphillipsd4c741e2016-04-28 09:55:15 -0700772}
773
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400774sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext(
775 SkBackingFit fit,
776 int width, int height,
777 GrPixelConfig config,
778 sk_sp<SkColorSpace> colorSpace,
779 int sampleCnt,
780 GrSurfaceOrigin origin,
781 const SkSurfaceProps* surfaceProps,
782 SkBudgeted budgeted) {
783 GrSurfaceDesc desc;
784 desc.fFlags = kRenderTarget_GrSurfaceFlag;
785 desc.fOrigin = origin;
786 desc.fWidth = width;
787 desc.fHeight = height;
788 desc.fConfig = config;
789 desc.fSampleCnt = sampleCnt;
790
791 sk_sp<GrRenderTargetProxy> rtp = GrRenderTargetProxy::Make(*this->caps(), desc, fit, budgeted);
792
793 return fDrawingManager->makeRenderTargetContext(std::move(rtp),
794 std::move(colorSpace),
795 surfaceProps);
796}
797
joshualitt1de610a2016-01-06 08:26:09 -0800798bool GrContext::abandoned() const {
799 ASSERT_SINGLE_OWNER
robertphillips7761d612016-05-16 09:14:53 -0700800 return fDrawingManager->wasAbandoned();
robertphillips77a2e522015-10-17 07:43:27 -0700801}
802
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000803namespace {
804void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
805 GrConfigConversionEffect::PMConversion pmToUPM;
806 GrConfigConversionEffect::PMConversion upmToPM;
807 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
808 *pmToUPMValue = pmToUPM;
809 *upmToPMValue = upmToPM;
810}
811}
812
bsalomon6c6f6582015-09-10 08:12:46 -0700813void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800814 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700815 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) {
816 SkAutoMutexAcquire ama(fTestPMConversionsMutex);
817 if (!fDidTestPMConversions) {
818 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
819 fDidTestPMConversions = true;
820 }
821 }
822}
823
bungeman06ca8ec2016-06-09 08:01:03 -0700824sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800825 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700826 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800827 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700828 // We should have already called this->testPMConversionsIfNecessary().
829 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000830 GrConfigConversionEffect::PMConversion pmToUPM =
831 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
832 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
bungeman06ca8ec2016-06-09 08:01:03 -0700833 return GrConfigConversionEffect::Make(texture, swizzle, pmToUPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000834 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700835 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000836 }
837}
838
bungeman06ca8ec2016-06-09 08:01:03 -0700839sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800840 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700841 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800842 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700843 // We should have already called this->testPMConversionsIfNecessary().
844 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000845 GrConfigConversionEffect::PMConversion upmToPM =
846 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
847 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
bungeman06ca8ec2016-06-09 08:01:03 -0700848 return GrConfigConversionEffect::Make(texture, swizzle, upmToPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000849 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700850 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000851 }
852}
853
bsalomon636e8022015-07-29 06:08:46 -0700854bool GrContext::didFailPMUPMConversionTest() const {
joshualitt1de610a2016-01-06 08:26:09 -0800855 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700856 // We should have already called this->testPMConversionsIfNecessary().
857 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700858 // The PM<->UPM tests fail or succeed together so we only need to check one.
bsalomon6c6f6582015-09-10 08:12:46 -0700859 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion;
bsalomon636e8022015-07-29 06:08:46 -0700860}
861
bsalomon37f9a262015-02-02 13:00:10 -0800862//////////////////////////////////////////////////////////////////////////////
863
864void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800865 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800866 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800867 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800868 }
869 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800870 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800871 }
872}
873
874void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800875 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800876 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800877}
878
ericrk0a5fa482015-09-15 14:16:10 -0700879//////////////////////////////////////////////////////////////////////////////
880
881void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800882 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700883 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
884}