blob: 39916b9728496ccb91fc5b30f2b42f9ead8f78a3 [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"
bsalomon682c2692015-05-22 14:01:46 -07009#include "GrContextOptions.h"
robertphillips77a2e522015-10-17 07:43:27 -070010#include "GrDrawingManager.h"
robertphillipsea461502015-05-26 11:38:03 -070011#include "GrDrawContext.h"
robertphillips@google.come930a072014-04-03 00:34:27 +000012#include "GrLayerCache.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);)
robertphillips77a2e522015-10-17 07:43:27 -070029#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
30#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; }
31#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000032
robertphillipsea461502015-05-26 11:38:03 -070033////////////////////////////////////////////////////////////////////////////////
34
bsalomon682c2692015-05-22 14:01:46 -070035GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
36 GrContextOptions defaultOptions;
37 return Create(backend, backendContext, defaultOptions);
38}
bsalomonf28cff72015-05-22 12:25:41 -070039
bsalomon682c2692015-05-22 14:01:46 -070040GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
41 const GrContextOptions& options) {
halcanary385fe4d2015-08-26 13:07:48 -070042 GrContext* context = new GrContext;
bsalomon682c2692015-05-22 14:01:46 -070043
44 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000045 return context;
46 } else {
47 context->unref();
halcanary96fcdcc2015-08-27 07:41:13 -070048 return nullptr;
bsalomon@google.com27847de2011-02-22 20:59:41 +000049 }
bsalomon@google.com27847de2011-02-22 20:59:41 +000050}
51
joshualitt0acd0d32015-05-07 08:23:19 -070052static int32_t gNextID = 1;
53static int32_t next_id() {
54 int32_t id;
55 do {
56 id = sk_atomic_inc(&gNextID);
57 } while (id == SK_InvalidGenID);
58 return id;
59}
60
bsalomon682c2692015-05-22 14:01:46 -070061GrContext::GrContext() : fUniqueID(next_id()) {
halcanary96fcdcc2015-08-27 07:41:13 -070062 fGpu = nullptr;
63 fCaps = nullptr;
64 fResourceCache = nullptr;
65 fResourceProvider = nullptr;
halcanary96fcdcc2015-08-27 07:41:13 -070066 fBatchFontCache = nullptr;
bsalomonf21dab92014-11-13 13:33:28 -080067 fFlushToReduceCacheSize = false;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000068}
69
bsalomon682c2692015-05-22 14:01:46 -070070bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
71 const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080072 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -070073 SkASSERT(!fGpu);
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000074
bsalomon682c2692015-05-22 14:01:46 -070075 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -070076 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000077 return false;
78 }
bsalomon69cfe952015-11-30 13:27:47 -080079 this->initCommon(options);
bsalomon33435572014-11-05 14:47:41 -080080 return true;
81}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000082
bsalomon69cfe952015-11-30 13:27:47 -080083void GrContext::initCommon(const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080084 ASSERT_SINGLE_OWNER
85
bsalomon76228632015-05-29 08:02:10 -070086 fCaps = SkRef(fGpu->caps());
halcanary385fe4d2015-08-26 13:07:48 -070087 fResourceCache = new GrResourceCache(fCaps);
bsalomon0ea80f42015-02-11 10:49:59 -080088 fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
joshualitt6d0872d2016-01-11 08:27:48 -080089 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +000090
halcanary385fe4d2015-08-26 13:07:48 -070091 fLayerCache.reset(new GrLayerCache(this));
robertphillips@google.come930a072014-04-03 00:34:27 +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();
155 fLayerCache->freeAll();
156 fTextBlobCache->freeAll();
157}
158
159void GrContext::releaseResourcesAndAbandonContext() {
160 ASSERT_SINGLE_OWNER
161
162 fResourceProvider->abandon();
163
164 // Need to abandon the drawing manager first so all the render targets
165 // will be released/forgotten before they too are abandoned.
166 fDrawingManager->abandon();
167
168 // Release all resources in the backend 3D API.
169 fResourceCache->releaseAll();
170
171 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000172
joshualitt7c3a2f82015-03-31 13:32:05 -0700173 fBatchFontCache->freeAll();
robertphillips@google.come930a072014-04-03 00:34:27 +0000174 fLayerCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700175 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000176}
177
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000178void GrContext::resetContext(uint32_t state) {
joshualitt1de610a2016-01-06 08:26:09 -0800179 ASSERT_SINGLE_OWNER
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000180 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000181}
182
183void GrContext::freeGpuResources() {
joshualitt1de610a2016-01-06 08:26:09 -0800184 ASSERT_SINGLE_OWNER
185
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000186 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000187
joshualitt7c3a2f82015-03-31 13:32:05 -0700188 fBatchFontCache->freeAll();
robertphillips@google.come930a072014-04-03 00:34:27 +0000189 fLayerCache->freeAll();
robertphillips68737822015-10-29 12:12:21 -0700190
191 fDrawingManager->freeGpuResources();
bsalomon3033b9f2015-04-13 11:09:56 -0700192
193 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000194}
195
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000196void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800197 ASSERT_SINGLE_OWNER
198
bsalomon71cb0c22014-11-14 12:10:14 -0800199 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800200 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800201 }
202 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800203 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800204 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000205}
206
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000207////////////////////////////////////////////////////////////////////////////////
208
bsalomon71cb0c22014-11-14 12:10:14 -0800209void GrContext::OverBudgetCB(void* data) {
bsalomon66a450f2014-11-13 13:19:10 -0800210 SkASSERT(data);
bsalomonf21dab92014-11-13 13:33:28 -0800211
bsalomon66a450f2014-11-13 13:19:10 -0800212 GrContext* context = reinterpret_cast<GrContext*>(data);
bsalomonf21dab92014-11-13 13:33:28 -0800213
joshualittb542bae2015-07-28 09:58:39 -0700214 // Flush the GrBufferedDrawTarget to possibly free up some textures
bsalomonf21dab92014-11-13 13:33:28 -0800215 context->fFlushToReduceCacheSize = true;
commit-bot@chromium.orgcae27fe2013-07-10 10:14:35 +0000216}
217
joshualitt0db6dfa2015-04-10 07:01:30 -0700218void GrContext::TextBlobCacheOverBudgetCB(void* data) {
219 SkASSERT(data);
220
221 // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
222 // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move
223 // drawText calls to below the GrContext level, but this is not trivial because they call
224 // drawPath on SkGpuDevice
225 GrContext* context = reinterpret_cast<GrContext*>(data);
226 context->flush();
227}
228
bsalomon@google.com27847de2011-02-22 20:59:41 +0000229////////////////////////////////////////////////////////////////////////////////
230
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000231void GrContext::flush(int flagsBitfield) {
joshualitt1de610a2016-01-06 08:26:09 -0800232 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700233 RETURN_IF_ABANDONED
robertphillips@google.come7db8d62013-07-04 11:48:52 +0000234
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000235 if (kDiscard_FlushBit & flagsBitfield) {
robertphillips77a2e522015-10-17 07:43:27 -0700236 fDrawingManager->reset();
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000237 } else {
robertphillips77a2e522015-10-17 07:43:27 -0700238 fDrawingManager->flush();
junov@google.com53a55842011-06-08 22:55:10 +0000239 }
bsalomon3f324322015-04-08 11:01:54 -0700240 fResourceCache->notifyFlushOccurred();
bsalomonf21dab92014-11-13 13:33:28 -0800241 fFlushToReduceCacheSize = false;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000242}
243
bsalomon81beccc2014-10-13 12:32:55 -0700244bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
245 const void* inPixels, size_t outRowBytes, void* outPixels) {
246 SkSrcPixelInfo srcPI;
halcanary96fcdcc2015-08-27 07:41:13 -0700247 if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, nullptr)) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000248 return false;
249 }
bsalomon81beccc2014-10-13 12:32:55 -0700250 srcPI.fAlphaType = kUnpremul_SkAlphaType;
251 srcPI.fPixels = inPixels;
252 srcPI.fRowBytes = inRowBytes;
253
254 SkDstPixelInfo dstPI;
255 dstPI.fColorType = srcPI.fColorType;
256 dstPI.fAlphaType = kPremul_SkAlphaType;
257 dstPI.fPixels = outPixels;
258 dstPI.fRowBytes = outRowBytes;
259
260 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000261}
262
bsalomon81beccc2014-10-13 12:32:55 -0700263bool GrContext::writeSurfacePixels(GrSurface* surface,
264 int left, int top, int width, int height,
265 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
266 uint32_t pixelOpsFlags) {
joshualitt1de610a2016-01-06 08:26:09 -0800267 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800268 RETURN_FALSE_IF_ABANDONED
bsalomon6c6f6582015-09-10 08:12:46 -0700269 ASSERT_OWNED_RESOURCE(surface);
270 SkASSERT(surface);
joshualittbc907352016-01-13 06:45:40 -0800271 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels");
bsalomon6c6f6582015-09-10 08:12:46 -0700272
273 this->testPMConversionsIfNecessary(pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700274
bsalomone8d21e82015-07-16 08:23:13 -0700275 // 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 -0700276 // necessary and because GrGpu::getWritePixelsInfo requires it.
bsalomone8d21e82015-07-16 08:23:13 -0700277 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
278 GrBytesPerPixel(srcConfig), &left, &top, &width,
279 &height, &buffer, &rowBytes)) {
280 return false;
281 }
282
bsalomonf0674512015-07-28 13:26:15 -0700283 bool applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700284 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
285 if (!GrPixelConfigIs8888(srcConfig)) {
286 return false;
287 }
bsalomonf0674512015-07-28 13:26:15 -0700288 applyPremulToSrc = true;
289 }
bsalomon636e8022015-07-29 06:08:46 -0700290
291 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
292 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
293 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
294 if (applyPremulToSrc && !this->didFailPMUPMConversionTest()) {
295 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
296 }
297
bsalomonf0674512015-07-28 13:26:15 -0700298 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
cblumeed828002016-02-16 13:00:01 -0800299 if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700300 &tempDrawInfo)) {
301 return false;
302 }
303
304 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
305 this->flush();
306 }
307
308 SkAutoTUnref<GrTexture> tempTexture;
309 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomoneae62002015-07-31 13:59:30 -0700310 tempTexture.reset(
311 this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
bsalomonf0674512015-07-28 13:26:15 -0700312 if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
313 return false;
314 }
315 }
316
317 // temp buffer for doing sw premul conversion, if needed.
318 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
319 if (tempTexture) {
320 SkAutoTUnref<const GrFragmentProcessor> fp;
321 SkMatrix textureMatrix;
322 textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
bsalomonf0674512015-07-28 13:26:15 -0700323 if (applyPremulToSrc) {
bsalomon6c9cd552016-01-22 07:17:34 -0800324 fp.reset(this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwizzle,
bsalomon4a339522015-10-06 08:40:50 -0700325 textureMatrix));
bsalomonf0674512015-07-28 13:26:15 -0700326 // If premultiplying was the only reason for the draw, fall back to a straight write.
327 if (!fp) {
328 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
halcanary96fcdcc2015-08-27 07:41:13 -0700329 tempTexture.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700330 }
331 } else {
332 applyPremulToSrc = false;
333 }
334 }
335 if (tempTexture) {
336 if (!fp) {
bsalomon6c9cd552016-01-22 07:17:34 -0800337 fp.reset(GrConfigConversionEffect::Create(tempTexture, tempDrawInfo.fSwizzle,
bsalomonf0674512015-07-28 13:26:15 -0700338 GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
339 if (!fp) {
340 return false;
341 }
342 }
343 GrRenderTarget* renderTarget = surface->asRenderTarget();
344 SkASSERT(renderTarget);
345 if (tempTexture->surfacePriv().hasPendingIO()) {
346 this->flush();
347 }
348 if (applyPremulToSrc) {
349 size_t tmpRowBytes = 4 * width;
350 tmpPixels.reset(width * height);
351 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
352 tmpPixels.get())) {
353 return false;
354 }
355 rowBytes = tmpRowBytes;
356 buffer = tmpPixels.get();
357 applyPremulToSrc = false;
358 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700359 if (!fGpu->writePixels(tempTexture, 0, 0, width, height,
bsalomon6c9cd552016-01-22 07:17:34 -0800360 tempDrawInfo.fWriteConfig, buffer,
bsalomon6cb3cbe2015-07-30 07:34:27 -0700361 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700362 return false;
363 }
364 SkMatrix matrix;
365 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
robertphillips6c7e3252016-04-27 10:47:51 -0700366 sk_sp<GrDrawContext> drawContext(this->drawContext(sk_ref_sp(renderTarget)));
bsalomonf0674512015-07-28 13:26:15 -0700367 if (!drawContext) {
368 return false;
369 }
brianosman898235c2016-04-06 07:38:23 -0700370 // SRGBTODO: AllowSRGBInputs? (We could force it on here, so we don't need the
371 // per-texture override in config conversion effect?)
egdanielc4b72722015-11-23 13:20:41 -0800372 GrPaint paint;
bsalomonac856c92015-08-27 06:30:17 -0700373 paint.addColorFragmentProcessor(fp);
egdanielc4b72722015-11-23 13:20:41 -0800374 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
bsalomonf0674512015-07-28 13:26:15 -0700375 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
cdalton846c0512016-05-13 10:25:00 -0700376 drawContext->drawRect(GrNoClip(), paint, matrix, rect, nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700377
378 if (kFlushWrites_PixelOp & pixelOpsFlags) {
379 this->flushSurfaceWrites(surface);
380 }
381 }
382 }
383 if (!tempTexture) {
bsalomonf0674512015-07-28 13:26:15 -0700384 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700385 size_t tmpRowBytes = 4 * width;
386 tmpPixels.reset(width * height);
387 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
388 tmpPixels.get())) {
389 return false;
390 }
391 rowBytes = tmpRowBytes;
392 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700393 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700394 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700395 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700396 }
bsalomon81beccc2014-10-13 12:32:55 -0700397 return true;
398}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000399
bsalomone8d21e82015-07-16 08:23:13 -0700400bool GrContext::readSurfacePixels(GrSurface* src,
401 int left, int top, int width, int height,
402 GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
403 uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800404 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800405 RETURN_FALSE_IF_ABANDONED
bsalomone8d21e82015-07-16 08:23:13 -0700406 ASSERT_OWNED_RESOURCE(src);
407 SkASSERT(src);
joshualittbc907352016-01-13 06:45:40 -0800408 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700409
bsalomon6c6f6582015-09-10 08:12:46 -0700410 this->testPMConversionsIfNecessary(flags);
411 SkAutoMutexAcquire ama(fReadPixelsMutex);
412
bsalomone8d21e82015-07-16 08:23:13 -0700413 // Adjust the params so that if we wind up using an intermediate surface we've already done
414 // all the trimming and the temporary can be the min size required.
415 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
416 GrBytesPerPixel(dstConfig), &left,
417 &top, &width, &height, &buffer, &rowBytes)) {
418 return false;
419 }
420
421 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000422 this->flush();
423 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000424
bsalomone8d21e82015-07-16 08:23:13 -0700425 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
bsalomon@google.com9c680582013-02-06 18:17:50 +0000426 if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
bsalomon39826022015-07-23 08:07:21 -0700427 // The unpremul flag is only allowed for 8888 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000428 return false;
429 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000430
bsalomon636e8022015-07-29 06:08:46 -0700431 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
432 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
433 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
434 if (unpremul && !this->didFailPMUPMConversionTest()) {
435 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
436 }
437
bsalomon39826022015-07-23 08:07:21 -0700438 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
439 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference,
440 &tempDrawInfo)) {
441 return false;
442 }
bsalomon191bcc02014-11-14 11:31:13 -0800443
bsalomon6cb3cbe2015-07-30 07:34:27 -0700444 SkAutoTUnref<GrSurface> surfaceToRead(SkRef(src));
bsalomon39826022015-07-23 08:07:21 -0700445 bool didTempDraw = false;
446 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomon39826022015-07-23 08:07:21 -0700447 if (tempDrawInfo.fUseExactScratch) {
448 // We only respect this when the entire src is being read. Otherwise we can trigger too
449 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700450 if (width != src->width() || height != src->height()) {
451 tempDrawInfo.fUseExactScratch = false;
bsalomon39826022015-07-23 08:07:21 -0700452 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000453 }
bsalomon39826022015-07-23 08:07:21 -0700454 SkAutoTUnref<GrTexture> temp;
bsalomoneae62002015-07-31 13:59:30 -0700455 if (tempDrawInfo.fUseExactScratch) {
bsalomon5ec26ae2016-02-25 08:33:02 -0800456 temp.reset(this->textureProvider()->createTexture(tempDrawInfo.fTempSurfaceDesc,
457 SkBudgeted::kYes));
bsalomoneae62002015-07-31 13:59:30 -0700458 } else {
459 temp.reset(this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
460 }
bsalomon39826022015-07-23 08:07:21 -0700461 if (temp) {
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000462 SkMatrix textureMatrix;
bsalomon39826022015-07-23 08:07:21 -0700463 textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000464 textureMatrix.postIDiv(src->width(), src->height());
joshualittb0a8a372014-09-23 09:50:21 -0700465 SkAutoTUnref<const GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000466 if (unpremul) {
bsalomon6c9cd552016-01-22 07:17:34 -0800467 fp.reset(this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle,
bsalomon39826022015-07-23 08:07:21 -0700468 textureMatrix));
joshualittb0a8a372014-09-23 09:50:21 -0700469 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000470 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon39826022015-07-23 08:07:21 -0700471 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
472 // We only wanted to do the draw in order to perform the unpremul so don't
473 // bother.
halcanary96fcdcc2015-08-27 07:41:13 -0700474 temp.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000475 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000476 }
bsalomon39826022015-07-23 08:07:21 -0700477 if (!fp && temp) {
bsalomon6c9cd552016-01-22 07:17:34 -0800478 fp.reset(GrConfigConversionEffect::Create(src->asTexture(), tempDrawInfo.fSwizzle,
bsalomon39826022015-07-23 08:07:21 -0700479 GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
480 }
481 if (fp) {
brianosman898235c2016-04-06 07:38:23 -0700482 // SRGBTODO: AllowSRGBInputs? (We could force it on here, so we don't need the
483 // per-texture override in config conversion effect?)
egdanielc4b72722015-11-23 13:20:41 -0800484 GrPaint paint;
bsalomonac856c92015-08-27 06:30:17 -0700485 paint.addColorFragmentProcessor(fp);
egdanielc4b72722015-11-23 13:20:41 -0800486 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
bsalomon39826022015-07-23 08:07:21 -0700487 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
robertphillips6c7e3252016-04-27 10:47:51 -0700488 sk_sp<GrDrawContext> drawContext(
489 this->drawContext(sk_ref_sp(temp->asRenderTarget())));
cdalton846c0512016-05-13 10:25:00 -0700490 drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect, nullptr);
bsalomon6cb3cbe2015-07-30 07:34:27 -0700491 surfaceToRead.reset(SkRef(temp.get()));
bsalomon39826022015-07-23 08:07:21 -0700492 left = 0;
493 top = 0;
494 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000495 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000496 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000497 }
joshualitt5c55fef2014-10-31 14:04:35 -0700498
bsalomon39826022015-07-23 08:07:21 -0700499 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000500 return false;
501 }
bsalomon39826022015-07-23 08:07:21 -0700502 GrPixelConfig configToRead = dstConfig;
503 if (didTempDraw) {
bsalomon6cb3cbe2015-07-30 07:34:27 -0700504 this->flushSurfaceWrites(surfaceToRead);
bsalomon6c9cd552016-01-22 07:17:34 -0800505 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700506 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700507 if (!fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead, buffer,
508 rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700509 return false;
510 }
511
512 // Perform umpremul conversion if we weren't able to perform it as a draw.
513 if (unpremul) {
reed@google.com7111d462014-03-25 16:20:24 +0000514 SkDstPixelInfo dstPI;
halcanary96fcdcc2015-08-27 07:41:13 -0700515 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, nullptr)) {
reed@google.com7111d462014-03-25 16:20:24 +0000516 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000517 }
reed@google.com7111d462014-03-25 16:20:24 +0000518 dstPI.fAlphaType = kUnpremul_SkAlphaType;
519 dstPI.fPixels = buffer;
520 dstPI.fRowBytes = rowBytes;
521
522 SkSrcPixelInfo srcPI;
bsalomon39826022015-07-23 08:07:21 -0700523 srcPI.fColorType = dstPI.fColorType;
reed@google.com7111d462014-03-25 16:20:24 +0000524 srcPI.fAlphaType = kPremul_SkAlphaType;
525 srcPI.fPixels = buffer;
526 srcPI.fRowBytes = rowBytes;
527
528 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000529 }
530 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000531}
532
brianosman2d1ee792016-05-05 12:24:31 -0700533bool GrContext::applyGamma(GrRenderTarget* dst, GrTexture* src, SkScalar gamma){
534 ASSERT_SINGLE_OWNER
535 RETURN_FALSE_IF_ABANDONED
536 ASSERT_OWNED_RESOURCE(dst);
537 ASSERT_OWNED_RESOURCE(src);
538 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::applyGamma");
539
540 // Dimensions must match exactly.
541 if (dst->width() != src->width() || dst->height() != src->height()) {
542 return false;
543 }
544
545 SkSurfaceProps props(SkSurfaceProps::kGammaCorrect_Flag,
546 SkSurfaceProps::kLegacyFontHost_InitType);
547 sk_sp<GrDrawContext> drawContext(this->drawContext(sk_ref_sp(dst), &props));
548 if (!drawContext) {
549 return false;
550 }
551
552 GrPaint paint;
brianosmanfe4d5d32016-05-11 06:49:32 -0700553 paint.addColorTextureProcessor(src, GrCoordTransform::MakeDivByTextureWHMatrix(src));
554 if (!SkScalarNearlyEqual(gamma, 1.0f)) {
555 paint.addColorFragmentProcessor(GrGammaEffect::Create(gamma))->unref();
brianosman2d1ee792016-05-05 12:24:31 -0700556 }
557 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
558 paint.setGammaCorrect(true);
559
560 SkRect rect;
561 src->getBoundsRect(&rect);
cdalton846c0512016-05-13 10:25:00 -0700562 drawContext->drawRect(GrNoClip(), paint, SkMatrix::I(), rect);
brianosman2d1ee792016-05-05 12:24:31 -0700563
564 this->flushSurfaceWrites(dst);
565 return true;
566}
567
bsalomonc49e8682015-06-30 11:37:35 -0700568void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800569 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800570 RETURN_IF_ABANDONED
bsalomon87a94eb2014-11-03 14:28:32 -0800571 SkASSERT(surface);
572 ASSERT_OWNED_RESOURCE(surface);
573 if (surface->surfacePriv().hasPendingIO()) {
574 this->flush();
575 }
576 GrRenderTarget* rt = surface->asRenderTarget();
577 if (fGpu && rt) {
578 fGpu->resolveRenderTarget(rt);
bsalomon41ebbdd2014-08-04 08:31:39 -0700579 }
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000580}
581
bsalomonb8fea972016-02-16 07:34:17 -0800582bool GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
583 const SkIPoint& dstPoint) {
joshualitt1de610a2016-01-06 08:26:09 -0800584 ASSERT_SINGLE_OWNER
bsalomonb8fea972016-02-16 07:34:17 -0800585 RETURN_FALSE_IF_ABANDONED
joshualittbc907352016-01-13 06:45:40 -0800586 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::copySurface");
587
robertphillipsea461502015-05-26 11:38:03 -0700588 if (!src || !dst) {
bsalomonb8fea972016-02-16 07:34:17 -0800589 return false;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000590 }
bsalomone3d4bf22014-09-23 09:15:03 -0700591 ASSERT_OWNED_RESOURCE(src);
junov2bb52102014-09-29 10:18:59 -0700592 ASSERT_OWNED_RESOURCE(dst);
Brian Salomon34a98952014-09-24 11:41:24 -0400593
robertphillipsea461502015-05-26 11:38:03 -0700594 if (!dst->asRenderTarget()) {
bsalomonb8fea972016-02-16 07:34:17 -0800595 SkIRect clippedSrcRect;
596 SkIPoint clippedDstPoint;
597 if (!GrCopySurfaceBatch::ClipSrcRectAndDstPoint(dst, src, srcRect, dstPoint,
598 &clippedSrcRect, &clippedDstPoint)) {
599 return false;
600 }
601 // If we don't have an RT for the dst then we won't have a GrDrawContext to insert the
602 // the copy surface into. In the future we plan to have a more limited Context type
603 // (GrCopyContext?) that has the subset of GrDrawContext operations that should be
604 // allowed on textures that aren't render targets.
605 // For now we just flush any writes to the src and issue an immediate copy to the dst.
606 src->flushWrites();
607 return fGpu->copySurface(dst, src, clippedSrcRect, clippedDstPoint);
robertphillipsea461502015-05-26 11:38:03 -0700608 }
robertphillips6c7e3252016-04-27 10:47:51 -0700609 sk_sp<GrDrawContext> drawContext(this->drawContext(sk_ref_sp(dst->asRenderTarget())));
kjlubick0eed9452016-02-11 12:05:24 -0800610 if (!drawContext) {
bsalomonb8fea972016-02-16 07:34:17 -0800611 return false;
bsalomonf80bfed2014-10-07 05:56:02 -0700612 }
kjlubick0eed9452016-02-11 12:05:24 -0800613
bsalomonb8fea972016-02-16 07:34:17 -0800614 if (!drawContext->copySurface(src, srcRect, dstPoint)) {
615 return false;
kjlubick0eed9452016-02-11 12:05:24 -0800616 }
bsalomonb8fea972016-02-16 07:34:17 -0800617 return true;
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000618}
619
bsalomonf80bfed2014-10-07 05:56:02 -0700620void GrContext::flushSurfaceWrites(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800621 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800622 RETURN_IF_ABANDONED
bsalomonf80bfed2014-10-07 05:56:02 -0700623 if (surface->surfacePriv().hasPendingWrite()) {
624 this->flush();
625 }
626}
627
bsalomon@google.com27847de2011-02-22 20:59:41 +0000628////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000629int GrContext::getRecommendedSampleCount(GrPixelConfig config,
630 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800631 ASSERT_SINGLE_OWNER
632
bsalomon76228632015-05-29 08:02:10 -0700633 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000634 return 0;
635 }
636 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700637 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000638 if (dpi >= 250.0f) {
639 chosenSampleCount = 4;
640 } else {
641 chosenSampleCount = 16;
642 }
643 }
egdanieleed519e2016-01-15 11:36:18 -0800644 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000645}
646
robertphillips77a2e522015-10-17 07:43:27 -0700647
robertphillips6c7e3252016-04-27 10:47:51 -0700648sk_sp<GrDrawContext> GrContext::drawContext(sk_sp<GrRenderTarget> rt,
649 const SkSurfaceProps* surfaceProps) {
joshualitt1de610a2016-01-06 08:26:09 -0800650 ASSERT_SINGLE_OWNER
robertphillips6c7e3252016-04-27 10:47:51 -0700651 return fDrawingManager->drawContext(std::move(rt), surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700652}
653
robertphillips76948d42016-05-04 12:47:41 -0700654sk_sp<GrDrawContext> GrContext::newDrawContext(SkBackingFit fit,
robertphillipsd4c741e2016-04-28 09:55:15 -0700655 int width, int height,
656 GrPixelConfig config,
657 int sampleCnt,
robertphillipsa8966a82016-05-09 06:45:37 -0700658 GrSurfaceOrigin origin,
659 const SkSurfaceProps* surfaceProps) {
robertphillipsd4c741e2016-04-28 09:55:15 -0700660 GrSurfaceDesc desc;
661 desc.fFlags = kRenderTarget_GrSurfaceFlag;
662 desc.fOrigin = origin;
663 desc.fWidth = width;
664 desc.fHeight = height;
665 desc.fConfig = config;
666 desc.fSampleCnt = sampleCnt;
667
668 sk_sp<GrTexture> tex;
robertphillips76948d42016-05-04 12:47:41 -0700669 if (SkBackingFit::kExact == fit) {
robertphillipsd4c741e2016-04-28 09:55:15 -0700670 tex.reset(this->textureProvider()->createTexture(desc, SkBudgeted::kYes));
671 } else {
672 tex.reset(this->textureProvider()->createApproxTexture(desc));
673 }
674 if (!tex) {
675 return nullptr;
676 }
677
robertphillipsa8966a82016-05-09 06:45:37 -0700678 sk_sp<GrDrawContext> drawContext(this->drawContext(sk_ref_sp(tex->asRenderTarget()),
679 surfaceProps));
robertphillipsd4c741e2016-04-28 09:55:15 -0700680 if (!drawContext) {
681 return nullptr;
682 }
683
684 return drawContext;
685}
686
joshualitt1de610a2016-01-06 08:26:09 -0800687bool GrContext::abandoned() const {
688 ASSERT_SINGLE_OWNER
robertphillips77a2e522015-10-17 07:43:27 -0700689 return fDrawingManager->abandoned();
690}
691
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000692namespace {
693void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
694 GrConfigConversionEffect::PMConversion pmToUPM;
695 GrConfigConversionEffect::PMConversion upmToPM;
696 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
697 *pmToUPMValue = pmToUPM;
698 *upmToPMValue = upmToPM;
699}
700}
701
bsalomon6c6f6582015-09-10 08:12:46 -0700702void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800703 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700704 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) {
705 SkAutoMutexAcquire ama(fTestPMConversionsMutex);
706 if (!fDidTestPMConversions) {
707 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
708 fDidTestPMConversions = true;
709 }
710 }
711}
712
bsalomon4a339522015-10-06 08:40:50 -0700713const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800714 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700715 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800716 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700717 // We should have already called this->testPMConversionsIfNecessary().
718 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000719 GrConfigConversionEffect::PMConversion pmToUPM =
720 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
721 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
bsalomon6c9cd552016-01-22 07:17:34 -0800722 return GrConfigConversionEffect::Create(texture, swizzle, pmToUPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000723 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700724 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000725 }
726}
727
bsalomon4a339522015-10-06 08:40:50 -0700728const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800729 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700730 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800731 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700732 // We should have already called this->testPMConversionsIfNecessary().
733 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000734 GrConfigConversionEffect::PMConversion upmToPM =
735 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
736 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
bsalomon6c9cd552016-01-22 07:17:34 -0800737 return GrConfigConversionEffect::Create(texture, swizzle, upmToPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000738 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700739 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000740 }
741}
742
bsalomon636e8022015-07-29 06:08:46 -0700743bool GrContext::didFailPMUPMConversionTest() const {
joshualitt1de610a2016-01-06 08:26:09 -0800744 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700745 // We should have already called this->testPMConversionsIfNecessary().
746 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700747 // The PM<->UPM tests fail or succeed together so we only need to check one.
bsalomon6c6f6582015-09-10 08:12:46 -0700748 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion;
bsalomon636e8022015-07-29 06:08:46 -0700749}
750
bsalomon37f9a262015-02-02 13:00:10 -0800751//////////////////////////////////////////////////////////////////////////////
752
753void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800754 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800755 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800756 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800757 }
758 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800759 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800760 }
761}
762
763void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800764 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800765 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800766}
767
ericrk0a5fa482015-09-15 14:16:10 -0700768//////////////////////////////////////////////////////////////////////////////
769
770void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800771 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700772 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
773}