blob: d5f9f9ce4cf2d9f7b06e90e57e30699a805c4154 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
bsalomon@google.com27847de2011-02-22 20:59:41 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
bsalomon@google.com27847de2011-02-22 20:59:41 +00007 */
8
bsalomon@google.com1fadb202011-12-12 16:10:08 +00009#include "GrContext.h"
10
jvanverth@google.combfe2b9d2013-09-06 16:57:29 +000011#include "GrAARectRenderer.h"
joshualitt0823bfa2015-02-27 10:06:15 -080012#include "GrBatch.h"
joshualitt7c3a2f82015-03-31 13:32:05 -070013#include "GrBatchFontCache.h"
joshualitt0823bfa2015-02-27 10:06:15 -080014#include "GrBatchTarget.h"
joshualitte5902662015-05-11 08:18:35 -070015#include "GrBatchTest.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070016#include "GrCaps.h"
bsalomon682c2692015-05-22 14:01:46 -070017#include "GrContextOptions.h"
joshualitt5478d422014-11-14 16:00:38 -080018#include "GrDefaultGeoProcFactory.h"
robertphillipsea461502015-05-26 11:38:03 -070019#include "GrDrawContext.h"
bsalomon453cf402014-11-11 14:15:57 -080020#include "GrGpuResource.h"
bsalomon3582d3e2015-02-13 14:20:05 -080021#include "GrGpuResourcePriv.h"
joshualitt5478d422014-11-14 16:00:38 -080022#include "GrGpu.h"
joshualittbb87b212015-05-19 14:28:04 -070023#include "GrImmediateDrawTarget.h"
commit-bot@chromium.orgdcb8ef92014-03-27 11:26:10 +000024#include "GrIndexBuffer.h"
commit-bot@chromium.org47841822014-03-27 14:19:17 +000025#include "GrInOrderDrawBuffer.h"
robertphillips@google.come930a072014-04-03 00:34:27 +000026#include "GrLayerCache.h"
commit-bot@chromium.org81312832013-03-22 18:34:09 +000027#include "GrOvalRenderer.h"
bsalomon@google.com27847de2011-02-22 20:59:41 +000028#include "GrPathRenderer.h"
tomhudson@google.comd22b6e42011-06-24 15:53:40 +000029#include "GrPathUtils.h"
bsalomon6bc1b5f2015-02-23 09:06:38 -080030#include "GrRenderTargetPriv.h"
bsalomon0ea80f42015-02-11 10:49:59 -080031#include "GrResourceCache.h"
bsalomond309e7a2015-04-30 14:18:54 -070032#include "GrResourceProvider.h"
robertphillips@google.com72176b22012-05-23 13:19:12 +000033#include "GrSoftwarePathRenderer.h"
egdanield58a0ba2014-06-11 10:30:05 -070034#include "GrStrokeInfo.h"
bsalomonafbf2d62014-09-30 12:18:44 -070035#include "GrSurfacePriv.h"
joshualittb7133be2015-04-08 09:08:31 -070036#include "GrTextBlobCache.h"
bsalomonafbf2d62014-09-30 12:18:44 -070037#include "GrTexturePriv.h"
egdanielbbcb38d2014-06-19 10:19:29 -070038#include "GrTraceMarker.h"
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +000039#include "GrTracing.h"
bsalomoncb8979d2015-05-05 09:51:38 -070040#include "GrVertices.h"
egdanield58a0ba2014-06-11 10:30:05 -070041#include "SkDashPathPriv.h"
bsalomon81beccc2014-10-13 12:32:55 -070042#include "SkConfig8888.h"
reed@google.com7111d462014-03-25 16:20:24 +000043#include "SkGr.h"
commit-bot@chromium.org47841822014-03-27 14:19:17 +000044#include "SkRRect.h"
sugoi@google.com5f74cf82012-12-17 21:16:45 +000045#include "SkStrokeRec.h"
commit-bot@chromium.orgdcb8ef92014-03-27 11:26:10 +000046#include "SkTLazy.h"
commit-bot@chromium.org47841822014-03-27 14:19:17 +000047#include "SkTLS.h"
commit-bot@chromium.org933e65d2014-03-20 20:00:24 +000048#include "SkTraceEvent.h"
bsalomon@google.com27847de2011-02-22 20:59:41 +000049
joshualitt5478d422014-11-14 16:00:38 -080050#include "effects/GrConfigConversionEffect.h"
51#include "effects/GrDashingEffect.h"
52#include "effects/GrSingleTextureEffect.h"
53
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000054#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
robertphillipsea461502015-05-26 11:38:03 -070055#define RETURN_IF_ABANDONED if (fDrawingMgr.abandoned()) { return; }
56#define RETURN_FALSE_IF_ABANDONED if (fDrawingMgr.abandoned()) { return false; }
57#define RETURN_NULL_IF_ABANDONED if (fDrawingMgr.abandoned()) { return NULL; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000058
bsalomonf21dab92014-11-13 13:33:28 -080059
robertphillipsea461502015-05-26 11:38:03 -070060////////////////////////////////////////////////////////////////////////////////
61
62void GrContext::DrawingMgr::init(GrContext* context) {
robertphillips2334fb62015-06-17 05:43:33 -070063 fContext = context;
64
robertphillipsea461502015-05-26 11:38:03 -070065#ifdef IMMEDIATE_MODE
66 fDrawTarget = SkNEW_ARGS(GrImmediateDrawTarget, (context));
67#else
68 fDrawTarget = SkNEW_ARGS(GrInOrderDrawBuffer, (context));
69#endif
robertphillips2334fb62015-06-17 05:43:33 -070070}
bsalomon781d5822015-06-16 15:03:11 -070071
robertphillips2334fb62015-06-17 05:43:33 -070072void GrContext::DrawingMgr::cleanup() {
73 SkSafeSetNull(fDrawTarget);
74 for (int i = 0; i < kNumPixelGeometries; ++i) {
75 SkSafeSetNull(fDrawContext[i][0]);
76 SkSafeSetNull(fDrawContext[i][1]);
77 }
robertphillipsea461502015-05-26 11:38:03 -070078}
79
80GrContext::DrawingMgr::~DrawingMgr() {
robertphillips2334fb62015-06-17 05:43:33 -070081 this->cleanup();
robertphillipsea461502015-05-26 11:38:03 -070082}
83
84void GrContext::DrawingMgr::abandon() {
85 SkSafeSetNull(fDrawTarget);
robertphillips2334fb62015-06-17 05:43:33 -070086 for (int i = 0; i < kNumPixelGeometries; ++i) {
87 for (int j = 0; j < kNumDFTOptions; ++j) {
88 if (fDrawContext[i][j]) {
89 SkSafeSetNull(fDrawContext[i][j]->fDrawTarget);
90 SkSafeSetNull(fDrawContext[i][j]);
91 }
92 }
93 }
robertphillipsea461502015-05-26 11:38:03 -070094}
95
96void GrContext::DrawingMgr::purgeResources() {
97 if (fDrawTarget) {
98 fDrawTarget->purgeResources();
bsalomonf21dab92014-11-13 13:33:28 -080099 }
robertphillipsea461502015-05-26 11:38:03 -0700100}
bsalomonf21dab92014-11-13 13:33:28 -0800101
robertphillipsea461502015-05-26 11:38:03 -0700102void GrContext::DrawingMgr::reset() {
103 if (fDrawTarget) {
104 fDrawTarget->reset();
105 }
106}
107
108void GrContext::DrawingMgr::flush() {
109 if (fDrawTarget) {
110 fDrawTarget->flush();
111 }
112}
113
robertphillips2334fb62015-06-17 05:43:33 -0700114GrDrawContext* GrContext::DrawingMgr::drawContext(const SkDeviceProperties* devProps, bool useDFT) {
robertphillipsea461502015-05-26 11:38:03 -0700115 if (this->abandoned()) {
116 return NULL;
117 }
robertphillips2334fb62015-06-17 05:43:33 -0700118
119 const SkDeviceProperties defProps;
120 if (!devProps) {
121 devProps = &defProps;
122 }
123
124 SkASSERT(devProps->pixelGeometry() < kNumPixelGeometries);
125 if (!fDrawContext[devProps->pixelGeometry()][useDFT]) {
126 fDrawContext[devProps->pixelGeometry()][useDFT] =
127 SkNEW_ARGS(GrDrawContext, (fContext, fDrawTarget, *devProps, useDFT));
128 }
129
130 SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fDevProps->pixelGeometry() ==
131 devProps->pixelGeometry());
132 SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fDevProps->gamma() ==
133 devProps->gamma());
134 SkASSERT(fDrawContext[devProps->pixelGeometry()][useDFT]->fUseDFT == useDFT);
135
136 return fDrawContext[devProps->pixelGeometry()][useDFT];
robertphillipsea461502015-05-26 11:38:03 -0700137}
138
139////////////////////////////////////////////////////////////////////////////////
140
bsalomonf21dab92014-11-13 13:33:28 -0800141
bsalomon682c2692015-05-22 14:01:46 -0700142GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
143 GrContextOptions defaultOptions;
144 return Create(backend, backendContext, defaultOptions);
145}
bsalomonf28cff72015-05-22 12:25:41 -0700146
bsalomon682c2692015-05-22 14:01:46 -0700147GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
148 const GrContextOptions& options) {
149 GrContext* context = SkNEW(GrContext);
150
151 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000152 return context;
153 } else {
154 context->unref();
155 return NULL;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000156 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000157}
158
joshualitt0acd0d32015-05-07 08:23:19 -0700159static int32_t gNextID = 1;
160static int32_t next_id() {
161 int32_t id;
162 do {
163 id = sk_atomic_inc(&gNextID);
164 } while (id == SK_InvalidGenID);
165 return id;
166}
167
bsalomon682c2692015-05-22 14:01:46 -0700168GrContext::GrContext() : fUniqueID(next_id()) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000169 fGpu = NULL;
bsalomon76228632015-05-29 08:02:10 -0700170 fCaps = NULL;
bsalomond309e7a2015-04-30 14:18:54 -0700171 fResourceCache = NULL;
172 fResourceProvider = NULL;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000173 fPathRendererChain = NULL;
174 fSoftwarePathRenderer = NULL;
joshualitt7c3a2f82015-03-31 13:32:05 -0700175 fBatchFontCache = NULL;
bsalomonf21dab92014-11-13 13:33:28 -0800176 fFlushToReduceCacheSize = false;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000177}
178
bsalomon682c2692015-05-22 14:01:46 -0700179bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
180 const GrContextOptions& options) {
robertphillipsea461502015-05-26 11:38:03 -0700181 SkASSERT(!fGpu);
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000182
bsalomon682c2692015-05-22 14:01:46 -0700183 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -0700184 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000185 return false;
186 }
bsalomon33435572014-11-05 14:47:41 -0800187 this->initCommon();
188 return true;
189}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000190
bsalomon33435572014-11-05 14:47:41 -0800191void GrContext::initCommon() {
bsalomon76228632015-05-29 08:02:10 -0700192 fCaps = SkRef(fGpu->caps());
bsalomon0ea80f42015-02-11 10:49:59 -0800193 fResourceCache = SkNEW(GrResourceCache);
194 fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
bsalomond309e7a2015-04-30 14:18:54 -0700195 fResourceProvider = SkNEW_ARGS(GrResourceProvider, (fGpu, fResourceCache));
commit-bot@chromium.org1836d332013-07-16 22:55:03 +0000196
robertphillips4ec84da2014-06-24 13:10:43 -0700197 fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
robertphillips@google.come930a072014-04-03 00:34:27 +0000198
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000199 fDidTestPMConversions = false;
200
robertphillipsea461502015-05-26 11:38:03 -0700201 fDrawingMgr.init(this);
joshualitt7c3a2f82015-03-31 13:32:05 -0700202
203 // GrBatchFontCache will eventually replace GrFontCache
joshualitt62db8ba2015-04-09 08:22:37 -0700204 fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this));
joshualittb7133be2015-04-08 09:08:31 -0700205
joshualitt0db6dfa2015-04-10 07:01:30 -0700206 fTextBlobCache.reset(SkNEW_ARGS(GrTextBlobCache, (TextBlobCacheOverBudgetCB, this)));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000207}
208
bsalomon@google.com27847de2011-02-22 20:59:41 +0000209GrContext::~GrContext() {
robertphillipsea461502015-05-26 11:38:03 -0700210 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700211 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000212 return;
213 }
214
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000215 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000216
robertphillips2334fb62015-06-17 05:43:33 -0700217 fDrawingMgr.cleanup();
218
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000219 for (int i = 0; i < fCleanUpData.count(); ++i) {
220 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
221 }
222
bsalomond309e7a2015-04-30 14:18:54 -0700223 SkDELETE(fResourceProvider);
bsalomon0ea80f42015-02-11 10:49:59 -0800224 SkDELETE(fResourceCache);
joshualitt7c3a2f82015-03-31 13:32:05 -0700225 SkDELETE(fBatchFontCache);
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000226
bsalomon@google.com205d4602011-04-25 12:43:45 +0000227 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700228 fCaps->unref();
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000229 SkSafeUnref(fPathRendererChain);
230 SkSafeUnref(fSoftwarePathRenderer);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000231}
232
bsalomon2354f842014-07-28 13:48:36 -0700233void GrContext::abandonContext() {
bsalomond309e7a2015-04-30 14:18:54 -0700234 fResourceProvider->abandon();
bsalomon@google.com205d4602011-04-25 12:43:45 +0000235 // abandon first to so destructors
236 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800237 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700238
robertphillipse3371302014-09-17 06:01:06 -0700239 fGpu->contextAbandoned();
bsalomon@google.com205d4602011-04-25 12:43:45 +0000240
bsalomon@google.com30085192011-08-19 15:42:31 +0000241 // a path renderer may be holding onto resources that
242 // are now unusable
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000243 SkSafeSetNull(fPathRendererChain);
244 SkSafeSetNull(fSoftwarePathRenderer);
bsalomon@google.com30085192011-08-19 15:42:31 +0000245
robertphillipsea461502015-05-26 11:38:03 -0700246 fDrawingMgr.abandon();
bsalomon@google.com205d4602011-04-25 12:43:45 +0000247
joshualitt7c3a2f82015-03-31 13:32:05 -0700248 fBatchFontCache->freeAll();
robertphillips@google.come930a072014-04-03 00:34:27 +0000249 fLayerCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700250 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000251}
252
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000253void GrContext::resetContext(uint32_t state) {
254 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000255}
256
257void GrContext::freeGpuResources() {
258 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000259
robertphillipsea461502015-05-26 11:38:03 -0700260 fDrawingMgr.purgeResources();
robertphillips@google.comff175842012-05-14 19:31:39 +0000261
joshualitt7c3a2f82015-03-31 13:32:05 -0700262 fBatchFontCache->freeAll();
robertphillips@google.come930a072014-04-03 00:34:27 +0000263 fLayerCache->freeAll();
bsalomon@google.com30085192011-08-19 15:42:31 +0000264 // a path renderer may be holding onto resources
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000265 SkSafeSetNull(fPathRendererChain);
266 SkSafeSetNull(fSoftwarePathRenderer);
bsalomon3033b9f2015-04-13 11:09:56 -0700267
268 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000269}
270
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000271void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
bsalomon71cb0c22014-11-14 12:10:14 -0800272 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800273 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800274 }
275 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800276 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800277 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000278}
279
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000280////////////////////////////////////////////////////////////////////////////////
281
bsalomon71cb0c22014-11-14 12:10:14 -0800282void GrContext::OverBudgetCB(void* data) {
bsalomon66a450f2014-11-13 13:19:10 -0800283 SkASSERT(data);
bsalomonf21dab92014-11-13 13:33:28 -0800284
bsalomon66a450f2014-11-13 13:19:10 -0800285 GrContext* context = reinterpret_cast<GrContext*>(data);
bsalomonf21dab92014-11-13 13:33:28 -0800286
287 // Flush the InOrderDrawBuffer to possibly free up some textures
288 context->fFlushToReduceCacheSize = true;
commit-bot@chromium.orgcae27fe2013-07-10 10:14:35 +0000289}
290
joshualitt0db6dfa2015-04-10 07:01:30 -0700291void GrContext::TextBlobCacheOverBudgetCB(void* data) {
292 SkASSERT(data);
293
294 // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
295 // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move
296 // drawText calls to below the GrContext level, but this is not trivial because they call
297 // drawPath on SkGpuDevice
298 GrContext* context = reinterpret_cast<GrContext*>(data);
299 context->flush();
300}
301
bsalomon@google.com27847de2011-02-22 20:59:41 +0000302////////////////////////////////////////////////////////////////////////////////
303
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000304void GrContext::flush(int flagsBitfield) {
robertphillipsea461502015-05-26 11:38:03 -0700305 RETURN_IF_ABANDONED
robertphillips@google.come7db8d62013-07-04 11:48:52 +0000306
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000307 if (kDiscard_FlushBit & flagsBitfield) {
robertphillipsea461502015-05-26 11:38:03 -0700308 fDrawingMgr.reset();
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000309 } else {
robertphillipsea461502015-05-26 11:38:03 -0700310 fDrawingMgr.flush();
junov@google.com53a55842011-06-08 22:55:10 +0000311 }
bsalomon3f324322015-04-08 11:01:54 -0700312 fResourceCache->notifyFlushOccurred();
bsalomonf21dab92014-11-13 13:33:28 -0800313 fFlushToReduceCacheSize = false;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000314}
315
bsalomon81beccc2014-10-13 12:32:55 -0700316bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
317 const void* inPixels, size_t outRowBytes, void* outPixels) {
318 SkSrcPixelInfo srcPI;
jvanverthfa1e8a72014-12-22 08:31:49 -0800319 if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, NULL)) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000320 return false;
321 }
bsalomon81beccc2014-10-13 12:32:55 -0700322 srcPI.fAlphaType = kUnpremul_SkAlphaType;
323 srcPI.fPixels = inPixels;
324 srcPI.fRowBytes = inRowBytes;
325
326 SkDstPixelInfo dstPI;
327 dstPI.fColorType = srcPI.fColorType;
328 dstPI.fAlphaType = kPremul_SkAlphaType;
329 dstPI.fPixels = outPixels;
330 dstPI.fRowBytes = outRowBytes;
331
332 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000333}
334
bsalomon81beccc2014-10-13 12:32:55 -0700335bool GrContext::writeSurfacePixels(GrSurface* surface,
336 int left, int top, int width, int height,
337 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
338 uint32_t pixelOpsFlags) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800339 RETURN_FALSE_IF_ABANDONED
bsalomon81beccc2014-10-13 12:32:55 -0700340 {
341 GrTexture* texture = NULL;
342 if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asTexture()) &&
343 fGpu->canWriteTexturePixels(texture, srcConfig)) {
344
345 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
346 surface->surfacePriv().hasPendingIO()) {
347 this->flush();
348 }
349 return fGpu->writeTexturePixels(texture, left, top, width, height,
350 srcConfig, buffer, rowBytes);
351 // Don't need to check kFlushWrites_PixelOp here, we just did a direct write so the
352 // upload is already flushed.
353 }
354 }
355
356 // If we didn't do a direct texture write then we upload the pixels to a texture and draw.
357 GrRenderTarget* renderTarget = surface->asRenderTarget();
robertphillipsea461502015-05-26 11:38:03 -0700358 if (!renderTarget) {
bsalomon81beccc2014-10-13 12:32:55 -0700359 return false;
360 }
361
362 // We ignore the preferred config unless it is a R/B swap of the src config. In that case
363 // we will upload the original src data to a scratch texture but we will spoof it as the swapped
364 // config. This scratch will then have R and B swapped. We correct for this by swapping again
365 // when drawing the scratch to the dst using a conversion effect.
366 bool swapRAndB = false;
367 GrPixelConfig writeConfig = srcConfig;
368 if (GrPixelConfigSwapRAndB(srcConfig) ==
369 fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
370 writeConfig = GrPixelConfigSwapRAndB(srcConfig);
371 swapRAndB = true;
372 }
373
bsalomonf2703d82014-10-28 14:33:06 -0700374 GrSurfaceDesc desc;
bsalomon81beccc2014-10-13 12:32:55 -0700375 desc.fWidth = width;
376 desc.fHeight = height;
377 desc.fConfig = writeConfig;
bsalomond309e7a2015-04-30 14:18:54 -0700378 SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(desc,
379 GrTextureProvider::kApprox_ScratchTexMatch));
bsalomone3059732014-10-14 11:47:22 -0700380 if (!texture) {
bsalomon81beccc2014-10-13 12:32:55 -0700381 return false;
382 }
383
384 SkAutoTUnref<const GrFragmentProcessor> fp;
385 SkMatrix textureMatrix;
386 textureMatrix.setIDiv(texture->width(), texture->height());
387
388 // allocate a tmp buffer and sw convert the pixels to premul
389 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
390
391 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
392 if (!GrPixelConfigIs8888(srcConfig)) {
393 return false;
394 }
395 fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
396 // handle the unpremul step on the CPU if we couldn't create an effect to do it.
robertphillipsea461502015-05-26 11:38:03 -0700397 if (!fp) {
bsalomon81beccc2014-10-13 12:32:55 -0700398 size_t tmpRowBytes = 4 * width;
399 tmpPixels.reset(width * height);
400 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
401 tmpPixels.get())) {
402 return false;
403 }
404 rowBytes = tmpRowBytes;
405 buffer = tmpPixels.get();
406 }
407 }
robertphillipsea461502015-05-26 11:38:03 -0700408 if (!fp) {
bsalomon81beccc2014-10-13 12:32:55 -0700409 fp.reset(GrConfigConversionEffect::Create(texture,
410 swapRAndB,
411 GrConfigConversionEffect::kNone_PMConversion,
412 textureMatrix));
413 }
414
415 // Even if the client told us not to flush, we still flush here. The client may have known that
416 // writes to the original surface caused no data hazards, but they can't know that the scratch
417 // we just got is safe.
418 if (texture->surfacePriv().hasPendingIO()) {
419 this->flush();
420 }
421 if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
422 writeConfig, buffer, rowBytes)) {
423 return false;
424 }
425
426 SkMatrix matrix;
427 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
428
robertphillipsea461502015-05-26 11:38:03 -0700429 GrDrawContext* drawContext = this->drawContext();
430 if (!drawContext) {
431 return false;
bsalomon81beccc2014-10-13 12:32:55 -0700432 }
433
robertphillipsea461502015-05-26 11:38:03 -0700434 GrPaint paint;
435 paint.addColorProcessor(fp);
436
437 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
438
439 drawContext->drawRect(renderTarget, GrClip::WideOpen(), paint, matrix, rect, NULL);
440
bsalomon81beccc2014-10-13 12:32:55 -0700441 if (kFlushWrites_PixelOp & pixelOpsFlags) {
442 this->flushSurfaceWrites(surface);
443 }
444
445 return true;
446}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000447
reed@google.com7111d462014-03-25 16:20:24 +0000448// toggles between RGBA and BGRA
449static SkColorType toggle_colortype32(SkColorType ct) {
450 if (kRGBA_8888_SkColorType == ct) {
451 return kBGRA_8888_SkColorType;
452 } else {
453 SkASSERT(kBGRA_8888_SkColorType == ct);
454 return kRGBA_8888_SkColorType;
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000455 }
456}
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000457
bsalomon@google.com0342a852012-08-20 19:22:38 +0000458bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
459 int left, int top, int width, int height,
bsalomon@google.com9c680582013-02-06 18:17:50 +0000460 GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
bsalomon@google.com0342a852012-08-20 19:22:38 +0000461 uint32_t flags) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800462 RETURN_FALSE_IF_ABANDONED
bsalomon@google.combc4b6542011-11-19 13:56:11 +0000463 ASSERT_OWNED_RESOURCE(target);
bsalomon89c62982014-11-03 12:08:42 -0800464 SkASSERT(target);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000465
bsalomonafbf2d62014-09-30 12:18:44 -0700466 if (!(kDontFlush_PixelOpsFlag & flags) && target->surfacePriv().hasPendingWrite()) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000467 this->flush();
468 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000469
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000470 // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
bsalomon@google.com0342a852012-08-20 19:22:38 +0000471
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000472 // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
473 // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
474 bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
bsalomon@google.com9c680582013-02-06 18:17:50 +0000475 width, height, dstConfig,
bsalomon@google.comc4364992011-11-07 15:54:49 +0000476 rowBytes);
bsalomon@google.com9c680582013-02-06 18:17:50 +0000477 // We ignore the preferred config if it is different than our config unless it is an R/B swap.
478 // In that case we'll perform an R and B swap while drawing to a scratch texture of the swapped
479 // config. Then we will call readPixels on the scratch with the swapped config. The swaps during
480 // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
481 // dstConfig.
482 GrPixelConfig readConfig = dstConfig;
483 bool swapRAndB = false;
commit-bot@chromium.org5d1d79a2013-05-24 18:52:52 +0000484 if (GrPixelConfigSwapRAndB(dstConfig) ==
485 fGpu->preferredReadPixelsConfig(dstConfig, target->config())) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000486 readConfig = GrPixelConfigSwapRAndB(readConfig);
487 swapRAndB = true;
488 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000489
bsalomon@google.com0342a852012-08-20 19:22:38 +0000490 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
bsalomon@google.comc4364992011-11-07 15:54:49 +0000491
bsalomon@google.com9c680582013-02-06 18:17:50 +0000492 if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000493 // The unpremul flag is only allowed for these two configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000494 return false;
495 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000496
bsalomon191bcc02014-11-14 11:31:13 -0800497 SkAutoTUnref<GrTexture> tempTexture;
498
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000499 // If the src is a texture and we would have to do conversions after read pixels, we instead
500 // do the conversions by drawing the src to a scratch texture. If we handle any of the
501 // conversions in the draw we set the corresponding bool to false so that we don't reapply it
502 // on the read back pixels.
503 GrTexture* src = target->asTexture();
bsalomon49f085d2014-09-05 13:34:00 -0700504 if (src && (swapRAndB || unpremul || flipY)) {
bsalomon81beccc2014-10-13 12:32:55 -0700505 // Make the scratch a render so we can read its pixels.
bsalomonf2703d82014-10-28 14:33:06 -0700506 GrSurfaceDesc desc;
507 desc.fFlags = kRenderTarget_GrSurfaceFlag;
robertphillips@google.com75b3c962012-06-07 12:08:45 +0000508 desc.fWidth = width;
509 desc.fHeight = height;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000510 desc.fConfig = readConfig;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000511 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
bsalomon@google.comc4ff22a2011-11-10 21:56:21 +0000512
bsalomon@google.com9c680582013-02-06 18:17:50 +0000513 // When a full read back is faster than a partial we could always make the scratch exactly
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000514 // match the passed rect. However, if we see many different size rectangles we will trash
515 // our texture cache and pay the cost of creating and destroying many textures. So, we only
516 // request an exact match when the caller is reading an entire RT.
bsalomond309e7a2015-04-30 14:18:54 -0700517 GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_ScratchTexMatch;
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000518 if (0 == left &&
519 0 == top &&
520 target->width() == width &&
521 target->height() == height &&
522 fGpu->fullReadPixelsIsFasterThanPartial()) {
bsalomond309e7a2015-04-30 14:18:54 -0700523 match = GrTextureProvider::kExact_ScratchTexMatch;
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000524 }
bsalomond309e7a2015-04-30 14:18:54 -0700525 tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match));
bsalomon191bcc02014-11-14 11:31:13 -0800526 if (tempTexture) {
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000527 // compute a matrix to perform the draw
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000528 SkMatrix textureMatrix;
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000529 textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000530 textureMatrix.postIDiv(src->width(), src->height());
531
joshualittb0a8a372014-09-23 09:50:21 -0700532 SkAutoTUnref<const GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000533 if (unpremul) {
joshualittb0a8a372014-09-23 09:50:21 -0700534 fp.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix));
535 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000536 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000537 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000538 }
539 // If we failed to create a PM->UPM effect and have no other conversions to perform then
540 // there is no longer any point to using the scratch.
joshualittb0a8a372014-09-23 09:50:21 -0700541 if (fp || flipY || swapRAndB) {
542 if (!fp) {
543 fp.reset(GrConfigConversionEffect::Create(
544 src, swapRAndB, GrConfigConversionEffect::kNone_PMConversion,
545 textureMatrix));
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000546 }
547 swapRAndB = false; // we will handle the swap in the draw.
bsalomon@google.comc4364992011-11-07 15:54:49 +0000548
robertphillips@google.com13f181f2013-03-02 12:02:08 +0000549 // We protect the existing geometry here since it may not be
550 // clear to the caller that a draw operation (i.e., drawSimpleRect)
551 // can be invoked in this method
joshualitt5c55fef2014-10-31 14:04:35 -0700552 {
robertphillipsea461502015-05-26 11:38:03 -0700553 GrDrawContext* drawContext = this->drawContext();
554 if (!drawContext) {
555 return false;
556 }
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000557
robertphillipsea461502015-05-26 11:38:03 -0700558 GrPaint paint;
559 paint.addColorProcessor(fp);
560
joshualitt5c55fef2014-10-31 14:04:35 -0700561 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
robertphillipsea461502015-05-26 11:38:03 -0700562
563 drawContext->drawRect(tempTexture->asRenderTarget(), GrClip::WideOpen(), paint,
564 SkMatrix::I(), rect, NULL);
565
joshualitt5c55fef2014-10-31 14:04:35 -0700566 // we want to read back from the scratch's origin
567 left = 0;
568 top = 0;
bsalomon191bcc02014-11-14 11:31:13 -0800569 target = tempTexture->asRenderTarget();
joshualitt5c55fef2014-10-31 14:04:35 -0700570 }
571 this->flushSurfaceWrites(target);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000572 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000573 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000574 }
joshualitt5c55fef2014-10-31 14:04:35 -0700575
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000576 if (!fGpu->readPixels(target,
577 left, top, width, height,
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000578 readConfig, buffer, rowBytes)) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000579 return false;
580 }
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000581 // Perform any conversions we weren't able to perform using a scratch texture.
senorblanco@chromium.org3cb406b2013-02-05 19:50:46 +0000582 if (unpremul || swapRAndB) {
reed@google.com7111d462014-03-25 16:20:24 +0000583 SkDstPixelInfo dstPI;
jvanverthfa1e8a72014-12-22 08:31:49 -0800584 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NULL)) {
reed@google.com7111d462014-03-25 16:20:24 +0000585 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000586 }
reed@google.com7111d462014-03-25 16:20:24 +0000587 dstPI.fAlphaType = kUnpremul_SkAlphaType;
588 dstPI.fPixels = buffer;
589 dstPI.fRowBytes = rowBytes;
590
591 SkSrcPixelInfo srcPI;
592 srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : dstPI.fColorType;
593 srcPI.fAlphaType = kPremul_SkAlphaType;
594 srcPI.fPixels = buffer;
595 srcPI.fRowBytes = rowBytes;
596
597 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000598 }
599 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000600}
601
bsalomon87a94eb2014-11-03 14:28:32 -0800602void GrContext::prepareSurfaceForExternalRead(GrSurface* surface) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800603 RETURN_IF_ABANDONED
bsalomon87a94eb2014-11-03 14:28:32 -0800604 SkASSERT(surface);
605 ASSERT_OWNED_RESOURCE(surface);
606 if (surface->surfacePriv().hasPendingIO()) {
607 this->flush();
608 }
609 GrRenderTarget* rt = surface->asRenderTarget();
610 if (fGpu && rt) {
611 fGpu->resolveRenderTarget(rt);
bsalomon41ebbdd2014-08-04 08:31:39 -0700612 }
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000613}
614
bsalomonf80bfed2014-10-07 05:56:02 -0700615void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
616 const SkIPoint& dstPoint, uint32_t pixelOpsFlags) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800617 RETURN_IF_ABANDONED
robertphillipsea461502015-05-26 11:38:03 -0700618 if (!src || !dst) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000619 return;
620 }
bsalomone3d4bf22014-09-23 09:15:03 -0700621 ASSERT_OWNED_RESOURCE(src);
junov2bb52102014-09-29 10:18:59 -0700622 ASSERT_OWNED_RESOURCE(dst);
Brian Salomon34a98952014-09-24 11:41:24 -0400623
bsalomonf80bfed2014-10-07 05:56:02 -0700624 // Since we're going to the draw target and not GPU, no need to check kNoFlush
625 // here.
robertphillipsea461502015-05-26 11:38:03 -0700626 if (!dst->asRenderTarget()) {
junov96c118e2014-09-26 13:09:47 -0700627 return;
628 }
robertphillipsea461502015-05-26 11:38:03 -0700629
630 GrDrawContext* drawContext = this->drawContext();
631 if (!drawContext) {
632 return;
633 }
634
635 drawContext->copySurface(dst->asRenderTarget(), src, srcRect, dstPoint);
bsalomonf80bfed2014-10-07 05:56:02 -0700636
637 if (kFlushWrites_PixelOp & pixelOpsFlags) {
638 this->flush();
639 }
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000640}
641
bsalomonf80bfed2014-10-07 05:56:02 -0700642void GrContext::flushSurfaceWrites(GrSurface* surface) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800643 RETURN_IF_ABANDONED
bsalomonf80bfed2014-10-07 05:56:02 -0700644 if (surface->surfacePriv().hasPendingWrite()) {
645 this->flush();
646 }
647}
648
robertphillips@google.com72176b22012-05-23 13:19:12 +0000649/*
650 * This method finds a path renderer that can draw the specified path on
651 * the provided target.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000652 * Due to its expense, the software path renderer has split out so it can
robertphillips@google.com72176b22012-05-23 13:19:12 +0000653 * can be individually allowed/disallowed via the "allowSW" boolean.
654 */
joshualitt9853cce2014-11-17 14:22:48 -0800655GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -0800656 const GrPipelineBuilder* pipelineBuilder,
joshualitt8059eb92014-12-29 15:10:07 -0800657 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800658 const SkPath& path,
kkinnunen18996512015-04-26 23:18:49 -0700659 const GrStrokeInfo& stroke,
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000660 bool allowSW,
661 GrPathRendererChain::DrawType drawType,
662 GrPathRendererChain::StencilSupport* stencilSupport) {
663
robertphillipsea461502015-05-26 11:38:03 -0700664 if (!fPathRendererChain) {
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000665 fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
bsalomon@google.com30085192011-08-19 15:42:31 +0000666 }
robertphillips@google.com72176b22012-05-23 13:19:12 +0000667
joshualitt9853cce2014-11-17 14:22:48 -0800668 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target,
egdaniel8dd688b2015-01-22 10:16:09 -0800669 pipelineBuilder,
joshualitt8059eb92014-12-29 15:10:07 -0800670 viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800671 path,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000672 stroke,
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000673 drawType,
674 stencilSupport);
robertphillips@google.com72176b22012-05-23 13:19:12 +0000675
robertphillipsea461502015-05-26 11:38:03 -0700676 if (!pr && allowSW) {
677 if (!fSoftwarePathRenderer) {
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000678 fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
robertphillips@google.com72176b22012-05-23 13:19:12 +0000679 }
robertphillips@google.com72176b22012-05-23 13:19:12 +0000680 pr = fSoftwarePathRenderer;
681 }
682
683 return pr;
bsalomon@google.com30085192011-08-19 15:42:31 +0000684}
685
bsalomon@google.com27847de2011-02-22 20:59:41 +0000686////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000687int GrContext::getRecommendedSampleCount(GrPixelConfig config,
688 SkScalar dpi) const {
bsalomon76228632015-05-29 08:02:10 -0700689 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000690 return 0;
691 }
692 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700693 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000694 if (dpi >= 250.0f) {
695 chosenSampleCount = 4;
696 } else {
697 chosenSampleCount = 16;
698 }
699 }
700 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ?
701 chosenSampleCount : 0;
702}
703
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000704namespace {
705void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
706 GrConfigConversionEffect::PMConversion pmToUPM;
707 GrConfigConversionEffect::PMConversion upmToPM;
708 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
709 *pmToUPMValue = pmToUPM;
710 *upmToPMValue = upmToPM;
711}
712}
713
joshualittb0a8a372014-09-23 09:50:21 -0700714const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture,
715 bool swapRAndB,
716 const SkMatrix& matrix) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000717 if (!fDidTestPMConversions) {
718 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
bsalomon@google.comd0f3f682012-08-28 13:08:14 +0000719 fDidTestPMConversions = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000720 }
721 GrConfigConversionEffect::PMConversion pmToUPM =
722 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
723 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000724 return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000725 } else {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000726 return NULL;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000727 }
728}
729
joshualittb0a8a372014-09-23 09:50:21 -0700730const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture,
731 bool swapRAndB,
732 const SkMatrix& matrix) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000733 if (!fDidTestPMConversions) {
734 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
bsalomon@google.comd0f3f682012-08-28 13:08:14 +0000735 fDidTestPMConversions = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000736 }
737 GrConfigConversionEffect::PMConversion upmToPM =
738 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
739 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000740 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000741 } else {
bsalomon@google.comadc65362013-01-28 14:26:09 +0000742 return NULL;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000743 }
744}
745
bsalomon37f9a262015-02-02 13:00:10 -0800746//////////////////////////////////////////////////////////////////////////////
747
748void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
749 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800750 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800751 }
752 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800753 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800754 }
755}
756
757void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800758 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800759}
760
bsalomon37f9a262015-02-02 13:00:10 -0800761//////////////////////////////////////////////////////////////////////////////
762
egdanielbbcb38d2014-06-19 10:19:29 -0700763void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
764 fGpu->addGpuTraceMarker(marker);
egdanielbbcb38d2014-06-19 10:19:29 -0700765}
766
767void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
768 fGpu->removeGpuTraceMarker(marker);
egdanielbbcb38d2014-06-19 10:19:29 -0700769}
joshualitte5902662015-05-11 08:18:35 -0700770