blob: ff5b0266e648267730f2c1f2f1508f725d84c58d [file] [log] [blame]
bsalomon@google.com27847de2011-02-22 20:59:41 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
bsalomon@google.com27847de2011-02-22 20:59:41 +00006 */
7
bsalomon@google.com1fadb202011-12-12 16:10:08 +00008#include "GrContext.h"
robertphillips4fd74ae2016-08-03 14:26:53 -07009#include "GrContextPriv.h"
bsalomon682c2692015-05-22 14:01:46 -070010#include "GrContextOptions.h"
robertphillips77a2e522015-10-17 07:43:27 -070011#include "GrDrawingManager.h"
Brian Osman11052242016-10-27 14:47:55 -040012#include "GrRenderTargetContext.h"
bsalomon0ea80f42015-02-11 10:49:59 -080013#include "GrResourceCache.h"
bsalomond309e7a2015-04-30 14:18:54 -070014#include "GrResourceProvider.h"
Robert Phillipsc7635fa2016-10-28 13:25:24 -040015#include "GrRenderTargetProxy.h"
robertphillips@google.com72176b22012-05-23 13:19:12 +000016#include "GrSoftwarePathRenderer.h"
Brian Osman45580d32016-11-23 09:37:01 -050017#include "GrSurfaceContext.h"
bsalomonafbf2d62014-09-30 12:18:44 -070018#include "GrSurfacePriv.h"
Brian Osman45580d32016-11-23 09:37:01 -050019#include "GrTextureContext.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070020
bsalomon81beccc2014-10-13 12:32:55 -070021#include "SkConfig8888.h"
bsalomonf276ac52015-10-09 13:36:42 -070022#include "SkGrPriv.h"
joshualitt74417822015-08-07 11:42:16 -070023
bsalomonb8fea972016-02-16 07:34:17 -080024#include "batches/GrCopySurfaceBatch.h"
joshualitt5478d422014-11-14 16:00:38 -080025#include "effects/GrConfigConversionEffect.h"
brianosman2d1ee792016-05-05 12:24:31 -070026#include "effects/GrGammaEffect.h"
joshualitte8042922015-12-11 06:11:21 -080027#include "text/GrTextBlobCache.h"
joshualitt5478d422014-11-14 16:00:38 -080028
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000029#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
joshualitt1de610a2016-01-06 08:26:09 -080030#define ASSERT_SINGLE_OWNER \
31 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);)
robertphillips4fd74ae2016-08-03 14:26:53 -070032#define ASSERT_SINGLE_OWNER_PRIV \
33 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070034#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
35#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
36#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000037
robertphillipsea461502015-05-26 11:38:03 -070038////////////////////////////////////////////////////////////////////////////////
39
bsalomon682c2692015-05-22 14:01:46 -070040GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
41 GrContextOptions defaultOptions;
42 return Create(backend, backendContext, defaultOptions);
43}
bsalomonf28cff72015-05-22 12:25:41 -070044
bsalomon682c2692015-05-22 14:01:46 -070045GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
46 const GrContextOptions& options) {
halcanary385fe4d2015-08-26 13:07:48 -070047 GrContext* context = new GrContext;
bsalomon682c2692015-05-22 14:01:46 -070048
49 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000050 return context;
51 } else {
52 context->unref();
halcanary96fcdcc2015-08-27 07:41:13 -070053 return nullptr;
bsalomon@google.com27847de2011-02-22 20:59:41 +000054 }
bsalomon@google.com27847de2011-02-22 20:59:41 +000055}
56
joshualitt0acd0d32015-05-07 08:23:19 -070057static int32_t gNextID = 1;
58static int32_t next_id() {
59 int32_t id;
60 do {
61 id = sk_atomic_inc(&gNextID);
62 } while (id == SK_InvalidGenID);
63 return id;
64}
65
bsalomon682c2692015-05-22 14:01:46 -070066GrContext::GrContext() : fUniqueID(next_id()) {
halcanary96fcdcc2015-08-27 07:41:13 -070067 fGpu = nullptr;
68 fCaps = nullptr;
69 fResourceCache = nullptr;
70 fResourceProvider = nullptr;
halcanary96fcdcc2015-08-27 07:41:13 -070071 fBatchFontCache = nullptr;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000072}
73
bsalomon682c2692015-05-22 14:01:46 -070074bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
75 const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080076 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -070077 SkASSERT(!fGpu);
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000078
bsalomon682c2692015-05-22 14:01:46 -070079 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -070080 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000081 return false;
82 }
bsalomon69cfe952015-11-30 13:27:47 -080083 this->initCommon(options);
bsalomon33435572014-11-05 14:47:41 -080084 return true;
85}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000086
bsalomon69cfe952015-11-30 13:27:47 -080087void GrContext::initCommon(const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080088 ASSERT_SINGLE_OWNER
89
bsalomon76228632015-05-29 08:02:10 -070090 fCaps = SkRef(fGpu->caps());
halcanary385fe4d2015-08-26 13:07:48 -070091 fResourceCache = new GrResourceCache(fCaps);
joshualitt6d0872d2016-01-11 08:27:48 -080092 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +000093
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000094 fDidTestPMConversions = false;
95
Robert Phillipsf2361d22016-10-25 14:20:06 -040096 GrRenderTargetOpList::Options rtOpListOptions;
97 rtOpListOptions.fClipBatchToBounds = options.fClipBatchToBounds;
Robert Phillipsf2361d22016-10-25 14:20:06 -040098 rtOpListOptions.fMaxBatchLookback = options.fMaxBatchLookback;
99 rtOpListOptions.fMaxBatchLookahead = options.fMaxBatchLookahead;
bsalomon6b2552f2016-09-15 13:50:26 -0700100 GrPathRendererChain::Options prcOptions;
101 prcOptions.fDisableDistanceFieldRenderer = options.fDisableDistanceFieldPaths;
bsalomon39ef7fb2016-09-21 11:16:05 -0700102 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching;
103 prcOptions.fDisableAllPathRenderers = options.fForceSWPathMasks;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400104 fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions,
105 options.fImmediateMode, &fSingleOwner));
joshualitt7c3a2f82015-03-31 13:32:05 -0700106
107 // GrBatchFontCache will eventually replace GrFontCache
halcanary385fe4d2015-08-26 13:07:48 -0700108 fBatchFontCache = new GrBatchFontCache(this);
joshualittb7133be2015-04-08 09:08:31 -0700109
halcanary385fe4d2015-08-26 13:07:48 -0700110 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000111}
112
bsalomon@google.com27847de2011-02-22 20:59:41 +0000113GrContext::~GrContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800114 ASSERT_SINGLE_OWNER
115
robertphillipsea461502015-05-26 11:38:03 -0700116 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700117 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000118 return;
119 }
120
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000121 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000122
robertphillips77a2e522015-10-17 07:43:27 -0700123 fDrawingManager->cleanup();
robertphillips2334fb62015-06-17 05:43:33 -0700124
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000125 for (int i = 0; i < fCleanUpData.count(); ++i) {
126 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
127 }
128
halcanary385fe4d2015-08-26 13:07:48 -0700129 delete fResourceProvider;
130 delete fResourceCache;
131 delete fBatchFontCache;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000132
bsalomon@google.com205d4602011-04-25 12:43:45 +0000133 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700134 fCaps->unref();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000135}
136
bungeman6bd52842016-10-27 09:30:08 -0700137sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
bsalomon41b952c2016-03-11 06:46:33 -0800138 if (!fThreadSafeProxy) {
bungeman6bd52842016-10-27 09:30:08 -0700139 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(sk_ref_sp(fCaps), this->uniqueID()));
bsalomon41b952c2016-03-11 06:46:33 -0800140 }
bungeman6bd52842016-10-27 09:30:08 -0700141 return fThreadSafeProxy;
bsalomon41b952c2016-03-11 06:46:33 -0800142}
143
bsalomon2354f842014-07-28 13:48:36 -0700144void GrContext::abandonContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800145 ASSERT_SINGLE_OWNER
146
bsalomond309e7a2015-04-30 14:18:54 -0700147 fResourceProvider->abandon();
robertphillips0dfa62c2015-11-16 06:23:31 -0800148
149 // Need to abandon the drawing manager first so all the render targets
150 // will be released/forgotten before they too are abandoned.
151 fDrawingManager->abandon();
152
bsalomon@google.com205d4602011-04-25 12:43:45 +0000153 // abandon first to so destructors
154 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800155 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700156
bsalomon6e2aad42016-04-01 11:54:31 -0700157 fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
158
159 fBatchFontCache->freeAll();
bsalomon6e2aad42016-04-01 11:54:31 -0700160 fTextBlobCache->freeAll();
161}
162
163void GrContext::releaseResourcesAndAbandonContext() {
164 ASSERT_SINGLE_OWNER
165
166 fResourceProvider->abandon();
167
168 // Need to abandon the drawing manager first so all the render targets
169 // will be released/forgotten before they too are abandoned.
170 fDrawingManager->abandon();
171
172 // Release all resources in the backend 3D API.
173 fResourceCache->releaseAll();
174
175 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000176
joshualitt7c3a2f82015-03-31 13:32:05 -0700177 fBatchFontCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700178 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000179}
180
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000181void GrContext::resetContext(uint32_t state) {
joshualitt1de610a2016-01-06 08:26:09 -0800182 ASSERT_SINGLE_OWNER
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000183 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000184}
185
186void GrContext::freeGpuResources() {
joshualitt1de610a2016-01-06 08:26:09 -0800187 ASSERT_SINGLE_OWNER
188
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000189 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000190
joshualitt7c3a2f82015-03-31 13:32:05 -0700191 fBatchFontCache->freeAll();
robertphillips68737822015-10-29 12:12:21 -0700192
193 fDrawingManager->freeGpuResources();
bsalomon3033b9f2015-04-13 11:09:56 -0700194
195 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000196}
197
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000198void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800199 ASSERT_SINGLE_OWNER
200
bsalomon71cb0c22014-11-14 12:10:14 -0800201 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800202 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800203 }
204 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800205 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800206 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000207}
208
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000209////////////////////////////////////////////////////////////////////////////////
210
joshualitt0db6dfa2015-04-10 07:01:30 -0700211void GrContext::TextBlobCacheOverBudgetCB(void* data) {
212 SkASSERT(data);
Brian Osman11052242016-10-27 14:47:55 -0400213 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
214 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls
215 // to below the GrContext level, but this is not trivial because they call drawPath on
216 // SkGpuDevice.
joshualitt0db6dfa2015-04-10 07:01:30 -0700217 GrContext* context = reinterpret_cast<GrContext*>(data);
218 context->flush();
219}
220
bsalomon@google.com27847de2011-02-22 20:59:41 +0000221////////////////////////////////////////////////////////////////////////////////
222
bsalomonb77a9072016-09-07 10:02:04 -0700223void GrContext::flush() {
joshualitt1de610a2016-01-06 08:26:09 -0800224 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700225 RETURN_IF_ABANDONED
bsalomonb77a9072016-09-07 10:02:04 -0700226 fDrawingManager->flush();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000227}
228
bsalomon81beccc2014-10-13 12:32:55 -0700229bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
230 const void* inPixels, size_t outRowBytes, void* outPixels) {
231 SkSrcPixelInfo srcPI;
brianosman396fcdb2016-07-22 06:26:11 -0700232 if (!GrPixelConfigToColorType(srcConfig, &srcPI.fColorType)) {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000233 return false;
234 }
bsalomon81beccc2014-10-13 12:32:55 -0700235 srcPI.fAlphaType = kUnpremul_SkAlphaType;
236 srcPI.fPixels = inPixels;
237 srcPI.fRowBytes = inRowBytes;
238
239 SkDstPixelInfo dstPI;
240 dstPI.fColorType = srcPI.fColorType;
241 dstPI.fAlphaType = kPremul_SkAlphaType;
242 dstPI.fPixels = outPixels;
243 dstPI.fRowBytes = outRowBytes;
244
245 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000246}
247
bsalomon81beccc2014-10-13 12:32:55 -0700248bool GrContext::writeSurfacePixels(GrSurface* surface,
249 int left, int top, int width, int height,
250 GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
251 uint32_t pixelOpsFlags) {
joshualitt1de610a2016-01-06 08:26:09 -0800252 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800253 RETURN_FALSE_IF_ABANDONED
bsalomon6c6f6582015-09-10 08:12:46 -0700254 ASSERT_OWNED_RESOURCE(surface);
255 SkASSERT(surface);
joshualittbc907352016-01-13 06:45:40 -0800256 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels");
bsalomon6c6f6582015-09-10 08:12:46 -0700257
258 this->testPMConversionsIfNecessary(pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700259
bsalomone8d21e82015-07-16 08:23:13 -0700260 // 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 -0700261 // necessary and because GrGpu::getWritePixelsInfo requires it.
bsalomone8d21e82015-07-16 08:23:13 -0700262 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
263 GrBytesPerPixel(srcConfig), &left, &top, &width,
264 &height, &buffer, &rowBytes)) {
265 return false;
266 }
267
bsalomonf0674512015-07-28 13:26:15 -0700268 bool applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700269 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500270 if (!GrPixelConfigIs8888Unorm(srcConfig)) {
bsalomon81beccc2014-10-13 12:32:55 -0700271 return false;
272 }
bsalomonf0674512015-07-28 13:26:15 -0700273 applyPremulToSrc = true;
274 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500275 // We don't allow conversion between integer configs and float/fixed configs.
276 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(srcConfig)) {
277 return false;
278 }
bsalomon636e8022015-07-29 06:08:46 -0700279
280 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
281 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
282 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
283 if (applyPremulToSrc && !this->didFailPMUPMConversionTest()) {
284 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
285 }
286
bsalomonf0674512015-07-28 13:26:15 -0700287 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
cblumeed828002016-02-16 13:00:01 -0800288 if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700289 &tempDrawInfo)) {
290 return false;
291 }
292
293 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
294 this->flush();
295 }
296
Hal Canary144caf52016-11-07 17:57:18 -0500297 sk_sp<GrTexture> tempTexture;
bsalomonf0674512015-07-28 13:26:15 -0700298 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomoneae62002015-07-31 13:59:30 -0700299 tempTexture.reset(
300 this->textureProvider()->createApproxTexture(tempDrawInfo.fTempSurfaceDesc));
bsalomonf0674512015-07-28 13:26:15 -0700301 if (!tempTexture && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
302 return false;
303 }
304 }
305
306 // temp buffer for doing sw premul conversion, if needed.
307 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
308 if (tempTexture) {
bungeman06ca8ec2016-06-09 08:01:03 -0700309 sk_sp<GrFragmentProcessor> fp;
bsalomonf0674512015-07-28 13:26:15 -0700310 SkMatrix textureMatrix;
311 textureMatrix.setIDiv(tempTexture->width(), tempTexture->height());
bsalomonf0674512015-07-28 13:26:15 -0700312 if (applyPremulToSrc) {
Hal Canary144caf52016-11-07 17:57:18 -0500313 fp = this->createUPMToPMEffect(tempTexture.get(), tempDrawInfo.fSwizzle, textureMatrix);
bsalomonf0674512015-07-28 13:26:15 -0700314 // If premultiplying was the only reason for the draw, fall back to a straight write.
315 if (!fp) {
316 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
halcanary96fcdcc2015-08-27 07:41:13 -0700317 tempTexture.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700318 }
319 } else {
320 applyPremulToSrc = false;
321 }
322 }
323 if (tempTexture) {
324 if (!fp) {
Hal Canary144caf52016-11-07 17:57:18 -0500325 fp = GrConfigConversionEffect::Make(tempTexture.get(), tempDrawInfo.fSwizzle,
bungeman06ca8ec2016-06-09 08:01:03 -0700326 GrConfigConversionEffect::kNone_PMConversion,
327 textureMatrix);
bsalomonf0674512015-07-28 13:26:15 -0700328 if (!fp) {
329 return false;
330 }
331 }
332 GrRenderTarget* renderTarget = surface->asRenderTarget();
333 SkASSERT(renderTarget);
334 if (tempTexture->surfacePriv().hasPendingIO()) {
335 this->flush();
336 }
337 if (applyPremulToSrc) {
338 size_t tmpRowBytes = 4 * width;
339 tmpPixels.reset(width * height);
340 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
341 tmpPixels.get())) {
342 return false;
343 }
344 rowBytes = tmpRowBytes;
345 buffer = tmpPixels.get();
346 applyPremulToSrc = false;
347 }
Hal Canary144caf52016-11-07 17:57:18 -0500348 if (!fGpu->writePixels(tempTexture.get(), 0, 0, width, height,
bsalomon6c9cd552016-01-22 07:17:34 -0800349 tempDrawInfo.fWriteConfig, buffer,
bsalomon6cb3cbe2015-07-30 07:34:27 -0700350 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700351 return false;
352 }
353 SkMatrix matrix;
354 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
brianosmandfe4f2e2016-07-21 13:28:36 -0700355 // TODO: Need to decide the semantics of this function for color spaces. Do we support
356 // conversion from a passed-in color space? For now, specifying nullptr means that this
357 // path will do no conversion, so it will match the behavior of the non-draw path.
Brian Osman11052242016-10-27 14:47:55 -0400358 sk_sp<GrRenderTargetContext> renderTargetContext(
359 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(renderTarget),
360 nullptr));
361 if (!renderTargetContext) {
bsalomonf0674512015-07-28 13:26:15 -0700362 return false;
363 }
egdanielc4b72722015-11-23 13:20:41 -0800364 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700365 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700366 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700367 paint.setAllowSRGBInputs(true);
bsalomonf0674512015-07-28 13:26:15 -0700368 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500369 renderTargetContext->drawRect(GrNoClip(), paint, GrAA::kNo, matrix, rect, nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700370
371 if (kFlushWrites_PixelOp & pixelOpsFlags) {
372 this->flushSurfaceWrites(surface);
373 }
374 }
375 }
376 if (!tempTexture) {
bsalomonf0674512015-07-28 13:26:15 -0700377 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700378 size_t tmpRowBytes = 4 * width;
379 tmpPixels.reset(width * height);
380 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
381 tmpPixels.get())) {
382 return false;
383 }
384 rowBytes = tmpRowBytes;
385 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700386 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700387 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700388 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700389 }
bsalomon81beccc2014-10-13 12:32:55 -0700390 return true;
391}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000392
bsalomone8d21e82015-07-16 08:23:13 -0700393bool GrContext::readSurfacePixels(GrSurface* src,
394 int left, int top, int width, int height,
395 GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
396 uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800397 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800398 RETURN_FALSE_IF_ABANDONED
bsalomone8d21e82015-07-16 08:23:13 -0700399 ASSERT_OWNED_RESOURCE(src);
400 SkASSERT(src);
joshualittbc907352016-01-13 06:45:40 -0800401 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700402
bsalomon6c6f6582015-09-10 08:12:46 -0700403 this->testPMConversionsIfNecessary(flags);
404 SkAutoMutexAcquire ama(fReadPixelsMutex);
405
bsalomone8d21e82015-07-16 08:23:13 -0700406 // Adjust the params so that if we wind up using an intermediate surface we've already done
407 // all the trimming and the temporary can be the min size required.
408 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
409 GrBytesPerPixel(dstConfig), &left,
410 &top, &width, &height, &buffer, &rowBytes)) {
411 return false;
412 }
413
414 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000415 this->flush();
416 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000417
bsalomone8d21e82015-07-16 08:23:13 -0700418 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500419 if (unpremul && !GrPixelConfigIs8888Unorm(dstConfig)) {
bsalomon39826022015-07-23 08:07:21 -0700420 // The unpremul flag is only allowed for 8888 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000421 return false;
422 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500423 // We don't allow conversion between integer configs and float/fixed configs.
424 if (GrPixelConfigIsSint(src->config()) != GrPixelConfigIsSint(dstConfig)) {
425 return false;
426 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000427
bsalomon636e8022015-07-29 06:08:46 -0700428 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
429 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
430 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
431 if (unpremul && !this->didFailPMUPMConversionTest()) {
432 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
433 }
434
bsalomon39826022015-07-23 08:07:21 -0700435 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
436 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference,
437 &tempDrawInfo)) {
438 return false;
439 }
bsalomon191bcc02014-11-14 11:31:13 -0800440
Hal Canary144caf52016-11-07 17:57:18 -0500441 sk_sp<GrSurface> surfaceToRead(SkRef(src));
bsalomon39826022015-07-23 08:07:21 -0700442 bool didTempDraw = false;
443 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomonb117ff12016-07-19 07:24:40 -0700444 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) {
bsalomon39826022015-07-23 08:07:21 -0700445 // We only respect this when the entire src is being read. Otherwise we can trigger too
446 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700447 if (width != src->width() || height != src->height()) {
bsalomonb117ff12016-07-19 07:24:40 -0700448 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox;
bsalomon39826022015-07-23 08:07:21 -0700449 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000450 }
brianosmandfe4f2e2016-07-21 13:28:36 -0700451 // TODO: Need to decide the semantics of this function for color spaces. Do we support
452 // conversion to a passed-in color space? For now, specifying nullptr means that this
453 // path will do no conversion, so it will match the behavior of the non-draw path.
Brian Osman693a5402016-10-27 15:13:22 -0400454 sk_sp<GrRenderTargetContext> tempRTC = this->makeRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400455 tempDrawInfo.fTempSurfaceFit,
bsalomonb117ff12016-07-19 07:24:40 -0700456 tempDrawInfo.fTempSurfaceDesc.fWidth,
457 tempDrawInfo.fTempSurfaceDesc.fHeight,
458 tempDrawInfo.fTempSurfaceDesc.fConfig,
brianosmandfe4f2e2016-07-21 13:28:36 -0700459 nullptr,
bsalomonb117ff12016-07-19 07:24:40 -0700460 tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
461 tempDrawInfo.fTempSurfaceDesc.fOrigin);
Brian Osman693a5402016-10-27 15:13:22 -0400462 if (tempRTC) {
bsalomon@google.comb9086a02012-11-01 18:02:54 +0000463 SkMatrix textureMatrix;
bsalomon39826022015-07-23 08:07:21 -0700464 textureMatrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000465 textureMatrix.postIDiv(src->width(), src->height());
bungeman06ca8ec2016-06-09 08:01:03 -0700466 sk_sp<GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000467 if (unpremul) {
bungeman06ca8ec2016-06-09 08:01:03 -0700468 fp = this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle,
469 textureMatrix);
joshualittb0a8a372014-09-23 09:50:21 -0700470 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000471 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon39826022015-07-23 08:07:21 -0700472 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
473 // We only wanted to do the draw in order to perform the unpremul so don't
474 // bother.
Brian Osman693a5402016-10-27 15:13:22 -0400475 tempRTC.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000476 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000477 }
Brian Osman693a5402016-10-27 15:13:22 -0400478 if (!fp && tempRTC) {
bungeman06ca8ec2016-06-09 08:01:03 -0700479 fp = GrConfigConversionEffect::Make(src->asTexture(), tempDrawInfo.fSwizzle,
480 GrConfigConversionEffect::kNone_PMConversion,
481 textureMatrix);
bsalomon39826022015-07-23 08:07:21 -0700482 }
483 if (fp) {
egdanielc4b72722015-11-23 13:20:41 -0800484 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700485 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700486 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700487 paint.setAllowSRGBInputs(true);
bsalomon39826022015-07-23 08:07:21 -0700488 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500489 tempRTC->drawRect(GrNoClip(), paint, GrAA::kNo, SkMatrix::I(), rect, nullptr);
Brian Osman693a5402016-10-27 15:13:22 -0400490 surfaceToRead.reset(tempRTC->asTexture().release());
bsalomon39826022015-07-23 08:07:21 -0700491 left = 0;
492 top = 0;
493 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000494 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000495 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000496 }
joshualitt5c55fef2014-10-31 14:04:35 -0700497
Robert Phillips833dcf42016-11-18 08:44:13 -0500498 if (!surfaceToRead) {
499 return false;
500 }
501
bsalomon39826022015-07-23 08:07:21 -0700502 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000503 return false;
504 }
bsalomon39826022015-07-23 08:07:21 -0700505 GrPixelConfig configToRead = dstConfig;
506 if (didTempDraw) {
Hal Canary144caf52016-11-07 17:57:18 -0500507 this->flushSurfaceWrites(surfaceToRead.get());
bsalomon6c9cd552016-01-22 07:17:34 -0800508 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700509 }
Hal Canary144caf52016-11-07 17:57:18 -0500510 if (!fGpu->readPixels(surfaceToRead.get(), left, top, width, height, configToRead, buffer,
511 rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700512 return false;
513 }
514
515 // Perform umpremul conversion if we weren't able to perform it as a draw.
516 if (unpremul) {
reed@google.com7111d462014-03-25 16:20:24 +0000517 SkDstPixelInfo dstPI;
brianosman396fcdb2016-07-22 06:26:11 -0700518 if (!GrPixelConfigToColorType(dstConfig, &dstPI.fColorType)) {
reed@google.com7111d462014-03-25 16:20:24 +0000519 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000520 }
reed@google.com7111d462014-03-25 16:20:24 +0000521 dstPI.fAlphaType = kUnpremul_SkAlphaType;
522 dstPI.fPixels = buffer;
523 dstPI.fRowBytes = rowBytes;
524
525 SkSrcPixelInfo srcPI;
bsalomon39826022015-07-23 08:07:21 -0700526 srcPI.fColorType = dstPI.fColorType;
reed@google.com7111d462014-03-25 16:20:24 +0000527 srcPI.fAlphaType = kPremul_SkAlphaType;
528 srcPI.fPixels = buffer;
529 srcPI.fRowBytes = rowBytes;
530
531 return srcPI.convertPixelsTo(&dstPI, width, height);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000532 }
533 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000534}
535
bsalomonc49e8682015-06-30 11:37:35 -0700536void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800537 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800538 RETURN_IF_ABANDONED
bsalomon87a94eb2014-11-03 14:28:32 -0800539 SkASSERT(surface);
540 ASSERT_OWNED_RESOURCE(surface);
bsalomon6a2b1942016-09-08 11:28:59 -0700541 fDrawingManager->prepareSurfaceForExternalIO(surface);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000542}
543
Robert Phillipsd316e772016-12-14 12:04:46 +0000544bool GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
545 const SkIPoint& dstPoint) {
546 ASSERT_SINGLE_OWNER
547 RETURN_FALSE_IF_ABANDONED
548 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::copySurface");
549
550 if (!src || !dst) {
551 return false;
552 }
553 ASSERT_OWNED_RESOURCE(src);
554 ASSERT_OWNED_RESOURCE(dst);
555
556 // We don't allow conversion between integer configs and float/fixed configs.
557 if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
558 return false;
559 }
560
561#ifndef ENABLE_MDB
562 // We can't yet fully defer copies to textures, so GrTextureContext::copySurface will
563 // execute the copy immediately. Ensure the data is ready.
564 src->flushWrites();
565#endif
566
567 sk_sp<GrSurfaceContext> surfaceContext(
568 this->contextPriv().makeWrappedSurfaceContext(sk_ref_sp(dst)));
569
570 if (!surfaceContext) {
571 return false;
572 }
573
574 if (!surfaceContext->copySurface(src, srcRect, dstPoint)) {
575 return false;
576 }
577
578 return true;
579}
580
bsalomonf80bfed2014-10-07 05:56:02 -0700581void GrContext::flushSurfaceWrites(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800582 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800583 RETURN_IF_ABANDONED
bsalomonf80bfed2014-10-07 05:56:02 -0700584 if (surface->surfacePriv().hasPendingWrite()) {
585 this->flush();
586 }
587}
588
ajuma95243eb2016-08-24 08:19:02 -0700589void GrContext::flushSurfaceIO(GrSurface* surface) {
590 ASSERT_SINGLE_OWNER
591 RETURN_IF_ABANDONED
592 if (surface->surfacePriv().hasPendingIO()) {
593 this->flush();
594 }
595}
596
bsalomon@google.com27847de2011-02-22 20:59:41 +0000597////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000598int GrContext::getRecommendedSampleCount(GrPixelConfig config,
599 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800600 ASSERT_SINGLE_OWNER
601
bsalomon76228632015-05-29 08:02:10 -0700602 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000603 return 0;
604 }
605 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700606 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000607 if (dpi >= 250.0f) {
608 chosenSampleCount = 4;
609 } else {
610 chosenSampleCount = 16;
611 }
612 }
egdanieleed519e2016-01-15 11:36:18 -0800613 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000614}
615
Brian Osman11052242016-10-27 14:47:55 -0400616sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext(
617 sk_sp<GrRenderTarget> rt,
618 sk_sp<SkColorSpace> colorSpace,
619 const SkSurfaceProps* surfaceProps) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700620 ASSERT_SINGLE_OWNER_PRIV
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400621
Robert Phillips37430132016-11-09 06:50:43 -0500622 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400623
Robert Phillips37430132016-11-09 06:50:43 -0500624 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400625 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400626 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700627}
robertphillips77a2e522015-10-17 07:43:27 -0700628
Brian Osman45580d32016-11-23 09:37:01 -0500629sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface> surface) {
630 ASSERT_SINGLE_OWNER_PRIV
631
632 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
633
634 if (proxy->asRenderTargetProxy()) {
635 return this->drawingManager()->makeRenderTargetContext(std::move(proxy), nullptr, nullptr);
636 } else {
637 SkASSERT(proxy->asTextureProxy());
638 return this->drawingManager()->makeTextureContext(std::move(proxy));
639 }
640}
641
Brian Osman11052242016-10-27 14:47:55 -0400642sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
Robert Phillipsd316e772016-12-14 12:04:46 +0000643 const GrBackendTextureDesc& desc,
Brian Osman11052242016-10-27 14:47:55 -0400644 sk_sp<SkColorSpace> colorSpace,
645 const SkSurfaceProps* props,
646 GrWrapOwnership ownership) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700647 ASSERT_SINGLE_OWNER_PRIV
648 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
649
650 sk_sp<GrSurface> surface(fContext->textureProvider()->wrapBackendTexture(desc, ownership));
651 if (!surface) {
652 return nullptr;
653 }
654
Robert Phillips37430132016-11-09 06:50:43 -0500655 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400656
Robert Phillips37430132016-11-09 06:50:43 -0500657 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Brian Osman11052242016-10-27 14:47:55 -0400658 std::move(colorSpace), props);
robertphillips4fd74ae2016-08-03 14:26:53 -0700659}
660
Brian Osman11052242016-10-27 14:47:55 -0400661sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
robertphillips4fd74ae2016-08-03 14:26:53 -0700662 const GrBackendRenderTargetDesc& desc,
663 sk_sp<SkColorSpace> colorSpace,
664 const SkSurfaceProps* surfaceProps) {
665 ASSERT_SINGLE_OWNER_PRIV
666
667 sk_sp<GrRenderTarget> rt(fContext->textureProvider()->wrapBackendRenderTarget(desc));
668 if (!rt) {
669 return nullptr;
670 }
671
Robert Phillips37430132016-11-09 06:50:43 -0500672 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400673
Robert Phillips37430132016-11-09 06:50:43 -0500674 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400675 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400676 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700677}
678
Brian Osman11052242016-10-27 14:47:55 -0400679sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
egdaniela95d46b2016-08-15 08:06:29 -0700680 const GrBackendTextureDesc& desc,
robertphillips4fd74ae2016-08-03 14:26:53 -0700681 sk_sp<SkColorSpace> colorSpace,
682 const SkSurfaceProps* surfaceProps) {
683 ASSERT_SINGLE_OWNER_PRIV
684 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
685
686 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
687 if (!surface) {
688 return nullptr;
689 }
690
Robert Phillips37430132016-11-09 06:50:43 -0500691 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400692
Robert Phillips37430132016-11-09 06:50:43 -0500693 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400694 std::move(colorSpace),
695 surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700696}
697
robertphillips48fde9c2016-09-06 05:20:20 -0700698static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
699 static const GrPixelConfig kFallback[] = {
700 kUnknown_GrPixelConfig, // kUnknown_GrPixelConfig
701 kRGBA_8888_GrPixelConfig, // kAlpha_8_GrPixelConfig
702 kUnknown_GrPixelConfig, // kIndex_8_GrPixelConfig
703 kRGBA_8888_GrPixelConfig, // kRGB_565_GrPixelConfig
704 kRGBA_8888_GrPixelConfig, // kRGBA_4444_GrPixelConfig
705 kUnknown_GrPixelConfig, // kRGBA_8888_GrPixelConfig
706 kRGBA_8888_GrPixelConfig, // kBGRA_8888_GrPixelConfig
707 kUnknown_GrPixelConfig, // kSRGBA_8888_GrPixelConfig
708 kSRGBA_8888_GrPixelConfig, // kSBGRA_8888_GrPixelConfig
Brian Salomonbf7b6202016-11-11 16:08:03 -0500709 kUnknown_GrPixelConfig, // kRGBA_8888_sint_GrPixelConfig
robertphillips48fde9c2016-09-06 05:20:20 -0700710 kUnknown_GrPixelConfig, // kETC1_GrPixelConfig
711 kUnknown_GrPixelConfig, // kLATC_GrPixelConfig
712 kUnknown_GrPixelConfig, // kR11_EAC_GrPixelConfig
713 kUnknown_GrPixelConfig, // kASTC_12x12_GrPixelConfig
714 kUnknown_GrPixelConfig, // kRGBA_float_GrPixelConfig
715 kRGBA_half_GrPixelConfig, // kAlpha_half_GrPixelConfig
716 kUnknown_GrPixelConfig, // kRGBA_half_GrPixelConfig
717 };
718 return kFallback[config];
719
720 GR_STATIC_ASSERT(0 == kUnknown_GrPixelConfig);
721 GR_STATIC_ASSERT(1 == kAlpha_8_GrPixelConfig);
722 GR_STATIC_ASSERT(2 == kIndex_8_GrPixelConfig);
723 GR_STATIC_ASSERT(3 == kRGB_565_GrPixelConfig);
724 GR_STATIC_ASSERT(4 == kRGBA_4444_GrPixelConfig);
725 GR_STATIC_ASSERT(5 == kRGBA_8888_GrPixelConfig);
726 GR_STATIC_ASSERT(6 == kBGRA_8888_GrPixelConfig);
727 GR_STATIC_ASSERT(7 == kSRGBA_8888_GrPixelConfig);
728 GR_STATIC_ASSERT(8 == kSBGRA_8888_GrPixelConfig);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500729 GR_STATIC_ASSERT(9 == kRGBA_8888_sint_GrPixelConfig);
730 GR_STATIC_ASSERT(10 == kETC1_GrPixelConfig);
731 GR_STATIC_ASSERT(11 == kLATC_GrPixelConfig);
732 GR_STATIC_ASSERT(12 == kR11_EAC_GrPixelConfig);
733 GR_STATIC_ASSERT(13 == kASTC_12x12_GrPixelConfig);
734 GR_STATIC_ASSERT(14 == kRGBA_float_GrPixelConfig);
735 GR_STATIC_ASSERT(15 == kAlpha_half_GrPixelConfig);
736 GR_STATIC_ASSERT(16 == kRGBA_half_GrPixelConfig);
robertphillips48fde9c2016-09-06 05:20:20 -0700737 GR_STATIC_ASSERT(SK_ARRAY_COUNT(kFallback) == kGrPixelConfigCnt);
738}
739
Brian Osman11052242016-10-27 14:47:55 -0400740sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContextWithFallback(
741 SkBackingFit fit,
742 int width, int height,
743 GrPixelConfig config,
744 sk_sp<SkColorSpace> colorSpace,
745 int sampleCnt,
746 GrSurfaceOrigin origin,
747 const SkSurfaceProps* surfaceProps,
748 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700749 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
750 config = GrPixelConfigFallback(config);
751 }
752
Brian Osman11052242016-10-27 14:47:55 -0400753 return this->makeRenderTargetContext(fit, width, height, config, std::move(colorSpace),
754 sampleCnt, origin, surfaceProps, budgeted);
robertphillips48fde9c2016-09-06 05:20:20 -0700755}
756
robertphillipsd728f0c2016-11-21 11:05:03 -0800757sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallback(
758 SkBackingFit fit,
759 int width, int height,
760 GrPixelConfig config,
761 sk_sp<SkColorSpace> colorSpace,
762 int sampleCnt,
763 GrSurfaceOrigin origin,
764 const SkSurfaceProps* surfaceProps,
765 SkBudgeted budgeted) {
766 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
767 config = GrPixelConfigFallback(config);
768 }
769
770 return this->makeDeferredRenderTargetContext(fit, width, height, config, std::move(colorSpace),
771 sampleCnt, origin, surfaceProps, budgeted);
772}
773
Brian Osman11052242016-10-27 14:47:55 -0400774sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContext(SkBackingFit fit,
775 int width, int height,
776 GrPixelConfig config,
777 sk_sp<SkColorSpace> colorSpace,
778 int sampleCnt,
779 GrSurfaceOrigin origin,
780 const SkSurfaceProps* surfaceProps,
781 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700782 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
783 return nullptr;
784 }
785
robertphillipsd4c741e2016-04-28 09:55:15 -0700786 GrSurfaceDesc desc;
787 desc.fFlags = kRenderTarget_GrSurfaceFlag;
788 desc.fOrigin = origin;
789 desc.fWidth = width;
790 desc.fHeight = height;
791 desc.fConfig = config;
792 desc.fSampleCnt = sampleCnt;
793
794 sk_sp<GrTexture> tex;
robertphillips76948d42016-05-04 12:47:41 -0700795 if (SkBackingFit::kExact == fit) {
robertphillipsca6eafc2016-05-17 09:57:46 -0700796 tex.reset(this->textureProvider()->createTexture(desc, budgeted));
robertphillipsd4c741e2016-04-28 09:55:15 -0700797 } else {
798 tex.reset(this->textureProvider()->createApproxTexture(desc));
799 }
800 if (!tex) {
801 return nullptr;
802 }
803
Brian Osman11052242016-10-27 14:47:55 -0400804 sk_sp<GrRenderTargetContext> renderTargetContext(
805 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(tex->asRenderTarget()),
robertphillips6738c702016-07-27 12:13:51 -0700806 std::move(colorSpace), surfaceProps));
Brian Osman11052242016-10-27 14:47:55 -0400807 if (!renderTargetContext) {
robertphillipsd4c741e2016-04-28 09:55:15 -0700808 return nullptr;
809 }
810
Brian Osman11052242016-10-27 14:47:55 -0400811 return renderTargetContext;
robertphillipsd4c741e2016-04-28 09:55:15 -0700812}
813
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400814sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext(
815 SkBackingFit fit,
816 int width, int height,
817 GrPixelConfig config,
818 sk_sp<SkColorSpace> colorSpace,
819 int sampleCnt,
820 GrSurfaceOrigin origin,
821 const SkSurfaceProps* surfaceProps,
822 SkBudgeted budgeted) {
823 GrSurfaceDesc desc;
824 desc.fFlags = kRenderTarget_GrSurfaceFlag;
825 desc.fOrigin = origin;
826 desc.fWidth = width;
827 desc.fHeight = height;
828 desc.fConfig = config;
829 desc.fSampleCnt = sampleCnt;
830
Robert Phillips37430132016-11-09 06:50:43 -0500831 sk_sp<GrSurfaceProxy> rtp = GrSurfaceProxy::MakeDeferred(*this->caps(), desc, fit, budgeted);
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400832
833 return fDrawingManager->makeRenderTargetContext(std::move(rtp),
834 std::move(colorSpace),
835 surfaceProps);
836}
837
joshualitt1de610a2016-01-06 08:26:09 -0800838bool GrContext::abandoned() const {
839 ASSERT_SINGLE_OWNER
robertphillips7761d612016-05-16 09:14:53 -0700840 return fDrawingManager->wasAbandoned();
robertphillips77a2e522015-10-17 07:43:27 -0700841}
842
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000843namespace {
844void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
845 GrConfigConversionEffect::PMConversion pmToUPM;
846 GrConfigConversionEffect::PMConversion upmToPM;
847 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
848 *pmToUPMValue = pmToUPM;
849 *upmToPMValue = upmToPM;
850}
851}
852
bsalomon6c6f6582015-09-10 08:12:46 -0700853void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800854 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700855 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) {
856 SkAutoMutexAcquire ama(fTestPMConversionsMutex);
857 if (!fDidTestPMConversions) {
858 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
859 fDidTestPMConversions = true;
860 }
861 }
862}
863
bungeman06ca8ec2016-06-09 08:01:03 -0700864sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800865 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700866 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800867 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700868 // We should have already called this->testPMConversionsIfNecessary().
869 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000870 GrConfigConversionEffect::PMConversion pmToUPM =
871 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
872 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
bungeman06ca8ec2016-06-09 08:01:03 -0700873 return GrConfigConversionEffect::Make(texture, swizzle, pmToUPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000874 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700875 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000876 }
877}
878
bungeman06ca8ec2016-06-09 08:01:03 -0700879sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800880 const GrSwizzle& swizzle,
bsalomon6c6f6582015-09-10 08:12:46 -0700881 const SkMatrix& matrix) const {
joshualitt1de610a2016-01-06 08:26:09 -0800882 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700883 // We should have already called this->testPMConversionsIfNecessary().
884 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000885 GrConfigConversionEffect::PMConversion upmToPM =
886 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
887 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
bungeman06ca8ec2016-06-09 08:01:03 -0700888 return GrConfigConversionEffect::Make(texture, swizzle, upmToPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000889 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700890 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000891 }
892}
893
bsalomon636e8022015-07-29 06:08:46 -0700894bool GrContext::didFailPMUPMConversionTest() const {
joshualitt1de610a2016-01-06 08:26:09 -0800895 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700896 // We should have already called this->testPMConversionsIfNecessary().
897 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700898 // The PM<->UPM tests fail or succeed together so we only need to check one.
bsalomon6c6f6582015-09-10 08:12:46 -0700899 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion;
bsalomon636e8022015-07-29 06:08:46 -0700900}
901
bsalomon37f9a262015-02-02 13:00:10 -0800902//////////////////////////////////////////////////////////////////////////////
903
904void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800905 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800906 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800907 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800908 }
909 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800910 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800911 }
912}
913
914void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800915 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800916 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800917}
918
ericrk0a5fa482015-09-15 14:16:10 -0700919//////////////////////////////////////////////////////////////////////////////
920
921void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800922 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700923 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
924}