blob: 3f4d2fa95913a066f2eb8719cf375e97780af159 [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"
robertphillipsea461502015-05-26 11:38:03 -070012#include "GrDrawContext.h"
bsalomon0ea80f42015-02-11 10:49:59 -080013#include "GrResourceCache.h"
bsalomond309e7a2015-04-30 14:18:54 -070014#include "GrResourceProvider.h"
robertphillips@google.com72176b22012-05-23 13:19:12 +000015#include "GrSoftwarePathRenderer.h"
bsalomonafbf2d62014-09-30 12:18:44 -070016#include "GrSurfacePriv.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070017
bsalomon81beccc2014-10-13 12:32:55 -070018#include "SkConfig8888.h"
bsalomonf276ac52015-10-09 13:36:42 -070019#include "SkGrPriv.h"
joshualitt74417822015-08-07 11:42:16 -070020
bsalomonb8fea972016-02-16 07:34:17 -080021#include "batches/GrCopySurfaceBatch.h"
joshualitt5478d422014-11-14 16:00:38 -080022#include "effects/GrConfigConversionEffect.h"
brianosman2d1ee792016-05-05 12:24:31 -070023#include "effects/GrGammaEffect.h"
joshualitte8042922015-12-11 06:11:21 -080024#include "text/GrTextBlobCache.h"
joshualitt5478d422014-11-14 16:00:38 -080025
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000026#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
joshualitt1de610a2016-01-06 08:26:09 -080027#define ASSERT_SINGLE_OWNER \
28 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);)
robertphillips4fd74ae2016-08-03 14:26:53 -070029#define ASSERT_SINGLE_OWNER_PRIV \
30 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070031#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
32#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
33#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000034
robertphillipsea461502015-05-26 11:38:03 -070035////////////////////////////////////////////////////////////////////////////////
36
bsalomon682c2692015-05-22 14:01:46 -070037GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
38 GrContextOptions defaultOptions;
39 return Create(backend, backendContext, defaultOptions);
40}
bsalomonf28cff72015-05-22 12:25:41 -070041
bsalomon682c2692015-05-22 14:01:46 -070042GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
43 const GrContextOptions& options) {
halcanary385fe4d2015-08-26 13:07:48 -070044 GrContext* context = new GrContext;
bsalomon682c2692015-05-22 14:01:46 -070045
46 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000047 return context;
48 } else {
49 context->unref();
halcanary96fcdcc2015-08-27 07:41:13 -070050 return nullptr;
bsalomon@google.com27847de2011-02-22 20:59:41 +000051 }
bsalomon@google.com27847de2011-02-22 20:59:41 +000052}
53
joshualitt0acd0d32015-05-07 08:23:19 -070054static int32_t gNextID = 1;
55static int32_t next_id() {
56 int32_t id;
57 do {
58 id = sk_atomic_inc(&gNextID);
59 } while (id == SK_InvalidGenID);
60 return id;
61}
62
bsalomon682c2692015-05-22 14:01:46 -070063GrContext::GrContext() : fUniqueID(next_id()) {
halcanary96fcdcc2015-08-27 07:41:13 -070064 fGpu = nullptr;
65 fCaps = nullptr;
66 fResourceCache = nullptr;
67 fResourceProvider = nullptr;
halcanary96fcdcc2015-08-27 07:41:13 -070068 fBatchFontCache = nullptr;
bsalomonf21dab92014-11-13 13:33:28 -080069 fFlushToReduceCacheSize = false;
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);
bsalomon0ea80f42015-02-11 10:49:59 -080090 fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
joshualitt6d0872d2016-01-11 08:27:48 -080091 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +000092
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000093 fDidTestPMConversions = false;
94
bsalomon69cfe952015-11-30 13:27:47 -080095 GrDrawTarget::Options dtOptions;
96 dtOptions.fClipBatchToBounds = options.fClipBatchToBounds;
bsalomon6dea83f2015-12-03 12:58:06 -080097 dtOptions.fDrawBatchBounds = options.fDrawBatchBounds;
bsalomon489147c2015-12-14 12:13:09 -080098 dtOptions.fMaxBatchLookback = options.fMaxBatchLookback;
bsalomonaecc0182016-03-07 11:50:44 -080099 dtOptions.fMaxBatchLookahead = options.fMaxBatchLookahead;
joshualittde8dc7e2016-01-08 10:09:13 -0800100 fDrawingManager.reset(new GrDrawingManager(this, dtOptions, &fSingleOwner));
joshualitt7c3a2f82015-03-31 13:32:05 -0700101
102 // GrBatchFontCache will eventually replace GrFontCache
halcanary385fe4d2015-08-26 13:07:48 -0700103 fBatchFontCache = new GrBatchFontCache(this);
joshualittb7133be2015-04-08 09:08:31 -0700104
halcanary385fe4d2015-08-26 13:07:48 -0700105 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000106}
107
bsalomon@google.com27847de2011-02-22 20:59:41 +0000108GrContext::~GrContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800109 ASSERT_SINGLE_OWNER
110
robertphillipsea461502015-05-26 11:38:03 -0700111 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700112 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000113 return;
114 }
115
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000116 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000117
robertphillips77a2e522015-10-17 07:43:27 -0700118 fDrawingManager->cleanup();
robertphillips2334fb62015-06-17 05:43:33 -0700119
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000120 for (int i = 0; i < fCleanUpData.count(); ++i) {
121 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
122 }
123
halcanary385fe4d2015-08-26 13:07:48 -0700124 delete fResourceProvider;
125 delete fResourceCache;
126 delete fBatchFontCache;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000127
bsalomon@google.com205d4602011-04-25 12:43:45 +0000128 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700129 fCaps->unref();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000130}
131
bsalomon41b952c2016-03-11 06:46:33 -0800132GrContextThreadSafeProxy* GrContext::threadSafeProxy() {
133 if (!fThreadSafeProxy) {
134 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(fCaps, this->uniqueID()));
135 }
136 return SkRef(fThreadSafeProxy.get());
137}
138
bsalomon2354f842014-07-28 13:48:36 -0700139void GrContext::abandonContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800140 ASSERT_SINGLE_OWNER
141
bsalomond309e7a2015-04-30 14:18:54 -0700142 fResourceProvider->abandon();
robertphillips0dfa62c2015-11-16 06:23:31 -0800143
144 // Need to abandon the drawing manager first so all the render targets
145 // will be released/forgotten before they too are abandoned.
146 fDrawingManager->abandon();
147
bsalomon@google.com205d4602011-04-25 12:43:45 +0000148 // abandon first to so destructors
149 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800150 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700151
bsalomon6e2aad42016-04-01 11:54:31 -0700152 fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
153
154 fBatchFontCache->freeAll();
bsalomon6e2aad42016-04-01 11:54:31 -0700155 fTextBlobCache->freeAll();
156}
157
158void GrContext::releaseResourcesAndAbandonContext() {
159 ASSERT_SINGLE_OWNER
160
161 fResourceProvider->abandon();
162
163 // Need to abandon the drawing manager first so all the render targets
164 // will be released/forgotten before they too are abandoned.
165 fDrawingManager->abandon();
166
167 // Release all resources in the backend 3D API.
168 fResourceCache->releaseAll();
169
170 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000171
joshualitt7c3a2f82015-03-31 13:32:05 -0700172 fBatchFontCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700173 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000174}
175
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000176void GrContext::resetContext(uint32_t state) {
joshualitt1de610a2016-01-06 08:26:09 -0800177 ASSERT_SINGLE_OWNER
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000178 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000179}
180
181void GrContext::freeGpuResources() {
joshualitt1de610a2016-01-06 08:26:09 -0800182 ASSERT_SINGLE_OWNER
183
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000184 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000185
joshualitt7c3a2f82015-03-31 13:32:05 -0700186 fBatchFontCache->freeAll();
robertphillips68737822015-10-29 12:12:21 -0700187
188 fDrawingManager->freeGpuResources();
bsalomon3033b9f2015-04-13 11:09:56 -0700189
190 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000191}
192
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000193void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800194 ASSERT_SINGLE_OWNER
195
bsalomon71cb0c22014-11-14 12:10:14 -0800196 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800197 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800198 }
199 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800200 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800201 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000202}
203
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000204////////////////////////////////////////////////////////////////////////////////
205
bsalomon71cb0c22014-11-14 12:10:14 -0800206void GrContext::OverBudgetCB(void* data) {
bsalomon66a450f2014-11-13 13:19:10 -0800207 SkASSERT(data);
bsalomonf21dab92014-11-13 13:33:28 -0800208
bsalomon66a450f2014-11-13 13:19:10 -0800209 GrContext* context = reinterpret_cast<GrContext*>(data);
bsalomonf21dab92014-11-13 13:33:28 -0800210
joshualittb542bae2015-07-28 09:58:39 -0700211 // Flush the GrBufferedDrawTarget to possibly free up some textures
bsalomonf21dab92014-11-13 13:33:28 -0800212 context->fFlushToReduceCacheSize = true;
commit-bot@chromium.orgcae27fe2013-07-10 10:14:35 +0000213}
214
joshualitt0db6dfa2015-04-10 07:01:30 -0700215void GrContext::TextBlobCacheOverBudgetCB(void* data) {
216 SkASSERT(data);
217
218 // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
219 // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move
220 // drawText calls to below the GrContext level, but this is not trivial because they call
221 // drawPath on SkGpuDevice
222 GrContext* context = reinterpret_cast<GrContext*>(data);
223 context->flush();
224}
225
bsalomon@google.com27847de2011-02-22 20:59:41 +0000226////////////////////////////////////////////////////////////////////////////////
227
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000228void GrContext::flush(int flagsBitfield) {
joshualitt1de610a2016-01-06 08:26:09 -0800229 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700230 RETURN_IF_ABANDONED
bsalomondc438982016-08-31 11:53:49 -0700231 bool flushed = false;
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000232 if (kDiscard_FlushBit & flagsBitfield) {
robertphillips77a2e522015-10-17 07:43:27 -0700233 fDrawingManager->reset();
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000234 } else {
bsalomondc438982016-08-31 11:53:49 -0700235 flushed = fDrawingManager->flush();
junov@google.com53a55842011-06-08 22:55:10 +0000236 }
bsalomondc438982016-08-31 11:53:49 -0700237 if (flushed) {
238 fResourceCache->notifyFlushOccurred();
239 }
bsalomonf21dab92014-11-13 13:33:28 -0800240 fFlushToReduceCacheSize = false;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000241}
242
bsalomon81beccc2014-10-13 12:32:55 -0700243bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
244 const void* inPixels, size_t outRowBytes, void* outPixels) {
245 SkSrcPixelInfo srcPI;
brianosman396fcdb2016-07-22 06:26:11 -0700246 if (!GrPixelConfigToColorType(srcConfig, &srcPI.fColorType)) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000247 return false;
248 }
bsalomon81beccc2014-10-13 12:32:55 -0700249 srcPI.fAlphaType = kUnpremul_SkAlphaType;
250 srcPI.fPixels = inPixels;
251 srcPI.fRowBytes = inRowBytes;
252
253 SkDstPixelInfo dstPI;
254 dstPI.fColorType = srcPI.fColorType;
255 dstPI.fAlphaType = kPremul_SkAlphaType;
256 dstPI.fPixels = outPixels;
257 dstPI.fRowBytes = outRowBytes;
258
259 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000260}
261
bsalomon81beccc2014-10-13 12:32:55 -0700262bool GrContext::writeSurfacePixels(GrSurface* surface,
263 int left, int top, int width, int height,
264 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
265 uint32_t pixelOpsFlags) {
joshualitt1de610a2016-01-06 08:26:09 -0800266 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800267 RETURN_FALSE_IF_ABANDONED
bsalomon6c6f6582015-09-10 08:12:46 -0700268 ASSERT_OWNED_RESOURCE(surface);
269 SkASSERT(surface);
joshualittbc907352016-01-13 06:45:40 -0800270 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels");
bsalomon6c6f6582015-09-10 08:12:46 -0700271
272 this->testPMConversionsIfNecessary(pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700273
bsalomone8d21e82015-07-16 08:23:13 -0700274 // 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 -0700275 // necessary and because GrGpu::getWritePixelsInfo requires it.
bsalomone8d21e82015-07-16 08:23:13 -0700276 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
277 GrBytesPerPixel(srcConfig), &left, &top, &width,
278 &height, &buffer, &rowBytes)) {
279 return false;
280 }
281
bsalomonf0674512015-07-28 13:26:15 -0700282 bool applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700283 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
284 if (!GrPixelConfigIs8888(srcConfig)) {
285 return false;
286 }
bsalomonf0674512015-07-28 13:26:15 -0700287 applyPremulToSrc = true;
288 }
bsalomon636e8022015-07-29 06:08:46 -0700289
290 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
291 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
292 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
293 if (applyPremulToSrc && !this->didFailPMUPMConversionTest()) {
294 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
295 }
296
bsalomonf0674512015-07-28 13:26:15 -0700297 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
cblumeed828002016-02-16 13:00:01 -0800298 if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700299 &tempDrawInfo)) {
300 return false;
301 }
302
303 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
304 this->flush();
305 }
306
307 SkAutoTUnref<GrTexture> tempTexture;
308 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomoneae62002015-07-31 13:59:30 -0700309 tempTexture.reset(
310 this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
bsalomonf0674512015-07-28 13:26:15 -0700311 if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
312 return false;
313 }
314 }
315
316 // temp buffer for doing sw premul conversion, if needed.
317 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
318 if (tempTexture) {
bungeman06ca8ec2016-06-09 08:01:03 -0700319 sk_sp<GrFragmentProcessor> fp;
bsalomonf0674512015-07-28 13:26:15 -0700320 SkMatrix textureMatrix;
321 textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
bsalomonf0674512015-07-28 13:26:15 -0700322 if (applyPremulToSrc) {
bungeman06ca8ec2016-06-09 08:01:03 -0700323 fp = this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwizzle, textureMatrix);
bsalomonf0674512015-07-28 13:26:15 -0700324 // If premultiplying was the only reason for the draw, fall back to a straight write.
325 if (!fp) {
326 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
halcanary96fcdcc2015-08-27 07:41:13 -0700327 tempTexture.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700328 }
329 } else {
330 applyPremulToSrc = false;
331 }
332 }
333 if (tempTexture) {
334 if (!fp) {
bungeman06ca8ec2016-06-09 08:01:03 -0700335 fp = GrConfigConversionEffect::Make(tempTexture, tempDrawInfo.fSwizzle,
336 GrConfigConversionEffect::kNone_PMConversion,
337 textureMatrix);
bsalomonf0674512015-07-28 13:26:15 -0700338 if (!fp) {
339 return false;
340 }
341 }
342 GrRenderTarget* renderTarget = surface->asRenderTarget();
343 SkASSERT(renderTarget);
344 if (tempTexture->surfacePriv().hasPendingIO()) {
345 this->flush();
346 }
347 if (applyPremulToSrc) {
348 size_t tmpRowBytes = 4 * width;
349 tmpPixels.reset(width * height);
350 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
351 tmpPixels.get())) {
352 return false;
353 }
354 rowBytes = tmpRowBytes;
355 buffer = tmpPixels.get();
356 applyPremulToSrc = false;
357 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700358 if (!fGpu->writePixels(tempTexture, 0, 0, width, height,
bsalomon6c9cd552016-01-22 07:17:34 -0800359 tempDrawInfo.fWriteConfig, buffer,
bsalomon6cb3cbe2015-07-30 07:34:27 -0700360 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700361 return false;
362 }
363 SkMatrix matrix;
364 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
brianosmandfe4f2e2016-07-21 13:28:36 -0700365 // TODO: Need to decide the semantics of this function for color spaces. Do we support
366 // conversion from a passed-in color space? For now, specifying nullptr means that this
367 // path will do no conversion, so it will match the behavior of the non-draw path.
robertphillips4fd74ae2016-08-03 14:26:53 -0700368 sk_sp<GrDrawContext> drawContext(this->contextPriv().makeWrappedDrawContext(
369 sk_ref_sp(renderTarget),
370 nullptr));
bsalomonf0674512015-07-28 13:26:15 -0700371 if (!drawContext) {
372 return false;
373 }
egdanielc4b72722015-11-23 13:20:41 -0800374 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700375 paint.addColorFragmentProcessor(std::move(fp));
egdanielc4b72722015-11-23 13:20:41 -0800376 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
brianosmana167e742016-05-24 06:18:48 -0700377 paint.setAllowSRGBInputs(true);
bsalomonf0674512015-07-28 13:26:15 -0700378 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
cdalton846c0512016-05-13 10:25:00 -0700379 drawContext->drawRect(GrNoClip(), paint, matrix, rect, nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700380
381 if (kFlushWrites_PixelOp & pixelOpsFlags) {
382 this->flushSurfaceWrites(surface);
383 }
384 }
385 }
386 if (!tempTexture) {
bsalomonf0674512015-07-28 13:26:15 -0700387 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700388 size_t tmpRowBytes = 4 * width;
389 tmpPixels.reset(width * height);
390 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
391 tmpPixels.get())) {
392 return false;
393 }
394 rowBytes = tmpRowBytes;
395 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700396 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700397 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700398 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700399 }
bsalomon81beccc2014-10-13 12:32:55 -0700400 return true;
401}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000402
bsalomone8d21e82015-07-16 08:23:13 -0700403bool GrContext::readSurfacePixels(GrSurface* src,
404 int left, int top, int width, int height,
405 GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
406 uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800407 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800408 RETURN_FALSE_IF_ABANDONED
bsalomone8d21e82015-07-16 08:23:13 -0700409 ASSERT_OWNED_RESOURCE(src);
410 SkASSERT(src);
joshualittbc907352016-01-13 06:45:40 -0800411 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700412
bsalomon6c6f6582015-09-10 08:12:46 -0700413 this->testPMConversionsIfNecessary(flags);
414 SkAutoMutexAcquire ama(fReadPixelsMutex);
415
bsalomone8d21e82015-07-16 08:23:13 -0700416 // Adjust the params so that if we wind up using an intermediate surface we've already done
417 // all the trimming and the temporary can be the min size required.
418 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
419 GrBytesPerPixel(dstConfig), &left,
420 &top, &width, &height, &buffer, &rowBytes)) {
421 return false;
422 }
423
424 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000425 this->flush();
426 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000427
bsalomone8d21e82015-07-16 08:23:13 -0700428 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
bsalomon@google.com9c680582013-02-06 18:17:50 +0000429 if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
bsalomon39826022015-07-23 08:07:21 -0700430 // The unpremul flag is only allowed for 8888 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000431 return false;
432 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000433
bsalomon636e8022015-07-29 06:08:46 -0700434 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
435 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
436 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
437 if (unpremul && !this->didFailPMUPMConversionTest()) {
438 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
439 }
440
bsalomon39826022015-07-23 08:07:21 -0700441 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
442 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference,
443 &tempDrawInfo)) {
444 return false;
445 }
bsalomon191bcc02014-11-14 11:31:13 -0800446
bsalomon6cb3cbe2015-07-30 07:34:27 -0700447 SkAutoTUnref<GrSurface> surfaceToRead(SkRef(src));
bsalomon39826022015-07-23 08:07:21 -0700448 bool didTempDraw = false;
449 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomonb117ff12016-07-19 07:24:40 -0700450 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) {
bsalomon39826022015-07-23 08:07:21 -0700451 // We only respect this when the entire src is being read. Otherwise we can trigger too
452 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700453 if (width != src->width() || height != src->height()) {
bsalomonb117ff12016-07-19 07:24:40 -0700454 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox;
bsalomon39826022015-07-23 08:07:21 -0700455 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000456 }
brianosmandfe4f2e2016-07-21 13:28:36 -0700457 // TODO: Need to decide the semantics of this function for color spaces. Do we support
458 // conversion to a passed-in color space? For now, specifying nullptr means that this
459 // path will do no conversion, so it will match the behavior of the non-draw path.
robertphillips6738c702016-07-27 12:13:51 -0700460 sk_sp<GrDrawContext> tempDC = this->makeDrawContext(tempDrawInfo.fTempSurfaceFit,
bsalomonb117ff12016-07-19 07:24:40 -0700461 tempDrawInfo.fTempSurfaceDesc.fWidth,
462 tempDrawInfo.fTempSurfaceDesc.fHeight,
463 tempDrawInfo.fTempSurfaceDesc.fConfig,
brianosmandfe4f2e2016-07-21 13:28:36 -0700464 nullptr,
bsalomonb117ff12016-07-19 07:24:40 -0700465 tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
466 tempDrawInfo.fTempSurfaceDesc.fOrigin);
467 if (tempDC) {
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000468 SkMatrix textureMatrix;
bsalomon39826022015-07-23 08:07:21 -0700469 textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000470 textureMatrix.postIDiv(src->width(), src->height());
bungeman06ca8ec2016-06-09 08:01:03 -0700471 sk_sp<GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000472 if (unpremul) {
bungeman06ca8ec2016-06-09 08:01:03 -0700473 fp = this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle,
474 textureMatrix);
joshualittb0a8a372014-09-23 09:50:21 -0700475 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000476 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon39826022015-07-23 08:07:21 -0700477 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
478 // We only wanted to do the draw in order to perform the unpremul so don't
479 // bother.
bsalomonb117ff12016-07-19 07:24:40 -0700480 tempDC.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000481 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000482 }
bsalomonb117ff12016-07-19 07:24:40 -0700483 if (!fp && tempDC) {
bungeman06ca8ec2016-06-09 08:01:03 -0700484 fp = GrConfigConversionEffect::Make(src->asTexture(), tempDrawInfo.fSwizzle,
485 GrConfigConversionEffect::kNone_PMConversion,
486 textureMatrix);
bsalomon39826022015-07-23 08:07:21 -0700487 }
488 if (fp) {
egdanielc4b72722015-11-23 13:20:41 -0800489 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700490 paint.addColorFragmentProcessor(std::move(fp));
egdanielc4b72722015-11-23 13:20:41 -0800491 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
brianosmana167e742016-05-24 06:18:48 -0700492 paint.setAllowSRGBInputs(true);
bsalomon39826022015-07-23 08:07:21 -0700493 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
bsalomonb117ff12016-07-19 07:24:40 -0700494 tempDC->drawRect(GrNoClip(), paint, SkMatrix::I(), rect, nullptr);
495 surfaceToRead.reset(tempDC->asTexture().release());
bsalomon39826022015-07-23 08:07:21 -0700496 left = 0;
497 top = 0;
498 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000499 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000500 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000501 }
joshualitt5c55fef2014-10-31 14:04:35 -0700502
bsalomon39826022015-07-23 08:07:21 -0700503 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000504 return false;
505 }
bsalomon39826022015-07-23 08:07:21 -0700506 GrPixelConfig configToRead = dstConfig;
507 if (didTempDraw) {
bsalomon6cb3cbe2015-07-30 07:34:27 -0700508 this->flushSurfaceWrites(surfaceToRead);
bsalomon6c9cd552016-01-22 07:17:34 -0800509 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700510 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700511 if (!fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead, buffer,
512 rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700513 return false;
514 }
515
516 // Perform umpremul conversion if we weren't able to perform it as a draw.
517 if (unpremul) {
reed@google.com7111d462014-03-25 16:20:24 +0000518 SkDstPixelInfo dstPI;
brianosman396fcdb2016-07-22 06:26:11 -0700519 if (!GrPixelConfigToColorType(dstConfig, &dstPI.fColorType)) {
reed@google.com7111d462014-03-25 16:20:24 +0000520 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000521 }
reed@google.com7111d462014-03-25 16:20:24 +0000522 dstPI.fAlphaType = kUnpremul_SkAlphaType;
523 dstPI.fPixels = buffer;
524 dstPI.fRowBytes = rowBytes;
525
526 SkSrcPixelInfo srcPI;
bsalomon39826022015-07-23 08:07:21 -0700527 srcPI.fColorType = dstPI.fColorType;
reed@google.com7111d462014-03-25 16:20:24 +0000528 srcPI.fAlphaType = kPremul_SkAlphaType;
529 srcPI.fPixels = buffer;
530 srcPI.fRowBytes = rowBytes;
531
532 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000533 }
534 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000535}
536
bsalomonc49e8682015-06-30 11:37:35 -0700537void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800538 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800539 RETURN_IF_ABANDONED
bsalomon87a94eb2014-11-03 14:28:32 -0800540 SkASSERT(surface);
541 ASSERT_OWNED_RESOURCE(surface);
542 if (surface->surfacePriv().hasPendingIO()) {
543 this->flush();
544 }
545 GrRenderTarget* rt = surface->asRenderTarget();
546 if (fGpu && rt) {
547 fGpu->resolveRenderTarget(rt);
bsalomon41ebbdd2014-08-04 08:31:39 -0700548 }
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000549}
550
bsalomonb8fea972016-02-16 07:34:17 -0800551bool GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
552 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800553 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800554 RETURN_FALSE_IF_ABANDONED
joshualittbc907352016-01-13 06:45:40 -0800555 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::copySurface");
556
robertphillipsea461502015-05-26 11:38:03 -0700557 if (!src || !dst) {
bsalomonb8fea972016-02-16 07:34:17 -0800558 return false;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000559 }
bsalomone3d4bf22014-09-23 09:15:03 -0700560 ASSERT_OWNED_RESOURCE(src);
junov2bb52102014-09-29 10:18:59 -0700561 ASSERT_OWNED_RESOURCE(dst);
Brian Salomon34a98952014-09-24 11:41:24 -0400562
robertphillipsea461502015-05-26 11:38:03 -0700563 if (!dst->asRenderTarget()) {
bsalomonb8fea972016-02-16 07:34:17 -0800564 SkIRect clippedSrcRect;
565 SkIPoint clippedDstPoint;
566 if (!GrCopySurfaceBatch::ClipSrcRectAndDstPoint(dst, src, srcRect, dstPoint,
567 &clippedSrcRect, &clippedDstPoint)) {
568 return false;
569 }
570 // If we don't have an RT for the dst then we won't have a GrDrawContext to insert the
571 // the copy surface into. In the future we plan to have a more limited Context type
572 // (GrCopyContext?) that has the subset of GrDrawContext operations that should be
573 // allowed on textures that aren't render targets.
574 // For now we just flush any writes to the src and issue an immediate copy to the dst.
575 src->flushWrites();
576 return fGpu->copySurface(dst, src, clippedSrcRect, clippedDstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700577 }
robertphillips4fd74ae2016-08-03 14:26:53 -0700578 sk_sp<GrDrawContext> drawContext(this->contextPriv().makeWrappedDrawContext(
579 sk_ref_sp(dst->asRenderTarget()),
580 nullptr));
kjlubick0eed9452016-02-11 12:05:24 -0800581 if (!drawContext) {
bsalomonb8fea972016-02-16 07:34:17 -0800582 return false;
bsalomonf80bfed2014-10-07 05:56:02 -0700583 }
kjlubick0eed9452016-02-11 12:05:24 -0800584
bsalomonb8fea972016-02-16 07:34:17 -0800585 if (!drawContext->copySurface(src, srcRect, dstPoint)) {
586 return false;
kjlubick0eed9452016-02-11 12:05:24 -0800587 }
bsalomonb8fea972016-02-16 07:34:17 -0800588 return true;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000589}
590
bsalomonf80bfed2014-10-07 05:56:02 -0700591void GrContext::flushSurfaceWrites(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800592 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800593 RETURN_IF_ABANDONED
bsalomonf80bfed2014-10-07 05:56:02 -0700594 if (surface->surfacePriv().hasPendingWrite()) {
595 this->flush();
596 }
597}
598
ajuma95243eb2016-08-24 08:19:02 -0700599void GrContext::flushSurfaceIO(GrSurface* surface) {
600 ASSERT_SINGLE_OWNER
601 RETURN_IF_ABANDONED
602 if (surface->surfacePriv().hasPendingIO()) {
603 this->flush();
604 }
605}
606
bsalomon@google.com27847de2011-02-22 20:59:41 +0000607////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000608int GrContext::getRecommendedSampleCount(GrPixelConfig config,
609 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800610 ASSERT_SINGLE_OWNER
611
bsalomon76228632015-05-29 08:02:10 -0700612 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000613 return 0;
614 }
615 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700616 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000617 if (dpi >= 250.0f) {
618 chosenSampleCount = 4;
619 } else {
620 chosenSampleCount = 16;
621 }
622 }
egdanieleed519e2016-01-15 11:36:18 -0800623 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000624}
625
robertphillips4fd74ae2016-08-03 14:26:53 -0700626sk_sp<GrDrawContext> GrContextPriv::makeWrappedDrawContext(sk_sp<GrRenderTarget> rt,
627 sk_sp<SkColorSpace> colorSpace,
628 const SkSurfaceProps* surfaceProps) {
629 ASSERT_SINGLE_OWNER_PRIV
csmartdaltonbde96c62016-08-31 12:54:46 -0700630 return this->drawingManager()->makeDrawContext(std::move(rt),
631 std::move(colorSpace),
632 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700633}
robertphillips77a2e522015-10-17 07:43:27 -0700634
robertphillips4fd74ae2016-08-03 14:26:53 -0700635sk_sp<GrDrawContext> GrContextPriv::makeBackendTextureDrawContext(const GrBackendTextureDesc& desc,
636 sk_sp<SkColorSpace> colorSpace,
637 const SkSurfaceProps* props,
638 GrWrapOwnership ownership) {
639 ASSERT_SINGLE_OWNER_PRIV
640 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
641
642 sk_sp<GrSurface> surface(fContext->textureProvider()->wrapBackendTexture(desc, ownership));
643 if (!surface) {
644 return nullptr;
645 }
646
csmartdaltonbde96c62016-08-31 12:54:46 -0700647 return this->drawingManager()->makeDrawContext(sk_ref_sp(surface->asRenderTarget()),
648 std::move(colorSpace), props);
robertphillips4fd74ae2016-08-03 14:26:53 -0700649}
650
651sk_sp<GrDrawContext> GrContextPriv::makeBackendRenderTargetDrawContext(
652 const GrBackendRenderTargetDesc& desc,
653 sk_sp<SkColorSpace> colorSpace,
654 const SkSurfaceProps* surfaceProps) {
655 ASSERT_SINGLE_OWNER_PRIV
656
657 sk_sp<GrRenderTarget> rt(fContext->textureProvider()->wrapBackendRenderTarget(desc));
658 if (!rt) {
659 return nullptr;
660 }
661
csmartdaltonbde96c62016-08-31 12:54:46 -0700662 return this->drawingManager()->makeDrawContext(std::move(rt),
663 std::move(colorSpace),
664 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700665}
666
667sk_sp<GrDrawContext> GrContextPriv::makeBackendTextureAsRenderTargetDrawContext(
egdaniela95d46b2016-08-15 08:06:29 -0700668 const GrBackendTextureDesc& desc,
robertphillips4fd74ae2016-08-03 14:26:53 -0700669 sk_sp<SkColorSpace> colorSpace,
670 const SkSurfaceProps* surfaceProps) {
671 ASSERT_SINGLE_OWNER_PRIV
672 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
673
674 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
675 if (!surface) {
676 return nullptr;
677 }
678
csmartdaltonbde96c62016-08-31 12:54:46 -0700679 return this->drawingManager()->makeDrawContext(sk_ref_sp(surface->asRenderTarget()),
680 std::move(colorSpace),
681 surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700682}
683
robertphillips48fde9c2016-09-06 05:20:20 -0700684static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
685 static const GrPixelConfig kFallback[] = {
686 kUnknown_GrPixelConfig, // kUnknown_GrPixelConfig
687 kRGBA_8888_GrPixelConfig, // kAlpha_8_GrPixelConfig
688 kUnknown_GrPixelConfig, // kIndex_8_GrPixelConfig
689 kRGBA_8888_GrPixelConfig, // kRGB_565_GrPixelConfig
690 kRGBA_8888_GrPixelConfig, // kRGBA_4444_GrPixelConfig
691 kUnknown_GrPixelConfig, // kRGBA_8888_GrPixelConfig
692 kRGBA_8888_GrPixelConfig, // kBGRA_8888_GrPixelConfig
693 kUnknown_GrPixelConfig, // kSRGBA_8888_GrPixelConfig
694 kSRGBA_8888_GrPixelConfig, // kSBGRA_8888_GrPixelConfig
695 kUnknown_GrPixelConfig, // kETC1_GrPixelConfig
696 kUnknown_GrPixelConfig, // kLATC_GrPixelConfig
697 kUnknown_GrPixelConfig, // kR11_EAC_GrPixelConfig
698 kUnknown_GrPixelConfig, // kASTC_12x12_GrPixelConfig
699 kUnknown_GrPixelConfig, // kRGBA_float_GrPixelConfig
700 kRGBA_half_GrPixelConfig, // kAlpha_half_GrPixelConfig
701 kUnknown_GrPixelConfig, // kRGBA_half_GrPixelConfig
702 };
703 return kFallback[config];
704
705 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
706 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
707 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
708 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
709 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
710 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
711 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
712 GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig);
713 GR_STATIC_ASSERT(8 == kSBGRA_8888_GrPixelConfig);
714 GR_STATIC_ASSERT(9 == kETC1_GrPixelConfig);
715 GR_STATIC_ASSERT(10 == kLATC_GrPixelConfig);
716 GR_STATIC_ASSERT(11 == kR11_EAC_GrPixelConfig);
717 GR_STATIC_ASSERT(12 == kASTC_12x12_GrPixelConfig);
718 GR_STATIC_ASSERT(13 == kRGBA_float_GrPixelConfig);
719 GR_STATIC_ASSERT(14 == kAlpha_half_GrPixelConfig);
720 GR_STATIC_ASSERT(15 == kRGBA_half_GrPixelConfig);
721 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFallback) == kGrPixelConfigCnt);
722}
723
724sk_sp<GrDrawContext> GrContext::makeDrawContextWithFallback(SkBackingFit fit,
725 int width, int height,
726 GrPixelConfig config,
727 sk_sp<SkColorSpace> colorSpace,
728 int sampleCnt,
729 GrSurfaceOrigin origin,
730 const SkSurfaceProps* surfaceProps,
731 SkBudgeted budgeted) {
732 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
733 config = GrPixelConfigFallback(config);
734 }
735
736 return this->makeDrawContext(fit, width, height, config, std::move(colorSpace),
737 sampleCnt, origin, surfaceProps, budgeted);
738}
739
robertphillips6738c702016-07-27 12:13:51 -0700740sk_sp<GrDrawContext> GrContext::makeDrawContext(SkBackingFit fit,
741 int width, int height,
742 GrPixelConfig config,
743 sk_sp<SkColorSpace> colorSpace,
744 int sampleCnt,
745 GrSurfaceOrigin origin,
746 const SkSurfaceProps* surfaceProps,
747 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700748 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
749 return nullptr;
750 }
751
robertphillipsd4c741e2016-04-28 09:55:15 -0700752 GrSurfaceDesc desc;
753 desc.fFlags = kRenderTarget_GrSurfaceFlag;
754 desc.fOrigin = origin;
755 desc.fWidth = width;
756 desc.fHeight = height;
757 desc.fConfig = config;
758 desc.fSampleCnt = sampleCnt;
759
760 sk_sp<GrTexture> tex;
robertphillips76948d42016-05-04 12:47:41 -0700761 if (SkBackingFit::kExact == fit) {
robertphillipsca6eafc2016-05-17 09:57:46 -0700762 tex.reset(this->textureProvider()->createTexture(desc, budgeted));
robertphillipsd4c741e2016-04-28 09:55:15 -0700763 } else {
764 tex.reset(this->textureProvider()->createApproxTexture(desc));
765 }
766 if (!tex) {
767 return nullptr;
768 }
769
robertphillips4fd74ae2016-08-03 14:26:53 -0700770 sk_sp<GrDrawContext> drawContext(this->contextPriv().makeWrappedDrawContext(
771 sk_ref_sp(tex->asRenderTarget()),
robertphillips6738c702016-07-27 12:13:51 -0700772 std::move(colorSpace), surfaceProps));
robertphillipsd4c741e2016-04-28 09:55:15 -0700773 if (!drawContext) {
774 return nullptr;
775 }
776
777 return drawContext;
778}
779
joshualitt1de610a2016-01-06 08:26:09 -0800780bool GrContext::abandoned() const {
781 ASSERT_SINGLE_OWNER
robertphillips7761d612016-05-16 09:14:53 -0700782 return fDrawingManager->wasAbandoned();
robertphillips77a2e522015-10-17 07:43:27 -0700783}
784
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000785namespace {
786void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
787 GrConfigConversionEffect::PMConversion pmToUPM;
788 GrConfigConversionEffect::PMConversion upmToPM;
789 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
790 *pmToUPMValue = pmToUPM;
791 *upmToPMValue = upmToPM;
792}
793}
794
bsalomon6c6f6582015-09-10 08:12:46 -0700795void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800796 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700797 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) {
798 SkAutoMutexAcquire ama(fTestPMConversionsMutex);
799 if (!fDidTestPMConversions) {
800 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
801 fDidTestPMConversions = true;
802 }
803 }
804}
805
bungeman06ca8ec2016-06-09 08:01:03 -0700806sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800807 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700808 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800809 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700810 // We should have already called this->testPMConversionsIfNecessary().
811 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000812 GrConfigConversionEffect::PMConversion pmToUPM =
813 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
814 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
bungeman06ca8ec2016-06-09 08:01:03 -0700815 return GrConfigConversionEffect::Make(texture, swizzle, pmToUPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000816 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700817 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000818 }
819}
820
bungeman06ca8ec2016-06-09 08:01:03 -0700821sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800822 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700823 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800824 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700825 // We should have already called this->testPMConversionsIfNecessary().
826 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000827 GrConfigConversionEffect::PMConversion upmToPM =
828 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
829 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
bungeman06ca8ec2016-06-09 08:01:03 -0700830 return GrConfigConversionEffect::Make(texture, swizzle, upmToPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000831 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700832 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000833 }
834}
835
bsalomon636e8022015-07-29 06:08:46 -0700836bool GrContext::didFailPMUPMConversionTest() const {
joshualitt1de610a2016-01-06 08:26:09 -0800837 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700838 // We should have already called this->testPMConversionsIfNecessary().
839 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700840 // The PM<->UPM tests fail or succeed together so we only need to check one.
bsalomon6c6f6582015-09-10 08:12:46 -0700841 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion;
bsalomon636e8022015-07-29 06:08:46 -0700842}
843
bsalomon37f9a262015-02-02 13:00:10 -0800844//////////////////////////////////////////////////////////////////////////////
845
846void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800847 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800848 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800849 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800850 }
851 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800852 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800853 }
854}
855
856void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800857 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800858 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800859}
860
ericrk0a5fa482015-09-15 14:16:10 -0700861//////////////////////////////////////////////////////////////////////////////
862
863void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800864 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700865 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
866}