blob: 07ae6b226ec0e6f04249aa349b69cc0cf10acbaf [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"
Brian Salomonc65aec92017-03-09 09:03:58 -05009#include "GrClip.h"
bsalomon682c2692015-05-22 14:01:46 -070010#include "GrContextOptions.h"
Brian Salomonc65aec92017-03-09 09:03:58 -050011#include "GrContextPriv.h"
robertphillips77a2e522015-10-17 07:43:27 -070012#include "GrDrawingManager.h"
Brian Osman11052242016-10-27 14:47:55 -040013#include "GrRenderTargetContext.h"
Brian Salomonc65aec92017-03-09 09:03:58 -050014#include "GrRenderTargetProxy.h"
bsalomon0ea80f42015-02-11 10:49:59 -080015#include "GrResourceCache.h"
bsalomond309e7a2015-04-30 14:18:54 -070016#include "GrResourceProvider.h"
Greg Danield85f97d2017-03-07 13:37:21 -050017#include "GrSemaphore.h"
robertphillips@google.com72176b22012-05-23 13:19:12 +000018#include "GrSoftwarePathRenderer.h"
Brian Osman45580d32016-11-23 09:37:01 -050019#include "GrSurfaceContext.h"
bsalomonafbf2d62014-09-30 12:18:44 -070020#include "GrSurfacePriv.h"
Robert Phillips757914d2017-01-25 15:48:30 -050021#include "GrSurfaceProxyPriv.h"
Brian Osman45580d32016-11-23 09:37:01 -050022#include "GrTextureContext.h"
Matt Sarett485c4992017-02-14 14:18:27 -050023#include "SkConvertPixels.h"
Brian Osman3b655982017-03-07 16:58:08 -050024#include "SkGr.h"
Matt Sarettc7b29082017-02-09 16:22:39 -050025#include "SkUnPreMultiplyPriv.h"
joshualitt5478d422014-11-14 16:00:38 -080026#include "effects/GrConfigConversionEffect.h"
joshualitte8042922015-12-11 06:11:21 -080027#include "text/GrTextBlobCache.h"
joshualitt5478d422014-11-14 16:00:38 -080028
Robert Phillipse78b7252017-04-06 07:59:41 -040029#define ASSERT_OWNED_PROXY(P) \
30SkASSERT(!(P) || !((P)->priv().peekTexture()) || (P)->priv().peekTexture()->getContext() == this)
Robert Phillips7ee385e2017-03-30 08:02:11 -040031#define ASSERT_OWNED_PROXY_PRIV(P) \
32SkASSERT(!(P) || !((P)->priv().peekTexture()) || (P)->priv().peekTexture()->getContext() == fContext)
33
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000034#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
joshualitt1de610a2016-01-06 08:26:09 -080035#define ASSERT_SINGLE_OWNER \
36 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);)
robertphillips4fd74ae2016-08-03 14:26:53 -070037#define ASSERT_SINGLE_OWNER_PRIV \
38 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070039#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
Robert Phillips7ee385e2017-03-30 08:02:11 -040040#define RETURN_IF_ABANDONED_PRIV if (fContext->fDrawingManager->wasAbandoned()) { return; }
robertphillips7761d612016-05-16 09:14:53 -070041#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
Robert Phillipse78b7252017-04-06 07:59:41 -040042#define RETURN_FALSE_IF_ABANDONED_PRIV if (fContext->fDrawingManager->wasAbandoned()) { return false; }
robertphillips7761d612016-05-16 09:14:53 -070043#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000044
robertphillipsea461502015-05-26 11:38:03 -070045////////////////////////////////////////////////////////////////////////////////
46
bsalomon682c2692015-05-22 14:01:46 -070047GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
48 GrContextOptions defaultOptions;
49 return Create(backend, backendContext, defaultOptions);
50}
bsalomonf28cff72015-05-22 12:25:41 -070051
bsalomon682c2692015-05-22 14:01:46 -070052GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
53 const GrContextOptions& options) {
halcanary385fe4d2015-08-26 13:07:48 -070054 GrContext* context = new GrContext;
bsalomon682c2692015-05-22 14:01:46 -070055
56 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000057 return context;
58 } else {
59 context->unref();
halcanary96fcdcc2015-08-27 07:41:13 -070060 return nullptr;
bsalomon@google.com27847de2011-02-22 20:59:41 +000061 }
bsalomon@google.com27847de2011-02-22 20:59:41 +000062}
63
joshualitt0acd0d32015-05-07 08:23:19 -070064static int32_t gNextID = 1;
65static int32_t next_id() {
66 int32_t id;
67 do {
68 id = sk_atomic_inc(&gNextID);
69 } while (id == SK_InvalidGenID);
70 return id;
71}
72
bsalomon682c2692015-05-22 14:01:46 -070073GrContext::GrContext() : fUniqueID(next_id()) {
halcanary96fcdcc2015-08-27 07:41:13 -070074 fGpu = nullptr;
75 fCaps = nullptr;
76 fResourceCache = nullptr;
77 fResourceProvider = nullptr;
Brian Salomonf856fd12016-12-16 14:24:34 -050078 fAtlasGlyphCache = nullptr;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000079}
80
bsalomon682c2692015-05-22 14:01:46 -070081bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
82 const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080083 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -070084 SkASSERT(!fGpu);
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000085
bsalomon682c2692015-05-22 14:01:46 -070086 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -070087 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000088 return false;
89 }
bsalomon69cfe952015-11-30 13:27:47 -080090 this->initCommon(options);
bsalomon33435572014-11-05 14:47:41 -080091 return true;
92}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000093
bsalomon69cfe952015-11-30 13:27:47 -080094void GrContext::initCommon(const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080095 ASSERT_SINGLE_OWNER
96
bsalomon76228632015-05-29 08:02:10 -070097 fCaps = SkRef(fGpu->caps());
halcanary385fe4d2015-08-26 13:07:48 -070098 fResourceCache = new GrResourceCache(fCaps);
joshualitt6d0872d2016-01-11 08:27:48 -080099 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +0000100
Brian Osman46da1cc2017-02-14 14:15:48 -0500101 fDisableGpuYUVConversion = options.fDisableGpuYUVConversion;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000102 fDidTestPMConversions = false;
103
Robert Phillipsf2361d22016-10-25 14:20:06 -0400104 GrRenderTargetOpList::Options rtOpListOptions;
Brian Salomon09d994e2016-12-21 11:14:46 -0500105 rtOpListOptions.fMaxOpCombineLookback = options.fMaxOpCombineLookback;
106 rtOpListOptions.fMaxOpCombineLookahead = options.fMaxOpCombineLookahead;
bsalomon6b2552f2016-09-15 13:50:26 -0700107 GrPathRendererChain::Options prcOptions;
bsalomon39ef7fb2016-09-21 11:16:05 -0700108 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching;
csmartdalton008b9d82017-02-22 12:00:42 -0700109 prcOptions.fGpuPathRenderers = options.fGpuPathRenderers;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400110 fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions,
111 options.fImmediateMode, &fSingleOwner));
joshualitt7c3a2f82015-03-31 13:32:05 -0700112
Brian Salomonf856fd12016-12-16 14:24:34 -0500113 fAtlasGlyphCache = new GrAtlasGlyphCache(this);
joshualittb7133be2015-04-08 09:08:31 -0700114
halcanary385fe4d2015-08-26 13:07:48 -0700115 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000116}
117
bsalomon@google.com27847de2011-02-22 20:59:41 +0000118GrContext::~GrContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800119 ASSERT_SINGLE_OWNER
120
robertphillipsea461502015-05-26 11:38:03 -0700121 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700122 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000123 return;
124 }
125
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000126 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000127
robertphillips77a2e522015-10-17 07:43:27 -0700128 fDrawingManager->cleanup();
robertphillips2334fb62015-06-17 05:43:33 -0700129
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000130 for (int i = 0; i < fCleanUpData.count(); ++i) {
131 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
132 }
133
halcanary385fe4d2015-08-26 13:07:48 -0700134 delete fResourceProvider;
135 delete fResourceCache;
Brian Salomonf856fd12016-12-16 14:24:34 -0500136 delete fAtlasGlyphCache;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000137
bsalomon@google.com205d4602011-04-25 12:43:45 +0000138 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700139 fCaps->unref();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000140}
141
bungeman6bd52842016-10-27 09:30:08 -0700142sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
bsalomon41b952c2016-03-11 06:46:33 -0800143 if (!fThreadSafeProxy) {
bungeman6bd52842016-10-27 09:30:08 -0700144 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(sk_ref_sp(fCaps), this->uniqueID()));
bsalomon41b952c2016-03-11 06:46:33 -0800145 }
bungeman6bd52842016-10-27 09:30:08 -0700146 return fThreadSafeProxy;
bsalomon41b952c2016-03-11 06:46:33 -0800147}
148
bsalomon2354f842014-07-28 13:48:36 -0700149void GrContext::abandonContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800150 ASSERT_SINGLE_OWNER
151
bsalomond309e7a2015-04-30 14:18:54 -0700152 fResourceProvider->abandon();
robertphillips0dfa62c2015-11-16 06:23:31 -0800153
154 // Need to abandon the drawing manager first so all the render targets
155 // will be released/forgotten before they too are abandoned.
156 fDrawingManager->abandon();
157
bsalomon@google.com205d4602011-04-25 12:43:45 +0000158 // abandon first to so destructors
159 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800160 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700161
bsalomon6e2aad42016-04-01 11:54:31 -0700162 fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
163
Brian Salomonf856fd12016-12-16 14:24:34 -0500164 fAtlasGlyphCache->freeAll();
bsalomon6e2aad42016-04-01 11:54:31 -0700165 fTextBlobCache->freeAll();
166}
167
168void GrContext::releaseResourcesAndAbandonContext() {
169 ASSERT_SINGLE_OWNER
170
171 fResourceProvider->abandon();
172
173 // Need to abandon the drawing manager first so all the render targets
174 // will be released/forgotten before they too are abandoned.
175 fDrawingManager->abandon();
176
177 // Release all resources in the backend 3D API.
178 fResourceCache->releaseAll();
179
180 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000181
Brian Salomonf856fd12016-12-16 14:24:34 -0500182 fAtlasGlyphCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700183 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000184}
185
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000186void GrContext::resetContext(uint32_t state) {
joshualitt1de610a2016-01-06 08:26:09 -0800187 ASSERT_SINGLE_OWNER
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000188 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000189}
190
191void GrContext::freeGpuResources() {
joshualitt1de610a2016-01-06 08:26:09 -0800192 ASSERT_SINGLE_OWNER
193
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000194 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000195
Brian Salomonf856fd12016-12-16 14:24:34 -0500196 fAtlasGlyphCache->freeAll();
robertphillips68737822015-10-29 12:12:21 -0700197
198 fDrawingManager->freeGpuResources();
bsalomon3033b9f2015-04-13 11:09:56 -0700199
200 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000201}
202
Brian Salomon5e150852017-03-22 14:53:13 -0400203void GrContext::purgeResourcesNotUsedInMs(std::chrono::milliseconds ms) {
204 ASSERT_SINGLE_OWNER
205 fResourceCache->purgeResourcesNotUsedSince(GrStdSteadyClock::now() - ms);
206}
207
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000208void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800209 ASSERT_SINGLE_OWNER
210
bsalomon71cb0c22014-11-14 12:10:14 -0800211 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800212 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800213 }
214 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800215 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800216 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000217}
218
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000219////////////////////////////////////////////////////////////////////////////////
220
joshualitt0db6dfa2015-04-10 07:01:30 -0700221void GrContext::TextBlobCacheOverBudgetCB(void* data) {
222 SkASSERT(data);
Brian Osman11052242016-10-27 14:47:55 -0400223 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
224 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls
225 // to below the GrContext level, but this is not trivial because they call drawPath on
226 // SkGpuDevice.
joshualitt0db6dfa2015-04-10 07:01:30 -0700227 GrContext* context = reinterpret_cast<GrContext*>(data);
228 context->flush();
229}
230
bsalomon@google.com27847de2011-02-22 20:59:41 +0000231////////////////////////////////////////////////////////////////////////////////
232
bsalomonb77a9072016-09-07 10:02:04 -0700233void GrContext::flush() {
joshualitt1de610a2016-01-06 08:26:09 -0800234 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700235 RETURN_IF_ABANDONED
Robert Phillips7ee385e2017-03-30 08:02:11 -0400236
237 fDrawingManager->flush(nullptr);
238}
239
240void GrContextPriv::flush(GrSurfaceProxy* proxy) {
241 ASSERT_SINGLE_OWNER_PRIV
242 RETURN_IF_ABANDONED_PRIV
243 ASSERT_OWNED_PROXY_PRIV(proxy);
244
245 fContext->fDrawingManager->flush(proxy);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000246}
247
bsalomon81beccc2014-10-13 12:32:55 -0700248bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
249 const void* inPixels, size_t outRowBytes, void* outPixels) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500250 SkColorType colorType;
251 if (!GrPixelConfigToColorType(srcConfig, &colorType) ||
252 4 != SkColorTypeBytesPerPixel(colorType))
253 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000254 return false;
255 }
bsalomon81beccc2014-10-13 12:32:55 -0700256
Matt Sarettc7b29082017-02-09 16:22:39 -0500257 for (int y = 0; y < height; y++) {
258 SkOpts::RGBA_to_rgbA((uint32_t*) outPixels, inPixels, width);
259 outPixels = SkTAddOffset<void>(outPixels, outRowBytes);
260 inPixels = SkTAddOffset<const void>(inPixels, inRowBytes);
261 }
bsalomon81beccc2014-10-13 12:32:55 -0700262
Matt Sarettc7b29082017-02-09 16:22:39 -0500263 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000264}
265
Brian Osmance425512017-03-22 14:37:50 -0400266static bool valid_unpremul_config(GrPixelConfig config) {
267 return GrPixelConfigIs8888Unorm(config) || kRGBA_half_GrPixelConfig == config;
268}
269
Robert Phillipse78b7252017-04-06 07:59:41 -0400270bool GrContextPriv::writeSurfacePixels(GrSurfaceProxy* srcProxy, SkColorSpace* dstColorSpace,
271 int left, int top, int width, int height,
272 GrPixelConfig srcConfig, SkColorSpace* srcColorSpace,
273 const void* buffer, size_t rowBytes,
274 uint32_t pixelOpsFlags) {
Brian Osmanb62ea222016-12-22 11:12:16 -0500275 // TODO: Color space conversion
276
Robert Phillipse78b7252017-04-06 07:59:41 -0400277 ASSERT_SINGLE_OWNER_PRIV
278 RETURN_FALSE_IF_ABANDONED_PRIV
279 ASSERT_OWNED_PROXY_PRIV(srcProxy);
280 SkASSERT(srcProxy);
281 GR_AUDIT_TRAIL_AUTO_FRAME(&fContext->fAuditTrail, "GrContextPriv::writeSurfacePixels");
bsalomon6c6f6582015-09-10 08:12:46 -0700282
Robert Phillipse78b7252017-04-06 07:59:41 -0400283 GrSurface* surface = srcProxy->instantiate(fContext->resourceProvider());
284 if (!surface) {
285 return false;
286 }
287
288 fContext->testPMConversionsIfNecessary(pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700289
bsalomone8d21e82015-07-16 08:23:13 -0700290 // 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 -0700291 // necessary and because GrGpu::getWritePixelsInfo requires it.
bsalomone8d21e82015-07-16 08:23:13 -0700292 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
293 GrBytesPerPixel(srcConfig), &left, &top, &width,
294 &height, &buffer, &rowBytes)) {
295 return false;
296 }
297
Brian Osmance425512017-03-22 14:37:50 -0400298 bool applyPremulToSrc = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
299 if (applyPremulToSrc && !valid_unpremul_config(srcConfig)) {
300 return false;
bsalomonf0674512015-07-28 13:26:15 -0700301 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500302 // We don't allow conversion between integer configs and float/fixed configs.
303 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(srcConfig)) {
304 return false;
305 }
bsalomon636e8022015-07-29 06:08:46 -0700306
307 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
308 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
309 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
Robert Phillipse78b7252017-04-06 07:59:41 -0400310 if (applyPremulToSrc && fContext->validPMUPMConversionExists(srcConfig)) {
bsalomon636e8022015-07-29 06:08:46 -0700311 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
312 }
313
bsalomonf0674512015-07-28 13:26:15 -0700314 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
Robert Phillipse78b7252017-04-06 07:59:41 -0400315 if (!fContext->fGpu->getWritePixelsInfo(surface, width, height, srcConfig,
316 &drawPreference, &tempDrawInfo)) {
bsalomonf0674512015-07-28 13:26:15 -0700317 return false;
318 }
319
320 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400321 this->flush(nullptr); // MDB TODO: tighten this
bsalomonf0674512015-07-28 13:26:15 -0700322 }
323
Robert Phillips2f493142017-03-02 18:18:38 -0500324 sk_sp<GrTextureProxy> tempProxy;
bsalomonf0674512015-07-28 13:26:15 -0700325 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400326 tempProxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(),
Robert Phillips2f493142017-03-02 18:18:38 -0500327 tempDrawInfo.fTempSurfaceDesc,
328 SkBackingFit::kApprox,
329 SkBudgeted::kYes);
330 if (!tempProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
bsalomonf0674512015-07-28 13:26:15 -0700331 return false;
332 }
333 }
334
335 // temp buffer for doing sw premul conversion, if needed.
336 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
Robert Phillips2f493142017-03-02 18:18:38 -0500337 if (tempProxy) {
Brian Osman60cd57e2017-04-06 10:19:06 -0400338 sk_sp<GrFragmentProcessor> texFP = GrSimpleTextureEffect::Make(
339 fContext->resourceProvider(), tempProxy, nullptr, SkMatrix::I());
bungeman06ca8ec2016-06-09 08:01:03 -0700340 sk_sp<GrFragmentProcessor> fp;
bsalomonf0674512015-07-28 13:26:15 -0700341 if (applyPremulToSrc) {
Brian Osman60cd57e2017-04-06 10:19:06 -0400342 fp = fContext->createUPMToPMEffect(texFP, tempProxy->config());
343 if (fp) {
344 // We no longer need to do this on CPU before the upload.
bsalomonf0674512015-07-28 13:26:15 -0700345 applyPremulToSrc = false;
Brian Osman60cd57e2017-04-06 10:19:06 -0400346 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
347 // We only wanted to do the draw to perform the premul so don't bother.
348 tempProxy.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700349 }
350 }
Robert Phillips2f493142017-03-02 18:18:38 -0500351 if (tempProxy) {
bsalomonf0674512015-07-28 13:26:15 -0700352 if (!fp) {
Brian Osman60cd57e2017-04-06 10:19:06 -0400353 fp = std::move(texFP);
bsalomonf0674512015-07-28 13:26:15 -0700354 }
Brian Osman60cd57e2017-04-06 10:19:06 -0400355 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
356 SkASSERT(fp);
357
Robert Phillips7ee385e2017-03-30 08:02:11 -0400358 if (tempProxy->priv().hasPendingIO()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400359 this->flush(tempProxy.get());
Robert Phillips7ee385e2017-03-30 08:02:11 -0400360 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400361 GrTexture* texture = tempProxy->instantiate(fContext->resourceProvider());
Robert Phillips757914d2017-01-25 15:48:30 -0500362 if (!texture) {
363 return false;
364 }
bsalomonf0674512015-07-28 13:26:15 -0700365 if (applyPremulToSrc) {
366 size_t tmpRowBytes = 4 * width;
367 tmpPixels.reset(width * height);
368 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
369 tmpPixels.get())) {
370 return false;
371 }
372 rowBytes = tmpRowBytes;
373 buffer = tmpPixels.get();
374 applyPremulToSrc = false;
375 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400376 if (!fContext->fGpu->writePixels(texture, 0, 0, width, height,
377 tempDrawInfo.fWriteConfig, buffer,
378 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700379 return false;
380 }
381 SkMatrix matrix;
382 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
brianosmandfe4f2e2016-07-21 13:28:36 -0700383 // TODO: Need to decide the semantics of this function for color spaces. Do we support
384 // conversion from a passed-in color space? For now, specifying nullptr means that this
385 // path will do no conversion, so it will match the behavior of the non-draw path.
Robert Phillips757914d2017-01-25 15:48:30 -0500386 GrRenderTarget* renderTarget = surface->asRenderTarget();
387 SkASSERT(renderTarget);
Brian Osman11052242016-10-27 14:47:55 -0400388 sk_sp<GrRenderTargetContext> renderTargetContext(
Robert Phillipse78b7252017-04-06 07:59:41 -0400389 this->makeWrappedRenderTargetContext(sk_ref_sp(renderTarget), nullptr));
Brian Osman11052242016-10-27 14:47:55 -0400390 if (!renderTargetContext) {
bsalomonf0674512015-07-28 13:26:15 -0700391 return false;
392 }
egdanielc4b72722015-11-23 13:20:41 -0800393 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700394 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700395 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700396 paint.setAllowSRGBInputs(true);
bsalomonf0674512015-07-28 13:26:15 -0700397 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon82f44312017-01-11 13:42:54 -0500398 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect,
399 nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700400
401 if (kFlushWrites_PixelOp & pixelOpsFlags) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400402 this->flushSurfaceWrites(renderTargetContext->asRenderTargetProxy());
bsalomonf0674512015-07-28 13:26:15 -0700403 }
404 }
405 }
Robert Phillips2f493142017-03-02 18:18:38 -0500406 if (!tempProxy) {
bsalomonf0674512015-07-28 13:26:15 -0700407 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700408 size_t tmpRowBytes = 4 * width;
409 tmpPixels.reset(width * height);
410 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
411 tmpPixels.get())) {
412 return false;
413 }
414 rowBytes = tmpRowBytes;
415 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700416 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700417 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400418 return fContext->fGpu->writePixels(surface, left, top, width, height, srcConfig,
419 buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700420 }
bsalomon81beccc2014-10-13 12:32:55 -0700421 return true;
422}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000423
Robert Phillipse78b7252017-04-06 07:59:41 -0400424bool GrContextPriv::readSurfacePixels(GrSurfaceProxy* srcProxy, SkColorSpace* srcColorSpace,
425 int left, int top, int width, int height,
426 GrPixelConfig dstConfig, SkColorSpace* dstColorSpace,
427 void* buffer, size_t rowBytes, uint32_t flags) {
Brian Osmanb62ea222016-12-22 11:12:16 -0500428 // TODO: Color space conversion
429
Robert Phillipse78b7252017-04-06 07:59:41 -0400430 ASSERT_SINGLE_OWNER_PRIV
431 RETURN_FALSE_IF_ABANDONED_PRIV
432 ASSERT_OWNED_PROXY_PRIV(srcProxy);
433 SkASSERT(srcProxy);
434 GR_AUDIT_TRAIL_AUTO_FRAME(&fContext->fAuditTrail, "GrContextPriv::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700435
Robert Phillipse78b7252017-04-06 07:59:41 -0400436 // MDB TODO: delay this instantiation until later in the method
437 GrSurface* src = srcProxy->instantiate(fContext->resourceProvider());
438 if (!src) {
439 return false;
440 }
441
442 fContext->testPMConversionsIfNecessary(flags);
bsalomon6c6f6582015-09-10 08:12:46 -0700443
bsalomone8d21e82015-07-16 08:23:13 -0700444 // Adjust the params so that if we wind up using an intermediate surface we've already done
445 // all the trimming and the temporary can be the min size required.
446 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
447 GrBytesPerPixel(dstConfig), &left,
448 &top, &width, &height, &buffer, &rowBytes)) {
449 return false;
450 }
451
452 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400453 this->flush(nullptr); // MDB TODO: tighten this
bsalomon@google.com6f379512011-11-16 20:36:03 +0000454 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000455
bsalomone8d21e82015-07-16 08:23:13 -0700456 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
Brian Osmance425512017-03-22 14:37:50 -0400457 if (unpremul && !valid_unpremul_config(dstConfig)) {
Brian Osmande1a6052017-03-22 10:57:00 -0400458 // The unpremul flag is only allowed for 8888 and F16 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000459 return false;
460 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500461 // We don't allow conversion between integer configs and float/fixed configs.
462 if (GrPixelConfigIsSint(src->config()) != GrPixelConfigIsSint(dstConfig)) {
463 return false;
464 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000465
bsalomon636e8022015-07-29 06:08:46 -0700466 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
467 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
468 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
Robert Phillipse78b7252017-04-06 07:59:41 -0400469 if (unpremul && fContext->validPMUPMConversionExists(src->config())) {
bsalomon636e8022015-07-29 06:08:46 -0700470 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
471 }
472
bsalomon39826022015-07-23 08:07:21 -0700473 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
Robert Phillipse78b7252017-04-06 07:59:41 -0400474 if (!fContext->fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig,
475 &drawPreference, &tempDrawInfo)) {
bsalomon39826022015-07-23 08:07:21 -0700476 return false;
477 }
bsalomon191bcc02014-11-14 11:31:13 -0800478
Robert Phillipse78b7252017-04-06 07:59:41 -0400479 sk_sp<GrSurfaceProxy> proxyToRead = sk_ref_sp(srcProxy);
bsalomon39826022015-07-23 08:07:21 -0700480 bool didTempDraw = false;
481 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomonb117ff12016-07-19 07:24:40 -0700482 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) {
bsalomon39826022015-07-23 08:07:21 -0700483 // We only respect this when the entire src is being read. Otherwise we can trigger too
484 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700485 if (width != src->width() || height != src->height()) {
bsalomonb117ff12016-07-19 07:24:40 -0700486 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox;
bsalomon39826022015-07-23 08:07:21 -0700487 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000488 }
brianosmandfe4f2e2016-07-21 13:28:36 -0700489 // TODO: Need to decide the semantics of this function for color spaces. Do we support
490 // conversion to a passed-in color space? For now, specifying nullptr means that this
491 // path will do no conversion, so it will match the behavior of the non-draw path.
Robert Phillipsd83ec042017-04-10 11:10:22 -0400492 sk_sp<GrRenderTargetContext> tempRTC = fContext->makeDeferredRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400493 tempDrawInfo.fTempSurfaceFit,
bsalomonb117ff12016-07-19 07:24:40 -0700494 tempDrawInfo.fTempSurfaceDesc.fWidth,
495 tempDrawInfo.fTempSurfaceDesc.fHeight,
496 tempDrawInfo.fTempSurfaceDesc.fConfig,
brianosmandfe4f2e2016-07-21 13:28:36 -0700497 nullptr,
bsalomonb117ff12016-07-19 07:24:40 -0700498 tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
499 tempDrawInfo.fTempSurfaceDesc.fOrigin);
Brian Osman693a5402016-10-27 15:13:22 -0400500 if (tempRTC) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500501 SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top));
Robert Phillipse78b7252017-04-06 07:59:41 -0400502 sk_sp<GrTextureProxy> proxy = sk_ref_sp(srcProxy->asTextureProxy());
Brian Osman60cd57e2017-04-06 10:19:06 -0400503 sk_sp<GrFragmentProcessor> texFP = GrSimpleTextureEffect::Make(
504 fContext->resourceProvider(), proxy, nullptr, textureMatrix);
bungeman06ca8ec2016-06-09 08:01:03 -0700505 sk_sp<GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000506 if (unpremul) {
Brian Osman60cd57e2017-04-06 10:19:06 -0400507 fp = fContext->createPMToUPMEffect(texFP, proxy->config());
joshualittb0a8a372014-09-23 09:50:21 -0700508 if (fp) {
Brian Osman60cd57e2017-04-06 10:19:06 -0400509 // We no longer need to do this on CPU after the read back.
510 unpremul = false;
bsalomon39826022015-07-23 08:07:21 -0700511 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
Brian Osman60cd57e2017-04-06 10:19:06 -0400512 // We only wanted to do the draw to perform the unpremul so don't bother.
Brian Osman693a5402016-10-27 15:13:22 -0400513 tempRTC.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000514 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000515 }
Brian Osman60cd57e2017-04-06 10:19:06 -0400516 if (tempRTC) {
517 if (!fp) {
518 fp = std::move(texFP);
519 }
Brian Osmance425512017-03-22 14:37:50 -0400520 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
Brian Osman60cd57e2017-04-06 10:19:06 -0400521 SkASSERT(fp);
522
egdanielc4b72722015-11-23 13:20:41 -0800523 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700524 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700525 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700526 paint.setAllowSRGBInputs(true);
bsalomon39826022015-07-23 08:07:21 -0700527 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon82f44312017-01-11 13:42:54 -0500528 tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect,
529 nullptr);
Robert Phillipse78b7252017-04-06 07:59:41 -0400530 proxyToRead = tempRTC->asTextureProxyRef();
bsalomon39826022015-07-23 08:07:21 -0700531 left = 0;
532 top = 0;
533 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000534 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000535 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000536 }
joshualitt5c55fef2014-10-31 14:04:35 -0700537
Robert Phillipse78b7252017-04-06 07:59:41 -0400538 if (!proxyToRead) {
539 return false;
540 }
541
542 GrSurface* surfaceToRead = proxyToRead->instantiate(fContext->resourceProvider());
Robert Phillips833dcf42016-11-18 08:44:13 -0500543 if (!surfaceToRead) {
544 return false;
545 }
546
bsalomon39826022015-07-23 08:07:21 -0700547 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000548 return false;
549 }
bsalomon39826022015-07-23 08:07:21 -0700550 GrPixelConfig configToRead = dstConfig;
551 if (didTempDraw) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400552 this->flushSurfaceWrites(proxyToRead.get());
bsalomon6c9cd552016-01-22 07:17:34 -0800553 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700554 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400555 if (!fContext->fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead,
556 buffer, rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700557 return false;
558 }
559
560 // Perform umpremul conversion if we weren't able to perform it as a draw.
561 if (unpremul) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500562 SkColorType colorType;
563 if (!GrPixelConfigToColorType(dstConfig, &colorType) ||
564 4 != SkColorTypeBytesPerPixel(colorType))
565 {
reed@google.com7111d462014-03-25 16:20:24 +0000566 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000567 }
reed@google.com7111d462014-03-25 16:20:24 +0000568
Matt Sarettc7b29082017-02-09 16:22:39 -0500569 for (int y = 0; y < height; y++) {
570 SkUnpremultiplyRow<false>((uint32_t*) buffer, (const uint32_t*) buffer, width);
571 buffer = SkTAddOffset<void>(buffer, rowBytes);
572 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000573 }
574 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000575}
576
Robert Phillips7ee385e2017-03-30 08:02:11 -0400577void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
578 ASSERT_SINGLE_OWNER_PRIV
579 RETURN_IF_ABANDONED_PRIV
580 SkASSERT(proxy);
581 ASSERT_OWNED_PROXY_PRIV(proxy);
582 fContext->fDrawingManager->prepareSurfaceForExternalIO(proxy);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000583}
584
Robert Phillips7ee385e2017-03-30 08:02:11 -0400585void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) {
586 ASSERT_SINGLE_OWNER_PRIV
587 RETURN_IF_ABANDONED_PRIV
588 SkASSERT(proxy);
589 ASSERT_OWNED_PROXY_PRIV(proxy);
590 if (proxy->priv().hasPendingWrite()) {
591 this->flush(proxy);
bsalomonf80bfed2014-10-07 05:56:02 -0700592 }
593}
594
Robert Phillips7ee385e2017-03-30 08:02:11 -0400595void GrContextPriv::flushSurfaceIO(GrSurfaceProxy* proxy) {
596 ASSERT_SINGLE_OWNER_PRIV
597 RETURN_IF_ABANDONED_PRIV
598 SkASSERT(proxy);
599 ASSERT_OWNED_PROXY_PRIV(proxy);
600 if (proxy->priv().hasPendingIO()) {
601 this->flush(proxy);
ajuma95243eb2016-08-24 08:19:02 -0700602 }
603}
604
bsalomon@google.com27847de2011-02-22 20:59:41 +0000605////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000606int GrContext::getRecommendedSampleCount(GrPixelConfig config,
607 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800608 ASSERT_SINGLE_OWNER
609
bsalomon76228632015-05-29 08:02:10 -0700610 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000611 return 0;
612 }
613 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700614 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000615 if (dpi >= 250.0f) {
616 chosenSampleCount = 4;
617 } else {
618 chosenSampleCount = 16;
619 }
620 }
egdanieleed519e2016-01-15 11:36:18 -0800621 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000622}
623
Brian Osman11052242016-10-27 14:47:55 -0400624sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext(
625 sk_sp<GrRenderTarget> rt,
626 sk_sp<SkColorSpace> colorSpace,
627 const SkSurfaceProps* surfaceProps) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700628 ASSERT_SINGLE_OWNER_PRIV
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400629
Robert Phillips37430132016-11-09 06:50:43 -0500630 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500631 if (!proxy) {
632 return nullptr;
633 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400634
Robert Phillips37430132016-11-09 06:50:43 -0500635 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400636 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400637 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700638}
robertphillips77a2e522015-10-17 07:43:27 -0700639
Robert Phillips2c862492017-01-18 10:08:39 -0500640sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
641 sk_sp<SkColorSpace> colorSpace) {
Brian Osman45580d32016-11-23 09:37:01 -0500642 ASSERT_SINGLE_OWNER_PRIV
643
Brian Osman45580d32016-11-23 09:37:01 -0500644 if (proxy->asRenderTargetProxy()) {
Robert Phillips2c862492017-01-18 10:08:39 -0500645 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
646 std::move(colorSpace), nullptr);
Brian Osman45580d32016-11-23 09:37:01 -0500647 } else {
648 SkASSERT(proxy->asTextureProxy());
Robert Phillips2c862492017-01-18 10:08:39 -0500649 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
Brian Osman45580d32016-11-23 09:37:01 -0500650 }
651}
652
Robert Phillips31c26082016-12-14 15:12:15 -0500653sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface> surface) {
654 ASSERT_SINGLE_OWNER_PRIV
655
656 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500657 if (!proxy) {
658 return nullptr;
659 }
Robert Phillips31c26082016-12-14 15:12:15 -0500660
Robert Phillips2c862492017-01-18 10:08:39 -0500661 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr);
Robert Phillips31c26082016-12-14 15:12:15 -0500662}
663
Robert Phillipse2f7d182016-12-15 09:23:05 -0500664sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
665 SkBackingFit fit,
666 SkBudgeted isDstBudgeted) {
667
Brian Osman32342f02017-03-04 08:12:46 -0500668 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400669 dstDesc, fit, isDstBudgeted);
Robert Phillips77b3f322017-01-31 18:24:12 -0500670 if (!proxy) {
671 return nullptr;
672 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500673
Robert Phillips2c862492017-01-18 10:08:39 -0500674 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500675}
676
Robert Phillips26caf892017-01-27 10:58:31 -0500677sk_sp<GrSurfaceContext> GrContextPriv::makeBackendSurfaceContext(const GrBackendTextureDesc& desc,
Brian Osmanc1e37052017-03-09 14:19:20 -0500678 sk_sp<SkColorSpace> colorSpace) {
Robert Phillips26caf892017-01-27 10:58:31 -0500679 ASSERT_SINGLE_OWNER_PRIV
680
Brian Osmanc1e37052017-03-09 14:19:20 -0500681 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc));
Robert Phillips26caf892017-01-27 10:58:31 -0500682 if (!surface) {
683 return nullptr;
684 }
685
686 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500687 if (!proxy) {
688 return nullptr;
689 }
Robert Phillips26caf892017-01-27 10:58:31 -0500690
691 return this->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace));
692}
693
Brian Osman11052242016-10-27 14:47:55 -0400694sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
Robert Phillipse305cc1f2016-12-14 12:19:05 -0500695 const GrBackendTextureDesc& desc,
Brian Osman11052242016-10-27 14:47:55 -0400696 sk_sp<SkColorSpace> colorSpace,
Brian Osmanc1e37052017-03-09 14:19:20 -0500697 const SkSurfaceProps* props) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700698 ASSERT_SINGLE_OWNER_PRIV
699 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
700
Brian Osmanc1e37052017-03-09 14:19:20 -0500701 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc));
robertphillips4fd74ae2016-08-03 14:26:53 -0700702 if (!surface) {
703 return nullptr;
704 }
705
Robert Phillips37430132016-11-09 06:50:43 -0500706 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500707 if (!proxy) {
708 return nullptr;
709 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400710
Robert Phillips37430132016-11-09 06:50:43 -0500711 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Brian Osman11052242016-10-27 14:47:55 -0400712 std::move(colorSpace), props);
robertphillips4fd74ae2016-08-03 14:26:53 -0700713}
714
Brian Osman11052242016-10-27 14:47:55 -0400715sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
robertphillips4fd74ae2016-08-03 14:26:53 -0700716 const GrBackendRenderTargetDesc& desc,
717 sk_sp<SkColorSpace> colorSpace,
718 const SkSurfaceProps* surfaceProps) {
719 ASSERT_SINGLE_OWNER_PRIV
720
Brian Osman32342f02017-03-04 08:12:46 -0500721 sk_sp<GrRenderTarget> rt(fContext->resourceProvider()->wrapBackendRenderTarget(desc));
robertphillips4fd74ae2016-08-03 14:26:53 -0700722 if (!rt) {
723 return nullptr;
724 }
725
Robert Phillips37430132016-11-09 06:50:43 -0500726 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500727 if (!proxy) {
728 return nullptr;
729 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400730
Robert Phillips37430132016-11-09 06:50:43 -0500731 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400732 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400733 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700734}
735
Brian Osman11052242016-10-27 14:47:55 -0400736sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
egdaniela95d46b2016-08-15 08:06:29 -0700737 const GrBackendTextureDesc& desc,
robertphillips4fd74ae2016-08-03 14:26:53 -0700738 sk_sp<SkColorSpace> colorSpace,
739 const SkSurfaceProps* surfaceProps) {
740 ASSERT_SINGLE_OWNER_PRIV
741 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
742
743 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
744 if (!surface) {
745 return nullptr;
746 }
747
Robert Phillips37430132016-11-09 06:50:43 -0500748 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500749 if (!proxy) {
750 return nullptr;
751 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400752
Robert Phillips37430132016-11-09 06:50:43 -0500753 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400754 std::move(colorSpace),
755 surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700756}
757
Robert Phillipseb35f4d2017-03-21 07:56:47 -0400758void GrContextPriv::addPreFlushCallbackObject(sk_sp<GrPreFlushCallbackObject> preFlushCBObject) {
759 fContext->fDrawingManager->addPreFlushCallbackObject(std::move(preFlushCBObject));
760}
761
762
robertphillips48fde9c2016-09-06 05:20:20 -0700763static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
Brian Osman78f20e02017-01-12 10:28:01 -0500764 switch (config) {
765 case kAlpha_8_GrPixelConfig:
766 case kRGB_565_GrPixelConfig:
767 case kRGBA_4444_GrPixelConfig:
768 case kBGRA_8888_GrPixelConfig:
769 return kRGBA_8888_GrPixelConfig;
770 case kSBGRA_8888_GrPixelConfig:
771 return kSRGBA_8888_GrPixelConfig;
772 case kAlpha_half_GrPixelConfig:
773 return kRGBA_half_GrPixelConfig;
774 default:
775 return kUnknown_GrPixelConfig;
776 }
robertphillips48fde9c2016-09-06 05:20:20 -0700777}
778
robertphillipsd728f0c2016-11-21 11:05:03 -0800779sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallback(
780 SkBackingFit fit,
781 int width, int height,
782 GrPixelConfig config,
783 sk_sp<SkColorSpace> colorSpace,
784 int sampleCnt,
785 GrSurfaceOrigin origin,
786 const SkSurfaceProps* surfaceProps,
787 SkBudgeted budgeted) {
788 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
789 config = GrPixelConfigFallback(config);
790 }
791
792 return this->makeDeferredRenderTargetContext(fit, width, height, config, std::move(colorSpace),
793 sampleCnt, origin, surfaceProps, budgeted);
794}
795
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400796sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext(
797 SkBackingFit fit,
798 int width, int height,
799 GrPixelConfig config,
800 sk_sp<SkColorSpace> colorSpace,
801 int sampleCnt,
802 GrSurfaceOrigin origin,
803 const SkSurfaceProps* surfaceProps,
804 SkBudgeted budgeted) {
Robert Phillipsd83ec042017-04-10 11:10:22 -0400805 SkASSERT(kDefault_GrSurfaceOrigin != origin);
806
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400807 GrSurfaceDesc desc;
808 desc.fFlags = kRenderTarget_GrSurfaceFlag;
809 desc.fOrigin = origin;
810 desc.fWidth = width;
811 desc.fHeight = height;
812 desc.fConfig = config;
813 desc.fSampleCnt = sampleCnt;
814
Brian Osman32342f02017-03-04 08:12:46 -0500815 sk_sp<GrTextureProxy> rtp = GrSurfaceProxy::MakeDeferred(this->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400816 desc, fit, budgeted);
Robert Phillips08c5ec72017-01-30 12:26:47 -0500817 if (!rtp) {
818 return nullptr;
819 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400820
821 return fDrawingManager->makeRenderTargetContext(std::move(rtp),
822 std::move(colorSpace),
823 surfaceProps);
824}
825
joshualitt1de610a2016-01-06 08:26:09 -0800826bool GrContext::abandoned() const {
827 ASSERT_SINGLE_OWNER
robertphillips7761d612016-05-16 09:14:53 -0700828 return fDrawingManager->wasAbandoned();
robertphillips77a2e522015-10-17 07:43:27 -0700829}
830
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000831namespace {
832void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
833 GrConfigConversionEffect::PMConversion pmToUPM;
834 GrConfigConversionEffect::PMConversion upmToPM;
835 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
836 *pmToUPMValue = pmToUPM;
837 *upmToPMValue = upmToPM;
838}
839}
840
bsalomon6c6f6582015-09-10 08:12:46 -0700841void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800842 ASSERT_SINGLE_OWNER
Robert Phillipse78b7252017-04-06 07:59:41 -0400843 if (SkToBool(GrContextPriv::kUnpremul_PixelOpsFlag & flags)) {
bsalomon6c6f6582015-09-10 08:12:46 -0700844 if (!fDidTestPMConversions) {
845 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
846 fDidTestPMConversions = true;
847 }
848 }
849}
850
Brian Osman60cd57e2017-04-06 10:19:06 -0400851sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrFragmentProcessor> fp,
852 GrPixelConfig config) {
Robert Phillips757914d2017-01-25 15:48:30 -0500853 ASSERT_SINGLE_OWNER
854 // We should have already called this->testPMConversionsIfNecessary().
855 SkASSERT(fDidTestPMConversions);
Brian Osmanee805322017-04-05 10:09:00 -0400856 if (kRGBA_half_GrPixelConfig == config) {
857 return GrFragmentProcessor::UnpremulOutput(std::move(fp));
858 } else if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
Brian Osmande1a6052017-03-22 10:57:00 -0400859 GrConfigConversionEffect::PMConversion pmToUPM =
860 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
Brian Osmance425512017-03-22 14:37:50 -0400861 if (GrConfigConversionEffect::kPMConversionCnt != pmToUPM) {
Brian Osmanee805322017-04-05 10:09:00 -0400862 return GrConfigConversionEffect::Make(std::move(fp), pmToUPM);
Brian Osmande1a6052017-03-22 10:57:00 -0400863 }
Robert Phillips757914d2017-01-25 15:48:30 -0500864 }
Brian Osmanee805322017-04-05 10:09:00 -0400865 return nullptr;
Robert Phillips757914d2017-01-25 15:48:30 -0500866}
867
Brian Osman60cd57e2017-04-06 10:19:06 -0400868sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrFragmentProcessor> fp,
869 GrPixelConfig config) {
joshualitt1de610a2016-01-06 08:26:09 -0800870 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700871 // We should have already called this->testPMConversionsIfNecessary().
872 SkASSERT(fDidTestPMConversions);
Brian Osmanee805322017-04-05 10:09:00 -0400873 if (kRGBA_half_GrPixelConfig == config) {
874 return GrFragmentProcessor::PremulOutput(std::move(fp));
875 } else if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
Brian Osmande1a6052017-03-22 10:57:00 -0400876 GrConfigConversionEffect::PMConversion upmToPM =
877 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
Brian Osmance425512017-03-22 14:37:50 -0400878 if (GrConfigConversionEffect::kPMConversionCnt != upmToPM) {
Brian Osmanee805322017-04-05 10:09:00 -0400879 return GrConfigConversionEffect::Make(std::move(fp), upmToPM);
Brian Osmande1a6052017-03-22 10:57:00 -0400880 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000881 }
Brian Osmanee805322017-04-05 10:09:00 -0400882 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000883}
884
Brian Osmande1a6052017-03-22 10:57:00 -0400885bool GrContext::validPMUPMConversionExists(GrPixelConfig config) const {
joshualitt1de610a2016-01-06 08:26:09 -0800886 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700887 // We should have already called this->testPMConversionsIfNecessary().
888 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700889 // The PM<->UPM tests fail or succeed together so we only need to check one.
Brian Osmande1a6052017-03-22 10:57:00 -0400890 // For F16, we always allow PM/UPM conversion on the GPU, even if it doesn't round-trip.
Brian Osmance425512017-03-22 14:37:50 -0400891 return GrConfigConversionEffect::kPMConversionCnt != fPMToUPMConversion ||
Brian Osmande1a6052017-03-22 10:57:00 -0400892 kRGBA_half_GrPixelConfig == config;
bsalomon636e8022015-07-29 06:08:46 -0700893}
894
bsalomon37f9a262015-02-02 13:00:10 -0800895//////////////////////////////////////////////////////////////////////////////
896
897void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800898 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800899 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800900 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800901 }
902 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800903 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800904 }
905}
906
907void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800908 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800909 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800910}
911
ericrk0a5fa482015-09-15 14:16:10 -0700912//////////////////////////////////////////////////////////////////////////////
913
914void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800915 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700916 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
917}