blob: e5bbb8fd918fcf0f4c3da9b0fba595979fb8273b [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
joshualitt7c3a2f82015-03-31 13:32:05 -070011#include "GrBatchFontCache.h"
bsalomon75398562015-08-17 12:55:38 -070012#include "GrBatchFlushState.h"
joshualitte5902662015-05-11 08:18:35 -070013#include "GrBatchTest.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070014#include "GrCaps.h"
bsalomon682c2692015-05-22 14:01:46 -070015#include "GrContextOptions.h"
joshualitt5478d422014-11-14 16:00:38 -080016#include "GrDefaultGeoProcFactory.h"
robertphillips77a2e522015-10-17 07:43:27 -070017#include "GrDrawingManager.h"
robertphillipsea461502015-05-26 11:38:03 -070018#include "GrDrawContext.h"
bsalomon512be532015-09-10 10:42:55 -070019#include "GrDrawTarget.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"
commit-bot@chromium.orgdcb8ef92014-03-27 11:26:10 +000023#include "GrIndexBuffer.h"
robertphillips@google.come930a072014-04-03 00:34:27 +000024#include "GrLayerCache.h"
commit-bot@chromium.org81312832013-03-22 18:34:09 +000025#include "GrOvalRenderer.h"
bsalomon@google.com27847de2011-02-22 20:59:41 +000026#include "GrPathRenderer.h"
tomhudson@google.comd22b6e42011-06-24 15:53:40 +000027#include "GrPathUtils.h"
bsalomon6bc1b5f2015-02-23 09:06:38 -080028#include "GrRenderTargetPriv.h"
bsalomon0ea80f42015-02-11 10:49:59 -080029#include "GrResourceCache.h"
bsalomond309e7a2015-04-30 14:18:54 -070030#include "GrResourceProvider.h"
robertphillips@google.com72176b22012-05-23 13:19:12 +000031#include "GrSoftwarePathRenderer.h"
robertphillips2d70dcb2015-10-06 07:38:23 -070032#include "GrStencilAndCoverTextContext.h"
egdanield58a0ba2014-06-11 10:30:05 -070033#include "GrStrokeInfo.h"
bsalomonafbf2d62014-09-30 12:18:44 -070034#include "GrSurfacePriv.h"
joshualittb7133be2015-04-08 09:08:31 -070035#include "GrTextBlobCache.h"
bsalomonafbf2d62014-09-30 12:18:44 -070036#include "GrTexturePriv.h"
commit-bot@chromium.org2a05de02014-03-25 15:17:32 +000037#include "GrTracing.h"
bsalomoncb8979d2015-05-05 09:51:38 -070038#include "GrVertices.h"
egdanield58a0ba2014-06-11 10:30:05 -070039#include "SkDashPathPriv.h"
bsalomon81beccc2014-10-13 12:32:55 -070040#include "SkConfig8888.h"
bsalomonf276ac52015-10-09 13:36:42 -070041#include "SkGrPriv.h"
commit-bot@chromium.org47841822014-03-27 14:19:17 +000042#include "SkRRect.h"
sugoi@google.com5f74cf82012-12-17 21:16:45 +000043#include "SkStrokeRec.h"
robertphillipsfcf78292015-06-19 11:49:52 -070044#include "SkSurfacePriv.h"
commit-bot@chromium.orgdcb8ef92014-03-27 11:26:10 +000045#include "SkTLazy.h"
commit-bot@chromium.org47841822014-03-27 14:19:17 +000046#include "SkTLS.h"
commit-bot@chromium.org933e65d2014-03-20 20:00:24 +000047#include "SkTraceEvent.h"
bsalomon@google.com27847de2011-02-22 20:59:41 +000048
robertphillips2d70dcb2015-10-06 07:38:23 -070049
joshualitt74417822015-08-07 11:42:16 -070050#include "batches/GrBatch.h"
51
joshualitt5478d422014-11-14 16:00:38 -080052#include "effects/GrConfigConversionEffect.h"
53#include "effects/GrDashingEffect.h"
54#include "effects/GrSingleTextureEffect.h"
55
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000056#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
robertphillips77a2e522015-10-17 07:43:27 -070057#define RETURN_IF_ABANDONED if (fDrawingManager->abandoned()) { return; }
58#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->abandoned()) { return false; }
59#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->abandoned()) { return nullptr; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000060
bsalomonf21dab92014-11-13 13:33:28 -080061
robertphillipsea461502015-05-26 11:38:03 -070062////////////////////////////////////////////////////////////////////////////////
63
robertphillips77a2e522015-10-17 07:43:27 -070064void GrDrawingManager::cleanup() {
robertphillipsa106c622015-10-16 09:07:06 -070065 for (int i = 0; i < fDrawTargets.count(); ++i) {
66 fDrawTargets[i]->unref();
67 }
68
69 fDrawTargets.reset();
70
robertphillips2d70dcb2015-10-06 07:38:23 -070071 delete fNVPRTextContext;
72 fNVPRTextContext = nullptr;
robertphillipsa106c622015-10-16 09:07:06 -070073
robertphillips2334fb62015-06-17 05:43:33 -070074 for (int i = 0; i < kNumPixelGeometries; ++i) {
robertphillips2d70dcb2015-10-06 07:38:23 -070075 delete fTextContexts[i][0];
76 fTextContexts[i][0] = nullptr;
77 delete fTextContexts[i][1];
78 fTextContexts[i][1] = nullptr;
robertphillips2334fb62015-06-17 05:43:33 -070079 }
robertphillipsea461502015-05-26 11:38:03 -070080}
81
robertphillips77a2e522015-10-17 07:43:27 -070082GrDrawingManager::~GrDrawingManager() {
robertphillips2334fb62015-06-17 05:43:33 -070083 this->cleanup();
robertphillipsea461502015-05-26 11:38:03 -070084}
85
robertphillips77a2e522015-10-17 07:43:27 -070086void GrDrawingManager::abandon() {
robertphillipsa106c622015-10-16 09:07:06 -070087 fAbandoned = true;
robertphillips2d70dcb2015-10-06 07:38:23 -070088 this->cleanup();
robertphillipsea461502015-05-26 11:38:03 -070089}
90
robertphillips77a2e522015-10-17 07:43:27 -070091void GrDrawingManager::reset() {
robertphillipsa106c622015-10-16 09:07:06 -070092 for (int i = 0; i < fDrawTargets.count(); ++i) {
93 fDrawTargets[i]->reset();
robertphillipsea461502015-05-26 11:38:03 -070094 }
95}
96
robertphillips77a2e522015-10-17 07:43:27 -070097void GrDrawingManager::flush() {
robertphillipsa106c622015-10-16 09:07:06 -070098 for (int i = 0; i < fDrawTargets.count(); ++i) {
99 fDrawTargets[i]->flush();
robertphillipsea461502015-05-26 11:38:03 -0700100 }
101}
102
robertphillips77a2e522015-10-17 07:43:27 -0700103GrTextContext* GrDrawingManager::textContext(const SkSurfaceProps& props,
104 GrRenderTarget* rt) {
robertphillips2d70dcb2015-10-06 07:38:23 -0700105 if (this->abandoned()) {
106 return nullptr;
107 }
108
109 SkASSERT(props.pixelGeometry() < kNumPixelGeometries);
110 bool useDIF = props.isUseDeviceIndependentFonts();
111
112 if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
113 rt->isStencilBufferMultisampled()) {
114 GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt);
115 if (sb) {
116 if (!fNVPRTextContext) {
117 fNVPRTextContext = GrStencilAndCoverTextContext::Create(fContext, props);
118 }
119
120 return fNVPRTextContext;
121 }
122 }
123
124 if (!fTextContexts[props.pixelGeometry()][useDIF]) {
125 fTextContexts[props.pixelGeometry()][useDIF] = GrAtlasTextContext::Create(fContext, props);
126 }
127
128 return fTextContexts[props.pixelGeometry()][useDIF];
129}
130
robertphillips77a2e522015-10-17 07:43:27 -0700131GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
robertphillipsa106c622015-10-16 09:07:06 -0700132 SkASSERT(fContext);
133
134 // When MDB is disabled we always just return the single drawTarget
135#ifndef ENABLE_MDB
136 if (fDrawTargets.count()) {
137 SkASSERT(fDrawTargets.count() == 1);
robertphillips77a2e522015-10-17 07:43:27 -0700138 // DrawingManager gets the creation ref - this ref is for the caller
robertphillipsa106c622015-10-16 09:07:06 -0700139 return SkRef(fDrawTargets[0]);
140 }
141#endif
142
143 GrDrawTarget* dt = new GrDrawTarget(fContext->getGpu(), fContext->resourceProvider());
144
145 *fDrawTargets.append() = dt;
146
robertphillips77a2e522015-10-17 07:43:27 -0700147 // DrawingManager gets the creation ref - this ref is for the caller
robertphillipsa106c622015-10-16 09:07:06 -0700148 return SkRef(dt);
149}
150
robertphillips77a2e522015-10-17 07:43:27 -0700151GrDrawContext* GrDrawingManager::drawContext(GrRenderTarget* rt,
152 const SkSurfaceProps* surfaceProps) {
robertphillipsea461502015-05-26 11:38:03 -0700153 if (this->abandoned()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700154 return nullptr;
robertphillipsea461502015-05-26 11:38:03 -0700155 }
robertphillips2334fb62015-06-17 05:43:33 -0700156
robertphillips77a2e522015-10-17 07:43:27 -0700157 return new GrDrawContext(this, rt, surfaceProps);
robertphillipsea461502015-05-26 11:38:03 -0700158}
159
160////////////////////////////////////////////////////////////////////////////////
161
bsalomonf21dab92014-11-13 13:33:28 -0800162
bsalomon682c2692015-05-22 14:01:46 -0700163GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
164 GrContextOptions defaultOptions;
165 return Create(backend, backendContext, defaultOptions);
166}
bsalomonf28cff72015-05-22 12:25:41 -0700167
bsalomon682c2692015-05-22 14:01:46 -0700168GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
169 const GrContextOptions& options) {
halcanary385fe4d2015-08-26 13:07:48 -0700170 GrContext* context = new GrContext;
bsalomon682c2692015-05-22 14:01:46 -0700171
172 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000173 return context;
174 } else {
175 context->unref();
halcanary96fcdcc2015-08-27 07:41:13 -0700176 return nullptr;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000177 }
bsalomon@google.com27847de2011-02-22 20:59:41 +0000178}
179
joshualitt0acd0d32015-05-07 08:23:19 -0700180static int32_t gNextID = 1;
181static int32_t next_id() {
182 int32_t id;
183 do {
184 id = sk_atomic_inc(&gNextID);
185 } while (id == SK_InvalidGenID);
186 return id;
187}
188
bsalomon682c2692015-05-22 14:01:46 -0700189GrContext::GrContext() : fUniqueID(next_id()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700190 fGpu = nullptr;
191 fCaps = nullptr;
192 fResourceCache = nullptr;
193 fResourceProvider = nullptr;
194 fPathRendererChain = nullptr;
195 fSoftwarePathRenderer = nullptr;
196 fBatchFontCache = nullptr;
bsalomonf21dab92014-11-13 13:33:28 -0800197 fFlushToReduceCacheSize = false;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000198}
199
bsalomon682c2692015-05-22 14:01:46 -0700200bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
201 const GrContextOptions& options) {
robertphillipsea461502015-05-26 11:38:03 -0700202 SkASSERT(!fGpu);
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000203
bsalomon682c2692015-05-22 14:01:46 -0700204 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -0700205 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000206 return false;
207 }
bsalomon33435572014-11-05 14:47:41 -0800208 this->initCommon();
209 return true;
210}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000211
bsalomon33435572014-11-05 14:47:41 -0800212void GrContext::initCommon() {
bsalomon76228632015-05-29 08:02:10 -0700213 fCaps = SkRef(fGpu->caps());
halcanary385fe4d2015-08-26 13:07:48 -0700214 fResourceCache = new GrResourceCache(fCaps);
bsalomon0ea80f42015-02-11 10:49:59 -0800215 fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
halcanary385fe4d2015-08-26 13:07:48 -0700216 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +0000217
halcanary385fe4d2015-08-26 13:07:48 -0700218 fLayerCache.reset(new GrLayerCache(this));
robertphillips@google.come930a072014-04-03 00:34:27 +0000219
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000220 fDidTestPMConversions = false;
221
robertphillips77a2e522015-10-17 07:43:27 -0700222 fDrawingManager.reset(new GrDrawingManager(this));
joshualitt7c3a2f82015-03-31 13:32:05 -0700223
224 // GrBatchFontCache will eventually replace GrFontCache
halcanary385fe4d2015-08-26 13:07:48 -0700225 fBatchFontCache = new GrBatchFontCache(this);
joshualittb7133be2015-04-08 09:08:31 -0700226
halcanary385fe4d2015-08-26 13:07:48 -0700227 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000228}
229
bsalomon@google.com27847de2011-02-22 20:59:41 +0000230GrContext::~GrContext() {
robertphillipsea461502015-05-26 11:38:03 -0700231 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700232 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000233 return;
234 }
235
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000236 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000237
robertphillips77a2e522015-10-17 07:43:27 -0700238 fDrawingManager->cleanup();
robertphillips2334fb62015-06-17 05:43:33 -0700239
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000240 for (int i = 0; i < fCleanUpData.count(); ++i) {
241 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
242 }
243
halcanary385fe4d2015-08-26 13:07:48 -0700244 delete fResourceProvider;
245 delete fResourceCache;
246 delete fBatchFontCache;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000247
bsalomon@google.com205d4602011-04-25 12:43:45 +0000248 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700249 fCaps->unref();
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000250 SkSafeUnref(fPathRendererChain);
251 SkSafeUnref(fSoftwarePathRenderer);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000252}
253
bsalomon2354f842014-07-28 13:48:36 -0700254void GrContext::abandonContext() {
bsalomond309e7a2015-04-30 14:18:54 -0700255 fResourceProvider->abandon();
bsalomon@google.com205d4602011-04-25 12:43:45 +0000256 // abandon first to so destructors
257 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800258 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700259
robertphillipse3371302014-09-17 06:01:06 -0700260 fGpu->contextAbandoned();
bsalomon@google.com205d4602011-04-25 12:43:45 +0000261
bsalomon@google.com30085192011-08-19 15:42:31 +0000262 // a path renderer may be holding onto resources that
263 // are now unusable
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000264 SkSafeSetNull(fPathRendererChain);
265 SkSafeSetNull(fSoftwarePathRenderer);
bsalomon@google.com30085192011-08-19 15:42:31 +0000266
robertphillips77a2e522015-10-17 07:43:27 -0700267 fDrawingManager->abandon();
bsalomon@google.com205d4602011-04-25 12:43:45 +0000268
joshualitt7c3a2f82015-03-31 13:32:05 -0700269 fBatchFontCache->freeAll();
robertphillips@google.come930a072014-04-03 00:34:27 +0000270 fLayerCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700271 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000272}
273
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000274void GrContext::resetContext(uint32_t state) {
275 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000276}
277
278void GrContext::freeGpuResources() {
279 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000280
joshualitt7c3a2f82015-03-31 13:32:05 -0700281 fBatchFontCache->freeAll();
robertphillips@google.come930a072014-04-03 00:34:27 +0000282 fLayerCache->freeAll();
bsalomon@google.com30085192011-08-19 15:42:31 +0000283 // a path renderer may be holding onto resources
commit-bot@chromium.orga4de8c22013-09-09 13:38:37 +0000284 SkSafeSetNull(fPathRendererChain);
285 SkSafeSetNull(fSoftwarePathRenderer);
bsalomon3033b9f2015-04-13 11:09:56 -0700286
287 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000288}
289
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000290void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
bsalomon71cb0c22014-11-14 12:10:14 -0800291 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800292 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800293 }
294 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800295 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800296 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000297}
298
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000299////////////////////////////////////////////////////////////////////////////////
300
bsalomon71cb0c22014-11-14 12:10:14 -0800301void GrContext::OverBudgetCB(void* data) {
bsalomon66a450f2014-11-13 13:19:10 -0800302 SkASSERT(data);
bsalomonf21dab92014-11-13 13:33:28 -0800303
bsalomon66a450f2014-11-13 13:19:10 -0800304 GrContext* context = reinterpret_cast<GrContext*>(data);
bsalomonf21dab92014-11-13 13:33:28 -0800305
joshualittb542bae2015-07-28 09:58:39 -0700306 // Flush the GrBufferedDrawTarget to possibly free up some textures
bsalomonf21dab92014-11-13 13:33:28 -0800307 context->fFlushToReduceCacheSize = true;
commit-bot@chromium.orgcae27fe2013-07-10 10:14:35 +0000308}
309
joshualitt0db6dfa2015-04-10 07:01:30 -0700310void GrContext::TextBlobCacheOverBudgetCB(void* data) {
311 SkASSERT(data);
312
313 // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
314 // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush. The solution is to move
315 // drawText calls to below the GrContext level, but this is not trivial because they call
316 // drawPath on SkGpuDevice
317 GrContext* context = reinterpret_cast<GrContext*>(data);
318 context->flush();
319}
320
bsalomon@google.com27847de2011-02-22 20:59:41 +0000321////////////////////////////////////////////////////////////////////////////////
322
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000323void GrContext::flush(int flagsBitfield) {
robertphillipsea461502015-05-26 11:38:03 -0700324 RETURN_IF_ABANDONED
robertphillips@google.come7db8d62013-07-04 11:48:52 +0000325
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000326 if (kDiscard_FlushBit & flagsBitfield) {
robertphillips77a2e522015-10-17 07:43:27 -0700327 fDrawingManager->reset();
bsalomon@google.coma7f84e12011-03-10 14:13:19 +0000328 } else {
robertphillips77a2e522015-10-17 07:43:27 -0700329 fDrawingManager->flush();
junov@google.com53a55842011-06-08 22:55:10 +0000330 }
bsalomon3f324322015-04-08 11:01:54 -0700331 fResourceCache->notifyFlushOccurred();
bsalomonf21dab92014-11-13 13:33:28 -0800332 fFlushToReduceCacheSize = false;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000333}
334
bsalomon81beccc2014-10-13 12:32:55 -0700335bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
336 const void* inPixels, size_t outRowBytes, void* outPixels) {
337 SkSrcPixelInfo srcPI;
halcanary96fcdcc2015-08-27 07:41:13 -0700338 if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, nullptr)) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000339 return false;
340 }
bsalomon81beccc2014-10-13 12:32:55 -0700341 srcPI.fAlphaType = kUnpremul_SkAlphaType;
342 srcPI.fPixels = inPixels;
343 srcPI.fRowBytes = inRowBytes;
344
345 SkDstPixelInfo dstPI;
346 dstPI.fColorType = srcPI.fColorType;
347 dstPI.fAlphaType = kPremul_SkAlphaType;
348 dstPI.fPixels = outPixels;
349 dstPI.fRowBytes = outRowBytes;
350
351 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000352}
353
bsalomon81beccc2014-10-13 12:32:55 -0700354bool GrContext::writeSurfacePixels(GrSurface* surface,
355 int left, int top, int width, int height,
356 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
357 uint32_t pixelOpsFlags) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800358 RETURN_FALSE_IF_ABANDONED
bsalomon6c6f6582015-09-10 08:12:46 -0700359 ASSERT_OWNED_RESOURCE(surface);
360 SkASSERT(surface);
361
362 this->testPMConversionsIfNecessary(pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700363
bsalomone8d21e82015-07-16 08:23:13 -0700364 // 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 -0700365 // necessary and because GrGpu::getWritePixelsInfo requires it.
bsalomone8d21e82015-07-16 08:23:13 -0700366 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
367 GrBytesPerPixel(srcConfig), &left, &top, &width,
368 &height, &buffer, &rowBytes)) {
369 return false;
370 }
371
bsalomonf0674512015-07-28 13:26:15 -0700372 bool applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700373 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
374 if (!GrPixelConfigIs8888(srcConfig)) {
375 return false;
376 }
bsalomonf0674512015-07-28 13:26:15 -0700377 applyPremulToSrc = true;
378 }
bsalomon636e8022015-07-29 06:08:46 -0700379
380 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
381 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
382 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
383 if (applyPremulToSrc && !this->didFailPMUPMConversionTest()) {
384 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
385 }
386
bsalomonf0674512015-07-28 13:26:15 -0700387 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
388 if (!fGpu->getWritePixelsInfo(surface, width, height, rowBytes, srcConfig, &drawPreference,
389 &tempDrawInfo)) {
390 return false;
391 }
392
393 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
394 this->flush();
395 }
396
397 SkAutoTUnref<GrTexture> tempTexture;
398 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomoneae62002015-07-31 13:59:30 -0700399 tempTexture.reset(
400 this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
bsalomonf0674512015-07-28 13:26:15 -0700401 if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
402 return false;
403 }
404 }
405
406 // temp buffer for doing sw premul conversion, if needed.
benjaminwagner7d974f52015-10-19 13:55:55 -0700407#if defined(GOOGLE3)
408 // Stack frame size is limited in GOOGLE3.
409 SkAutoSTMalloc<48 * 48, uint32_t> tmpPixels(0);
410#else
bsalomonf0674512015-07-28 13:26:15 -0700411 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
benjaminwagner7d974f52015-10-19 13:55:55 -0700412#endif
bsalomonf0674512015-07-28 13:26:15 -0700413 if (tempTexture) {
414 SkAutoTUnref<const GrFragmentProcessor> fp;
415 SkMatrix textureMatrix;
416 textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
417 GrPaint paint;
418 if (applyPremulToSrc) {
bsalomon4a339522015-10-06 08:40:50 -0700419 fp.reset(this->createUPMToPMEffect(tempTexture, tempDrawInfo.fSwapRAndB,
420 textureMatrix));
bsalomonf0674512015-07-28 13:26:15 -0700421 // If premultiplying was the only reason for the draw, fall back to a straight write.
422 if (!fp) {
423 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
halcanary96fcdcc2015-08-27 07:41:13 -0700424 tempTexture.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700425 }
426 } else {
427 applyPremulToSrc = false;
428 }
429 }
430 if (tempTexture) {
431 if (!fp) {
bsalomon4a339522015-10-06 08:40:50 -0700432 fp.reset(GrConfigConversionEffect::Create(tempTexture, tempDrawInfo.fSwapRAndB,
bsalomonf0674512015-07-28 13:26:15 -0700433 GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
434 if (!fp) {
435 return false;
436 }
437 }
438 GrRenderTarget* renderTarget = surface->asRenderTarget();
439 SkASSERT(renderTarget);
440 if (tempTexture->surfacePriv().hasPendingIO()) {
441 this->flush();
442 }
443 if (applyPremulToSrc) {
444 size_t tmpRowBytes = 4 * width;
445 tmpPixels.reset(width * height);
446 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
447 tmpPixels.get())) {
448 return false;
449 }
450 rowBytes = tmpRowBytes;
451 buffer = tmpPixels.get();
452 applyPremulToSrc = false;
453 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700454 if (!fGpu->writePixels(tempTexture, 0, 0, width, height,
455 tempDrawInfo.fTempSurfaceDesc.fConfig, buffer,
456 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700457 return false;
458 }
459 SkMatrix matrix;
460 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
robertphillips2e1e51f2015-10-15 08:01:48 -0700461 SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(renderTarget));
bsalomonf0674512015-07-28 13:26:15 -0700462 if (!drawContext) {
463 return false;
464 }
bsalomonac856c92015-08-27 06:30:17 -0700465 paint.addColorFragmentProcessor(fp);
bsalomonf0674512015-07-28 13:26:15 -0700466 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
robertphillips2e1e51f2015-10-15 08:01:48 -0700467 drawContext->drawRect(GrClip::WideOpen(), paint, matrix, rect, nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700468
469 if (kFlushWrites_PixelOp & pixelOpsFlags) {
470 this->flushSurfaceWrites(surface);
471 }
472 }
473 }
474 if (!tempTexture) {
bsalomonf0674512015-07-28 13:26:15 -0700475 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700476 size_t tmpRowBytes = 4 * width;
477 tmpPixels.reset(width * height);
478 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
479 tmpPixels.get())) {
480 return false;
481 }
482 rowBytes = tmpRowBytes;
483 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700484 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700485 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700486 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700487 }
bsalomon81beccc2014-10-13 12:32:55 -0700488 return true;
489}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000490
bsalomone8d21e82015-07-16 08:23:13 -0700491bool GrContext::readSurfacePixels(GrSurface* src,
492 int left, int top, int width, int height,
493 GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
494 uint32_t flags) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800495 RETURN_FALSE_IF_ABANDONED
bsalomone8d21e82015-07-16 08:23:13 -0700496 ASSERT_OWNED_RESOURCE(src);
497 SkASSERT(src);
bsalomon32ab2602015-09-09 18:57:49 -0700498
bsalomon6c6f6582015-09-10 08:12:46 -0700499 this->testPMConversionsIfNecessary(flags);
500 SkAutoMutexAcquire ama(fReadPixelsMutex);
501
bsalomone8d21e82015-07-16 08:23:13 -0700502 // Adjust the params so that if we wind up using an intermediate surface we've already done
503 // all the trimming and the temporary can be the min size required.
504 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
505 GrBytesPerPixel(dstConfig), &left,
506 &top, &width, &height, &buffer, &rowBytes)) {
507 return false;
508 }
509
510 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000511 this->flush();
512 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000513
bsalomone8d21e82015-07-16 08:23:13 -0700514 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
bsalomon@google.com9c680582013-02-06 18:17:50 +0000515 if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
bsalomon39826022015-07-23 08:07:21 -0700516 // The unpremul flag is only allowed for 8888 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000517 return false;
518 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000519
bsalomon636e8022015-07-29 06:08:46 -0700520 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
521 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
522 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
523 if (unpremul && !this->didFailPMUPMConversionTest()) {
524 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
525 }
526
bsalomon39826022015-07-23 08:07:21 -0700527 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
528 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference,
529 &tempDrawInfo)) {
530 return false;
531 }
bsalomon191bcc02014-11-14 11:31:13 -0800532
bsalomon6cb3cbe2015-07-30 07:34:27 -0700533 SkAutoTUnref<GrSurface> surfaceToRead(SkRef(src));
bsalomon39826022015-07-23 08:07:21 -0700534 bool didTempDraw = false;
535 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomon39826022015-07-23 08:07:21 -0700536 if (tempDrawInfo.fUseExactScratch) {
537 // We only respect this when the entire src is being read. Otherwise we can trigger too
538 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700539 if (width != src->width() || height != src->height()) {
540 tempDrawInfo.fUseExactScratch = false;
bsalomon39826022015-07-23 08:07:21 -0700541 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000542 }
bsalomon39826022015-07-23 08:07:21 -0700543 SkAutoTUnref<GrTexture> temp;
bsalomoneae62002015-07-31 13:59:30 -0700544 if (tempDrawInfo.fUseExactScratch) {
545 temp.reset(this->textureProvider()->createTexture(tempDrawInfo.fTempSurfaceDesc, true));
546 } else {
547 temp.reset(this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
548 }
bsalomon39826022015-07-23 08:07:21 -0700549 if (temp) {
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000550 SkMatrix textureMatrix;
bsalomon39826022015-07-23 08:07:21 -0700551 textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000552 textureMatrix.postIDiv(src->width(), src->height());
joshualitt5f10b5c2015-07-09 10:24:35 -0700553 GrPaint paint;
joshualittb0a8a372014-09-23 09:50:21 -0700554 SkAutoTUnref<const GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000555 if (unpremul) {
bsalomon4a339522015-10-06 08:40:50 -0700556 fp.reset(this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwapRAndB,
bsalomon39826022015-07-23 08:07:21 -0700557 textureMatrix));
joshualittb0a8a372014-09-23 09:50:21 -0700558 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000559 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon39826022015-07-23 08:07:21 -0700560 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
561 // We only wanted to do the draw in order to perform the unpremul so don't
562 // bother.
halcanary96fcdcc2015-08-27 07:41:13 -0700563 temp.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000564 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000565 }
bsalomon39826022015-07-23 08:07:21 -0700566 if (!fp && temp) {
bsalomon4a339522015-10-06 08:40:50 -0700567 fp.reset(GrConfigConversionEffect::Create(src->asTexture(), tempDrawInfo.fSwapRAndB,
bsalomon39826022015-07-23 08:07:21 -0700568 GrConfigConversionEffect::kNone_PMConversion, textureMatrix));
569 }
570 if (fp) {
bsalomonac856c92015-08-27 06:30:17 -0700571 paint.addColorFragmentProcessor(fp);
bsalomon39826022015-07-23 08:07:21 -0700572 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
robertphillips2e1e51f2015-10-15 08:01:48 -0700573 SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(temp->asRenderTarget()));
574 drawContext->drawRect(GrClip::WideOpen(), paint, SkMatrix::I(), rect, nullptr);
bsalomon6cb3cbe2015-07-30 07:34:27 -0700575 surfaceToRead.reset(SkRef(temp.get()));
bsalomon39826022015-07-23 08:07:21 -0700576 left = 0;
577 top = 0;
578 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000579 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000580 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000581 }
joshualitt5c55fef2014-10-31 14:04:35 -0700582
bsalomon39826022015-07-23 08:07:21 -0700583 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000584 return false;
585 }
bsalomon39826022015-07-23 08:07:21 -0700586 GrPixelConfig configToRead = dstConfig;
587 if (didTempDraw) {
bsalomon6cb3cbe2015-07-30 07:34:27 -0700588 this->flushSurfaceWrites(surfaceToRead);
bsalomon39826022015-07-23 08:07:21 -0700589 // We swapped R and B while doing the temp draw. Swap back on the read.
590 if (tempDrawInfo.fSwapRAndB) {
591 configToRead = GrPixelConfigSwapRAndB(dstConfig);
592 }
593 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700594 if (!fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead, buffer,
595 rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700596 return false;
597 }
598
599 // Perform umpremul conversion if we weren't able to perform it as a draw.
600 if (unpremul) {
reed@google.com7111d462014-03-25 16:20:24 +0000601 SkDstPixelInfo dstPI;
halcanary96fcdcc2015-08-27 07:41:13 -0700602 if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, nullptr)) {
reed@google.com7111d462014-03-25 16:20:24 +0000603 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000604 }
reed@google.com7111d462014-03-25 16:20:24 +0000605 dstPI.fAlphaType = kUnpremul_SkAlphaType;
606 dstPI.fPixels = buffer;
607 dstPI.fRowBytes = rowBytes;
608
609 SkSrcPixelInfo srcPI;
bsalomon39826022015-07-23 08:07:21 -0700610 srcPI.fColorType = dstPI.fColorType;
reed@google.com7111d462014-03-25 16:20:24 +0000611 srcPI.fAlphaType = kPremul_SkAlphaType;
612 srcPI.fPixels = buffer;
613 srcPI.fRowBytes = rowBytes;
614
615 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000616 }
617 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000618}
619
bsalomonc49e8682015-06-30 11:37:35 -0700620void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800621 RETURN_IF_ABANDONED
bsalomon87a94eb2014-11-03 14:28:32 -0800622 SkASSERT(surface);
623 ASSERT_OWNED_RESOURCE(surface);
624 if (surface->surfacePriv().hasPendingIO()) {
625 this->flush();
626 }
627 GrRenderTarget* rt = surface->asRenderTarget();
628 if (fGpu && rt) {
629 fGpu->resolveRenderTarget(rt);
bsalomon41ebbdd2014-08-04 08:31:39 -0700630 }
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000631}
632
bsalomonf80bfed2014-10-07 05:56:02 -0700633void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
634 const SkIPoint& dstPoint, uint32_t pixelOpsFlags) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800635 RETURN_IF_ABANDONED
robertphillipsea461502015-05-26 11:38:03 -0700636 if (!src || !dst) {
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000637 return;
638 }
bsalomone3d4bf22014-09-23 09:15:03 -0700639 ASSERT_OWNED_RESOURCE(src);
junov2bb52102014-09-29 10:18:59 -0700640 ASSERT_OWNED_RESOURCE(dst);
Brian Salomon34a98952014-09-24 11:41:24 -0400641
bsalomonf80bfed2014-10-07 05:56:02 -0700642 // Since we're going to the draw target and not GPU, no need to check kNoFlush
643 // here.
robertphillipsea461502015-05-26 11:38:03 -0700644 if (!dst->asRenderTarget()) {
junov96c118e2014-09-26 13:09:47 -0700645 return;
646 }
robertphillipsea461502015-05-26 11:38:03 -0700647
robertphillips2e1e51f2015-10-15 08:01:48 -0700648 SkAutoTUnref<GrDrawContext> drawContext(this->drawContext(dst->asRenderTarget()));
robertphillipsea461502015-05-26 11:38:03 -0700649 if (!drawContext) {
650 return;
651 }
652
robertphillips2e1e51f2015-10-15 08:01:48 -0700653 drawContext->copySurface(src, srcRect, dstPoint);
bsalomonf80bfed2014-10-07 05:56:02 -0700654
655 if (kFlushWrites_PixelOp & pixelOpsFlags) {
656 this->flush();
657 }
senorblanco@chromium.orgef843cd2011-12-02 19:11:17 +0000658}
659
bsalomonf80bfed2014-10-07 05:56:02 -0700660void GrContext::flushSurfaceWrites(GrSurface* surface) {
joshualitt5f5a8d72015-02-25 14:09:45 -0800661 RETURN_IF_ABANDONED
bsalomonf80bfed2014-10-07 05:56:02 -0700662 if (surface->surfacePriv().hasPendingWrite()) {
663 this->flush();
664 }
665}
666
robertphillips@google.com72176b22012-05-23 13:19:12 +0000667/*
668 * This method finds a path renderer that can draw the specified path on
669 * the provided target.
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000670 * Due to its expense, the software path renderer has split out so it can
robertphillips@google.com72176b22012-05-23 13:19:12 +0000671 * can be individually allowed/disallowed via the "allowSW" boolean.
672 */
joshualitt9853cce2014-11-17 14:22:48 -0800673GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
egdaniel8dd688b2015-01-22 10:16:09 -0800674 const GrPipelineBuilder* pipelineBuilder,
joshualitt8059eb92014-12-29 15:10:07 -0800675 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800676 const SkPath& path,
kkinnunen18996512015-04-26 23:18:49 -0700677 const GrStrokeInfo& stroke,
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000678 bool allowSW,
679 GrPathRendererChain::DrawType drawType,
680 GrPathRendererChain::StencilSupport* stencilSupport) {
681
robertphillipsea461502015-05-26 11:38:03 -0700682 if (!fPathRendererChain) {
halcanary385fe4d2015-08-26 13:07:48 -0700683 fPathRendererChain = new GrPathRendererChain(this);
bsalomon@google.com30085192011-08-19 15:42:31 +0000684 }
robertphillips@google.com72176b22012-05-23 13:19:12 +0000685
joshualitt9853cce2014-11-17 14:22:48 -0800686 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target,
egdaniel8dd688b2015-01-22 10:16:09 -0800687 pipelineBuilder,
joshualitt8059eb92014-12-29 15:10:07 -0800688 viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800689 path,
sugoi@google.com12b4e272012-12-06 20:13:11 +0000690 stroke,
bsalomon@google.com45a15f52012-12-10 19:10:17 +0000691 drawType,
692 stencilSupport);
robertphillips@google.com72176b22012-05-23 13:19:12 +0000693
robertphillipsea461502015-05-26 11:38:03 -0700694 if (!pr && allowSW) {
695 if (!fSoftwarePathRenderer) {
halcanary385fe4d2015-08-26 13:07:48 -0700696 fSoftwarePathRenderer = new GrSoftwarePathRenderer(this);
robertphillips@google.com72176b22012-05-23 13:19:12 +0000697 }
robertphillips@google.com72176b22012-05-23 13:19:12 +0000698 pr = fSoftwarePathRenderer;
699 }
700
701 return pr;
bsalomon@google.com30085192011-08-19 15:42:31 +0000702}
703
bsalomon@google.com27847de2011-02-22 20:59:41 +0000704////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000705int GrContext::getRecommendedSampleCount(GrPixelConfig config,
706 SkScalar dpi) const {
bsalomon76228632015-05-29 08:02:10 -0700707 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000708 return 0;
709 }
710 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700711 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000712 if (dpi >= 250.0f) {
713 chosenSampleCount = 4;
714 } else {
715 chosenSampleCount = 16;
716 }
717 }
718 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ?
719 chosenSampleCount : 0;
720}
721
robertphillips77a2e522015-10-17 07:43:27 -0700722
723GrDrawContext* GrContext::drawContext(GrRenderTarget* rt, const SkSurfaceProps* surfaceProps) {
724 return fDrawingManager->drawContext(rt, surfaceProps);
725}
726
727bool GrContext::abandoned() const {
728 return fDrawingManager->abandoned();
729}
730
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000731namespace {
732void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
733 GrConfigConversionEffect::PMConversion pmToUPM;
734 GrConfigConversionEffect::PMConversion upmToPM;
735 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
736 *pmToUPMValue = pmToUPM;
737 *upmToPMValue = upmToPM;
738}
739}
740
bsalomon6c6f6582015-09-10 08:12:46 -0700741void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
742 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) {
743 SkAutoMutexAcquire ama(fTestPMConversionsMutex);
744 if (!fDidTestPMConversions) {
745 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
746 fDidTestPMConversions = true;
747 }
748 }
749}
750
bsalomon4a339522015-10-06 08:40:50 -0700751const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture,
joshualittb0a8a372014-09-23 09:50:21 -0700752 bool swapRAndB,
bsalomon6c6f6582015-09-10 08:12:46 -0700753 const SkMatrix& matrix) const {
754 // We should have already called this->testPMConversionsIfNecessary().
755 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000756 GrConfigConversionEffect::PMConversion pmToUPM =
757 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
758 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
bsalomon4a339522015-10-06 08:40:50 -0700759 return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000760 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700761 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000762 }
763}
764
bsalomon4a339522015-10-06 08:40:50 -0700765const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture,
joshualittb0a8a372014-09-23 09:50:21 -0700766 bool swapRAndB,
bsalomon6c6f6582015-09-10 08:12:46 -0700767 const SkMatrix& matrix) const {
768 // We should have already called this->testPMConversionsIfNecessary().
769 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000770 GrConfigConversionEffect::PMConversion upmToPM =
771 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
772 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
bsalomon4a339522015-10-06 08:40:50 -0700773 return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000774 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700775 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000776 }
777}
778
bsalomon636e8022015-07-29 06:08:46 -0700779bool GrContext::didFailPMUPMConversionTest() const {
bsalomon6c6f6582015-09-10 08:12:46 -0700780 // We should have already called this->testPMConversionsIfNecessary().
781 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700782 // The PM<->UPM tests fail or succeed together so we only need to check one.
bsalomon6c6f6582015-09-10 08:12:46 -0700783 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion;
bsalomon636e8022015-07-29 06:08:46 -0700784}
785
bsalomon37f9a262015-02-02 13:00:10 -0800786//////////////////////////////////////////////////////////////////////////////
787
788void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
789 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800790 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800791 }
792 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800793 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800794 }
795}
796
797void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800798 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800799}
800
ericrk0a5fa482015-09-15 14:16:10 -0700801//////////////////////////////////////////////////////////////////////////////
802
803void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
804 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
805}