blob: 17db9566977541ffeda3eaf96053d5316d4cd844 [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
Greg Danielfc978fd2017-04-13 09:54:12 -040086 fBackend = backend;
87
bsalomon682c2692015-05-22 14:01:46 -070088 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -070089 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000090 return false;
91 }
bsalomon69cfe952015-11-30 13:27:47 -080092 this->initCommon(options);
bsalomon33435572014-11-05 14:47:41 -080093 return true;
94}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000095
bsalomon69cfe952015-11-30 13:27:47 -080096void GrContext::initCommon(const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080097 ASSERT_SINGLE_OWNER
98
bsalomon76228632015-05-29 08:02:10 -070099 fCaps = SkRef(fGpu->caps());
Brian Osman13dddce2017-05-09 13:19:50 -0400100 fResourceCache = new GrResourceCache(fCaps, fUniqueID);
joshualitt6d0872d2016-01-11 08:27:48 -0800101 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +0000102
Brian Osman46da1cc2017-02-14 14:15:48 -0500103 fDisableGpuYUVConversion = options.fDisableGpuYUVConversion;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +0000104 fDidTestPMConversions = false;
105
bsalomon6b2552f2016-09-15 13:50:26 -0700106 GrPathRendererChain::Options prcOptions;
bsalomon39ef7fb2016-09-21 11:16:05 -0700107 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching;
csmartdalton008b9d82017-02-22 12:00:42 -0700108 prcOptions.fGpuPathRenderers = options.fGpuPathRenderers;
Robert Phillips3ea17982017-06-02 12:43:04 -0400109 fDrawingManager.reset(new GrDrawingManager(this, prcOptions, &fSingleOwner));
joshualitt7c3a2f82015-03-31 13:32:05 -0700110
Eric Karl6d342282017-05-03 17:08:42 -0700111 fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes);
joshualittb7133be2015-04-08 09:08:31 -0700112
halcanary385fe4d2015-08-26 13:07:48 -0700113 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000114}
115
bsalomon@google.com27847de2011-02-22 20:59:41 +0000116GrContext::~GrContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800117 ASSERT_SINGLE_OWNER
118
robertphillipsea461502015-05-26 11:38:03 -0700119 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700120 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000121 return;
122 }
123
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000124 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000125
robertphillips77a2e522015-10-17 07:43:27 -0700126 fDrawingManager->cleanup();
robertphillips2334fb62015-06-17 05:43:33 -0700127
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000128 for (int i = 0; i < fCleanUpData.count(); ++i) {
129 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
130 }
131
halcanary385fe4d2015-08-26 13:07:48 -0700132 delete fResourceProvider;
133 delete fResourceCache;
Brian Salomonf856fd12016-12-16 14:24:34 -0500134 delete fAtlasGlyphCache;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000135
bsalomon@google.com205d4602011-04-25 12:43:45 +0000136 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700137 fCaps->unref();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000138}
139
bungeman6bd52842016-10-27 09:30:08 -0700140sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
bsalomon41b952c2016-03-11 06:46:33 -0800141 if (!fThreadSafeProxy) {
bungeman6bd52842016-10-27 09:30:08 -0700142 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(sk_ref_sp(fCaps), this->uniqueID()));
bsalomon41b952c2016-03-11 06:46:33 -0800143 }
bungeman6bd52842016-10-27 09:30:08 -0700144 return fThreadSafeProxy;
bsalomon41b952c2016-03-11 06:46:33 -0800145}
146
bsalomon2354f842014-07-28 13:48:36 -0700147void GrContext::abandonContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800148 ASSERT_SINGLE_OWNER
149
bsalomond309e7a2015-04-30 14:18:54 -0700150 fResourceProvider->abandon();
robertphillips0dfa62c2015-11-16 06:23:31 -0800151
152 // Need to abandon the drawing manager first so all the render targets
153 // will be released/forgotten before they too are abandoned.
154 fDrawingManager->abandon();
155
bsalomon@google.com205d4602011-04-25 12:43:45 +0000156 // abandon first to so destructors
157 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800158 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700159
bsalomon6e2aad42016-04-01 11:54:31 -0700160 fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
161
Brian Salomonf856fd12016-12-16 14:24:34 -0500162 fAtlasGlyphCache->freeAll();
bsalomon6e2aad42016-04-01 11:54:31 -0700163 fTextBlobCache->freeAll();
164}
165
166void GrContext::releaseResourcesAndAbandonContext() {
167 ASSERT_SINGLE_OWNER
168
169 fResourceProvider->abandon();
170
171 // Need to abandon the drawing manager first so all the render targets
172 // will be released/forgotten before they too are abandoned.
173 fDrawingManager->abandon();
174
175 // Release all resources in the backend 3D API.
176 fResourceCache->releaseAll();
177
178 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000179
Brian Salomonf856fd12016-12-16 14:24:34 -0500180 fAtlasGlyphCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700181 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000182}
183
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000184void GrContext::resetContext(uint32_t state) {
joshualitt1de610a2016-01-06 08:26:09 -0800185 ASSERT_SINGLE_OWNER
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000186 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000187}
188
189void GrContext::freeGpuResources() {
joshualitt1de610a2016-01-06 08:26:09 -0800190 ASSERT_SINGLE_OWNER
191
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000192 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000193
Brian Salomonf856fd12016-12-16 14:24:34 -0500194 fAtlasGlyphCache->freeAll();
robertphillips68737822015-10-29 12:12:21 -0700195
196 fDrawingManager->freeGpuResources();
bsalomon3033b9f2015-04-13 11:09:56 -0700197
198 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000199}
200
Brian Salomon5e150852017-03-22 14:53:13 -0400201void GrContext::purgeResourcesNotUsedInMs(std::chrono::milliseconds ms) {
202 ASSERT_SINGLE_OWNER
203 fResourceCache->purgeResourcesNotUsedSince(GrStdSteadyClock::now() - ms);
204}
205
Derek Sollenberger5480a182017-05-25 16:43:59 -0400206void GrContext::purgeUnlockedResources(size_t bytesToPurge, bool preferScratchResources) {
207 ASSERT_SINGLE_OWNER
208 fResourceCache->purgeUnlockedResources(bytesToPurge, preferScratchResources);
209}
210
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000211void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800212 ASSERT_SINGLE_OWNER
213
bsalomon71cb0c22014-11-14 12:10:14 -0800214 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800215 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800216 }
217 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800218 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800219 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000220}
221
Derek Sollenbergeree479142017-05-24 11:41:33 -0400222size_t GrContext::getResourceCachePurgeableBytes() const {
223 ASSERT_SINGLE_OWNER
224 return fResourceCache->getPurgeableBytes();
225}
226
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000227////////////////////////////////////////////////////////////////////////////////
228
joshualitt0db6dfa2015-04-10 07:01:30 -0700229void GrContext::TextBlobCacheOverBudgetCB(void* data) {
230 SkASSERT(data);
Brian Osman11052242016-10-27 14:47:55 -0400231 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
232 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls
233 // to below the GrContext level, but this is not trivial because they call drawPath on
234 // SkGpuDevice.
joshualitt0db6dfa2015-04-10 07:01:30 -0700235 GrContext* context = reinterpret_cast<GrContext*>(data);
236 context->flush();
237}
238
bsalomon@google.com27847de2011-02-22 20:59:41 +0000239////////////////////////////////////////////////////////////////////////////////
240
bsalomonb77a9072016-09-07 10:02:04 -0700241void GrContext::flush() {
joshualitt1de610a2016-01-06 08:26:09 -0800242 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700243 RETURN_IF_ABANDONED
Robert Phillips7ee385e2017-03-30 08:02:11 -0400244
245 fDrawingManager->flush(nullptr);
246}
247
248void GrContextPriv::flush(GrSurfaceProxy* proxy) {
249 ASSERT_SINGLE_OWNER_PRIV
250 RETURN_IF_ABANDONED_PRIV
251 ASSERT_OWNED_PROXY_PRIV(proxy);
252
253 fContext->fDrawingManager->flush(proxy);
bsalomon@google.com27847de2011-02-22 20:59:41 +0000254}
255
bsalomon81beccc2014-10-13 12:32:55 -0700256bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
257 const void* inPixels, size_t outRowBytes, void* outPixels) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500258 SkColorType colorType;
259 if (!GrPixelConfigToColorType(srcConfig, &colorType) ||
260 4 != SkColorTypeBytesPerPixel(colorType))
261 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000262 return false;
263 }
bsalomon81beccc2014-10-13 12:32:55 -0700264
Matt Sarettc7b29082017-02-09 16:22:39 -0500265 for (int y = 0; y < height; y++) {
266 SkOpts::RGBA_to_rgbA((uint32_t*) outPixels, inPixels, width);
267 outPixels = SkTAddOffset<void>(outPixels, outRowBytes);
268 inPixels = SkTAddOffset<const void>(inPixels, inRowBytes);
269 }
bsalomon81beccc2014-10-13 12:32:55 -0700270
Matt Sarettc7b29082017-02-09 16:22:39 -0500271 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000272}
273
Brian Osmand2ca59a2017-04-13 14:03:57 -0400274static bool valid_premul_config(GrPixelConfig config) {
Brian Osmance425512017-03-22 14:37:50 -0400275 return GrPixelConfigIs8888Unorm(config) || kRGBA_half_GrPixelConfig == config;
276}
277
Brian Osmand2ca59a2017-04-13 14:03:57 -0400278static bool valid_pixel_conversion(GrPixelConfig srcConfig, GrPixelConfig dstConfig,
279 bool premulConversion) {
280 // We don't allow conversion between integer configs and float/fixed configs.
281 if (GrPixelConfigIsSint(srcConfig) != GrPixelConfigIsSint(dstConfig)) {
282 return false;
283 }
284
285 // We only allow premul <-> unpremul conversions for some formats
286 if (premulConversion && (!valid_premul_config(srcConfig) || !valid_premul_config(dstConfig))) {
287 return false;
288 }
289
290 return true;
291}
292
Brian Osman409e74f2017-04-17 11:48:28 -0400293static bool pm_upm_must_round_trip(GrPixelConfig config, SkColorSpace* colorSpace) {
294 return !colorSpace &&
295 (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config);
296}
297
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400298bool GrContextPriv::writeSurfacePixels(GrSurfaceContext* dst,
Robert Phillipse78b7252017-04-06 07:59:41 -0400299 int left, int top, int width, int height,
300 GrPixelConfig srcConfig, SkColorSpace* srcColorSpace,
301 const void* buffer, size_t rowBytes,
302 uint32_t pixelOpsFlags) {
Brian Osmanb62ea222016-12-22 11:12:16 -0500303 // TODO: Color space conversion
304
Robert Phillipse78b7252017-04-06 07:59:41 -0400305 ASSERT_SINGLE_OWNER_PRIV
306 RETURN_FALSE_IF_ABANDONED_PRIV
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400307 SkASSERT(dst);
308 ASSERT_OWNED_PROXY_PRIV(dst->asSurfaceProxy());
Robert Phillipse78b7252017-04-06 07:59:41 -0400309 GR_AUDIT_TRAIL_AUTO_FRAME(&fContext->fAuditTrail, "GrContextPriv::writeSurfacePixels");
bsalomon6c6f6582015-09-10 08:12:46 -0700310
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400311 if (!dst->asSurfaceProxy()->instantiate(fContext->resourceProvider())) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400312 return false;
313 }
314
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400315 GrSurface* dstSurface = dst->asSurfaceProxy()->priv().peekSurface();
316
Brian Osmand2ca59a2017-04-13 14:03:57 -0400317 // The src is unpremul but the dst is premul -> premul the src before or as part of the write
Brian Osman409e74f2017-04-17 11:48:28 -0400318 const bool premul = SkToBool(kUnpremul_PixelOpsFlag & pixelOpsFlags);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400319 if (!valid_pixel_conversion(srcConfig, dstSurface->config(), premul)) {
Brian Osmand2ca59a2017-04-13 14:03:57 -0400320 return false;
321 }
322
Brian Osman409e74f2017-04-17 11:48:28 -0400323 // We need to guarantee round-trip conversion if we are reading and writing 8888 non-sRGB data,
324 // without any color spaces attached, and the caller wants us to premul.
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400325 bool useConfigConversionEffect =
326 premul &&
327 pm_upm_must_round_trip(srcConfig, srcColorSpace) &&
328 pm_upm_must_round_trip(dstSurface->config(), dst->getColorSpace());
Brian Osman409e74f2017-04-17 11:48:28 -0400329
330 // Are we going to try to premul as part of a draw? For the non-legacy case, we always allow
331 // this. GrConfigConversionEffect fails on some GPUs, so only allow this if it works perfectly.
332 bool premulOnGpu = premul &&
333 (!useConfigConversionEffect || fContext->validPMUPMConversionExists());
bsalomon81beccc2014-10-13 12:32:55 -0700334
bsalomone8d21e82015-07-16 08:23:13 -0700335 // 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 -0700336 // necessary and because GrGpu::getWritePixelsInfo requires it.
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400337 if (!GrSurfacePriv::AdjustWritePixelParams(dstSurface->width(), dstSurface->height(),
bsalomone8d21e82015-07-16 08:23:13 -0700338 GrBytesPerPixel(srcConfig), &left, &top, &width,
339 &height, &buffer, &rowBytes)) {
340 return false;
341 }
342
Brian Osman409e74f2017-04-17 11:48:28 -0400343 GrGpu::DrawPreference drawPreference = premulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference
344 : GrGpu::kNoDraw_DrawPreference;
bsalomonf0674512015-07-28 13:26:15 -0700345 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400346 if (!fContext->fGpu->getWritePixelsInfo(dstSurface, width, height, srcConfig,
Robert Phillipse78b7252017-04-06 07:59:41 -0400347 &drawPreference, &tempDrawInfo)) {
bsalomonf0674512015-07-28 13:26:15 -0700348 return false;
349 }
350
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400351 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && dstSurface->surfacePriv().hasPendingIO()) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400352 this->flush(nullptr); // MDB TODO: tighten this
bsalomonf0674512015-07-28 13:26:15 -0700353 }
354
Robert Phillips2f493142017-03-02 18:18:38 -0500355 sk_sp<GrTextureProxy> tempProxy;
bsalomonf0674512015-07-28 13:26:15 -0700356 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400357 tempProxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(),
Robert Phillips2f493142017-03-02 18:18:38 -0500358 tempDrawInfo.fTempSurfaceDesc,
359 SkBackingFit::kApprox,
360 SkBudgeted::kYes);
361 if (!tempProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
bsalomonf0674512015-07-28 13:26:15 -0700362 return false;
363 }
364 }
365
366 // temp buffer for doing sw premul conversion, if needed.
367 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
Brian Osman409e74f2017-04-17 11:48:28 -0400368 // We need to do sw premul if we were unable to create a RT for drawing, or if we can't do the
369 // premul on the GPU
370 if (premul && (!tempProxy || !premulOnGpu)) {
371 size_t tmpRowBytes = 4 * width;
372 tmpPixels.reset(width * height);
373 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
374 tmpPixels.get())) {
375 return false;
bsalomonf0674512015-07-28 13:26:15 -0700376 }
Brian Osman409e74f2017-04-17 11:48:28 -0400377 rowBytes = tmpRowBytes;
378 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700379 }
Brian Osman409e74f2017-04-17 11:48:28 -0400380
381 if (tempProxy) {
382 sk_sp<GrFragmentProcessor> fp = GrSimpleTextureEffect::Make(
383 fContext->resourceProvider(), tempProxy, nullptr, SkMatrix::I());
384 if (premulOnGpu) {
385 fp = fContext->createUPMToPMEffect(std::move(fp), useConfigConversionEffect);
bsalomon81beccc2014-10-13 12:32:55 -0700386 }
Brian Osman409e74f2017-04-17 11:48:28 -0400387 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
388 SkASSERT(fp);
389
390 if (tempProxy->priv().hasPendingIO()) {
391 this->flush(tempProxy.get());
392 }
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400393 if (!tempProxy->instantiate(fContext->resourceProvider())) {
Brian Osman409e74f2017-04-17 11:48:28 -0400394 return false;
395 }
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400396 GrTexture* texture = tempProxy->priv().peekTexture();
Brian Osman409e74f2017-04-17 11:48:28 -0400397 if (!fContext->fGpu->writePixels(texture, 0, 0, width, height, tempDrawInfo.fWriteConfig,
398 buffer, rowBytes)) {
399 return false;
400 }
401 SkMatrix matrix;
402 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400403 GrRenderTargetContext* renderTargetContext = dst->asRenderTargetContext();
Brian Osman409e74f2017-04-17 11:48:28 -0400404 if (!renderTargetContext) {
405 return false;
406 }
407 GrPaint paint;
408 paint.addColorFragmentProcessor(std::move(fp));
409 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
Brian Osman7ab6a7f2017-04-25 15:01:46 -0400410 paint.setAllowSRGBInputs(SkToBool(dst->getColorSpace()) ||
411 GrPixelConfigIsSRGB(renderTargetContext->config()));
Brian Osman409e74f2017-04-17 11:48:28 -0400412 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
413 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect,
414 nullptr);
415
416 if (kFlushWrites_PixelOp & pixelOpsFlags) {
417 this->flushSurfaceWrites(renderTargetContext->asRenderTargetProxy());
418 }
419 } else {
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400420 return fContext->fGpu->writePixels(dstSurface, left, top, width, height, srcConfig,
Robert Phillipse78b7252017-04-06 07:59:41 -0400421 buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700422 }
bsalomon81beccc2014-10-13 12:32:55 -0700423 return true;
424}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000425
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400426bool GrContextPriv::readSurfacePixels(GrSurfaceContext* src,
Robert Phillipse78b7252017-04-06 07:59:41 -0400427 int left, int top, int width, int height,
428 GrPixelConfig dstConfig, SkColorSpace* dstColorSpace,
429 void* buffer, size_t rowBytes, uint32_t flags) {
Brian Osmanb62ea222016-12-22 11:12:16 -0500430 // TODO: Color space conversion
431
Robert Phillipse78b7252017-04-06 07:59:41 -0400432 ASSERT_SINGLE_OWNER_PRIV
433 RETURN_FALSE_IF_ABANDONED_PRIV
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400434 SkASSERT(src);
435 ASSERT_OWNED_PROXY_PRIV(src->asSurfaceProxy());
Robert Phillipse78b7252017-04-06 07:59:41 -0400436 GR_AUDIT_TRAIL_AUTO_FRAME(&fContext->fAuditTrail, "GrContextPriv::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700437
Robert Phillipse78b7252017-04-06 07:59:41 -0400438 // MDB TODO: delay this instantiation until later in the method
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400439 if (!src->asSurfaceProxy()->instantiate(fContext->resourceProvider())) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400440 return false;
441 }
442
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400443 GrSurface* srcSurface = src->asSurfaceProxy()->priv().peekSurface();
444
Brian Osmand2ca59a2017-04-13 14:03:57 -0400445 // The src is premul but the dst is unpremul -> unpremul the src after or as part of the read
446 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400447 if (!valid_pixel_conversion(srcSurface->config(), dstConfig, unpremul)) {
Brian Osmand2ca59a2017-04-13 14:03:57 -0400448 return false;
449 }
450
Brian Osman409e74f2017-04-17 11:48:28 -0400451 // We need to guarantee round-trip conversion if we are reading and writing 8888 non-sRGB data,
452 // without any color spaces attached, and the caller wants us to unpremul.
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400453 bool useConfigConversionEffect =
454 unpremul &&
455 pm_upm_must_round_trip(srcSurface->config(), src->getColorSpace()) &&
456 pm_upm_must_round_trip(dstConfig, dstColorSpace);
Brian Osman409e74f2017-04-17 11:48:28 -0400457
458 // Are we going to try to unpremul as part of a draw? For the non-legacy case, we always allow
459 // this. GrConfigConversionEffect fails on some GPUs, so only allow this if it works perfectly.
460 bool unpremulOnGpu = unpremul &&
461 (!useConfigConversionEffect || fContext->validPMUPMConversionExists());
bsalomon6c6f6582015-09-10 08:12:46 -0700462
bsalomone8d21e82015-07-16 08:23:13 -0700463 // Adjust the params so that if we wind up using an intermediate surface we've already done
464 // all the trimming and the temporary can be the min size required.
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400465 if (!GrSurfacePriv::AdjustReadPixelParams(srcSurface->width(), srcSurface->height(),
bsalomone8d21e82015-07-16 08:23:13 -0700466 GrBytesPerPixel(dstConfig), &left,
467 &top, &width, &height, &buffer, &rowBytes)) {
468 return false;
469 }
470
Brian Osman409e74f2017-04-17 11:48:28 -0400471 GrGpu::DrawPreference drawPreference = unpremulOnGpu ? GrGpu::kCallerPrefersDraw_DrawPreference
472 : GrGpu::kNoDraw_DrawPreference;
bsalomon39826022015-07-23 08:07:21 -0700473 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400474 if (!fContext->fGpu->getReadPixelsInfo(srcSurface, width, height, rowBytes, dstConfig,
Robert Phillipse78b7252017-04-06 07:59:41 -0400475 &drawPreference, &tempDrawInfo)) {
bsalomon39826022015-07-23 08:07:21 -0700476 return false;
477 }
bsalomon191bcc02014-11-14 11:31:13 -0800478
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400479 if (!(kDontFlush_PixelOpsFlag & flags) && srcSurface->surfacePriv().hasPendingWrite()) {
Brian Osmand2ca59a2017-04-13 14:03:57 -0400480 this->flush(nullptr); // MDB TODO: tighten this
481 }
482
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400483 sk_sp<GrSurfaceProxy> proxyToRead = src->asSurfaceProxyRef();
bsalomon39826022015-07-23 08:07:21 -0700484 bool didTempDraw = false;
485 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomonb117ff12016-07-19 07:24:40 -0700486 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) {
bsalomon39826022015-07-23 08:07:21 -0700487 // We only respect this when the entire src is being read. Otherwise we can trigger too
488 // many odd ball texture sizes and trash the cache.
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400489 if (width != srcSurface->width() || height != srcSurface->height()) {
bsalomonb117ff12016-07-19 07:24:40 -0700490 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox;
bsalomon39826022015-07-23 08:07:21 -0700491 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000492 }
brianosmandfe4f2e2016-07-21 13:28:36 -0700493 // TODO: Need to decide the semantics of this function for color spaces. Do we support
494 // conversion to a passed-in color space? For now, specifying nullptr means that this
495 // path will do no conversion, so it will match the behavior of the non-draw path.
Robert Phillipsdd3b3f42017-04-24 10:57:28 -0400496 sk_sp<GrRenderTargetContext> tempRTC = fContext->makeDeferredRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400497 tempDrawInfo.fTempSurfaceFit,
bsalomonb117ff12016-07-19 07:24:40 -0700498 tempDrawInfo.fTempSurfaceDesc.fWidth,
499 tempDrawInfo.fTempSurfaceDesc.fHeight,
500 tempDrawInfo.fTempSurfaceDesc.fConfig,
brianosmandfe4f2e2016-07-21 13:28:36 -0700501 nullptr,
bsalomonb117ff12016-07-19 07:24:40 -0700502 tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
503 tempDrawInfo.fTempSurfaceDesc.fOrigin);
Brian Osman693a5402016-10-27 15:13:22 -0400504 if (tempRTC) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500505 SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top));
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400506 sk_sp<GrTextureProxy> proxy = src->asTextureProxyRef();
Brian Osman409e74f2017-04-17 11:48:28 -0400507 sk_sp<GrFragmentProcessor> fp = GrSimpleTextureEffect::Make(
Robert Phillipsf41c22f2017-04-18 07:48:58 -0400508 fContext->resourceProvider(), std::move(proxy), nullptr, textureMatrix);
Brian Osman409e74f2017-04-17 11:48:28 -0400509 if (unpremulOnGpu) {
510 fp = fContext->createPMToUPMEffect(std::move(fp), useConfigConversionEffect);
511 // We no longer need to do this on CPU after the read back.
512 unpremul = false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000513 }
Brian Osman409e74f2017-04-17 11:48:28 -0400514 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
515 SkASSERT(fp);
Brian Osman60cd57e2017-04-06 10:19:06 -0400516
Brian Osman409e74f2017-04-17 11:48:28 -0400517 GrPaint paint;
518 paint.addColorFragmentProcessor(std::move(fp));
519 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
520 paint.setAllowSRGBInputs(true);
521 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
522 tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect,
523 nullptr);
524 proxyToRead = tempRTC->asTextureProxyRef();
525 left = 0;
526 top = 0;
527 didTempDraw = true;
bsalomon@google.com0342a852012-08-20 19:22:38 +0000528 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000529 }
joshualitt5c55fef2014-10-31 14:04:35 -0700530
Robert Phillipse78b7252017-04-06 07:59:41 -0400531 if (!proxyToRead) {
532 return false;
533 }
534
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400535 if (!proxyToRead->instantiate(fContext->resourceProvider())) {
Robert Phillips833dcf42016-11-18 08:44:13 -0500536 return false;
537 }
538
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400539 GrSurface* surfaceToRead = proxyToRead->priv().peekSurface();
540
bsalomon39826022015-07-23 08:07:21 -0700541 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000542 return false;
543 }
bsalomon39826022015-07-23 08:07:21 -0700544 GrPixelConfig configToRead = dstConfig;
545 if (didTempDraw) {
Robert Phillipse78b7252017-04-06 07:59:41 -0400546 this->flushSurfaceWrites(proxyToRead.get());
bsalomon6c9cd552016-01-22 07:17:34 -0800547 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700548 }
Robert Phillipse78b7252017-04-06 07:59:41 -0400549 if (!fContext->fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead,
550 buffer, rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700551 return false;
552 }
553
554 // Perform umpremul conversion if we weren't able to perform it as a draw.
555 if (unpremul) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500556 SkColorType colorType;
557 if (!GrPixelConfigToColorType(dstConfig, &colorType) ||
558 4 != SkColorTypeBytesPerPixel(colorType))
559 {
reed@google.com7111d462014-03-25 16:20:24 +0000560 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000561 }
reed@google.com7111d462014-03-25 16:20:24 +0000562
Matt Sarettc7b29082017-02-09 16:22:39 -0500563 for (int y = 0; y < height; y++) {
564 SkUnpremultiplyRow<false>((uint32_t*) buffer, (const uint32_t*) buffer, width);
565 buffer = SkTAddOffset<void>(buffer, rowBytes);
566 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000567 }
568 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000569}
570
Robert Phillips7ee385e2017-03-30 08:02:11 -0400571void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
572 ASSERT_SINGLE_OWNER_PRIV
573 RETURN_IF_ABANDONED_PRIV
574 SkASSERT(proxy);
575 ASSERT_OWNED_PROXY_PRIV(proxy);
576 fContext->fDrawingManager->prepareSurfaceForExternalIO(proxy);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000577}
578
Robert Phillips7ee385e2017-03-30 08:02:11 -0400579void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) {
580 ASSERT_SINGLE_OWNER_PRIV
581 RETURN_IF_ABANDONED_PRIV
582 SkASSERT(proxy);
583 ASSERT_OWNED_PROXY_PRIV(proxy);
584 if (proxy->priv().hasPendingWrite()) {
585 this->flush(proxy);
bsalomonf80bfed2014-10-07 05:56:02 -0700586 }
587}
588
Robert Phillips7ee385e2017-03-30 08:02:11 -0400589void GrContextPriv::flushSurfaceIO(GrSurfaceProxy* proxy) {
590 ASSERT_SINGLE_OWNER_PRIV
591 RETURN_IF_ABANDONED_PRIV
592 SkASSERT(proxy);
593 ASSERT_OWNED_PROXY_PRIV(proxy);
594 if (proxy->priv().hasPendingIO()) {
595 this->flush(proxy);
ajuma95243eb2016-08-24 08:19:02 -0700596 }
597}
598
bsalomon@google.com27847de2011-02-22 20:59:41 +0000599////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000600int GrContext::getRecommendedSampleCount(GrPixelConfig config,
601 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800602 ASSERT_SINGLE_OWNER
603
bsalomon76228632015-05-29 08:02:10 -0700604 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000605 return 0;
606 }
607 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700608 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000609 if (dpi >= 250.0f) {
610 chosenSampleCount = 4;
611 } else {
612 chosenSampleCount = 16;
613 }
614 }
egdanieleed519e2016-01-15 11:36:18 -0800615 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000616}
617
Robert Phillips2c862492017-01-18 10:08:39 -0500618sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
619 sk_sp<SkColorSpace> colorSpace) {
Brian Osman45580d32016-11-23 09:37:01 -0500620 ASSERT_SINGLE_OWNER_PRIV
621
Brian Osman45580d32016-11-23 09:37:01 -0500622 if (proxy->asRenderTargetProxy()) {
Robert Phillips2c862492017-01-18 10:08:39 -0500623 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
624 std::move(colorSpace), nullptr);
Brian Osman45580d32016-11-23 09:37:01 -0500625 } else {
626 SkASSERT(proxy->asTextureProxy());
Robert Phillips2c862492017-01-18 10:08:39 -0500627 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
Brian Osman45580d32016-11-23 09:37:01 -0500628 }
629}
630
Robert Phillipse2f7d182016-12-15 09:23:05 -0500631sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
632 SkBackingFit fit,
633 SkBudgeted isDstBudgeted) {
634
Brian Osman32342f02017-03-04 08:12:46 -0500635 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400636 dstDesc, fit, isDstBudgeted);
Robert Phillips77b3f322017-01-31 18:24:12 -0500637 if (!proxy) {
638 return nullptr;
639 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500640
Robert Phillips2c862492017-01-18 10:08:39 -0500641 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500642}
643
Greg Daniel7ef28f32017-04-20 16:41:55 +0000644sk_sp<GrSurfaceContext> GrContextPriv::makeBackendSurfaceContext(const GrBackendTexture& tex,
645 GrSurfaceOrigin origin,
646 GrBackendTextureFlags flags,
647 int sampleCnt,
Brian Osmanc1e37052017-03-09 14:19:20 -0500648 sk_sp<SkColorSpace> colorSpace) {
Robert Phillips26caf892017-01-27 10:58:31 -0500649 ASSERT_SINGLE_OWNER_PRIV
650
Greg Daniel7ef28f32017-04-20 16:41:55 +0000651 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(tex, origin,
652 flags, sampleCnt));
Robert Phillips26caf892017-01-27 10:58:31 -0500653 if (!surface) {
654 return nullptr;
655 }
656
657 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500658 if (!proxy) {
659 return nullptr;
660 }
Robert Phillips26caf892017-01-27 10:58:31 -0500661
662 return this->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace));
663}
664
Brian Osman11052242016-10-27 14:47:55 -0400665sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
Greg Daniel7ef28f32017-04-20 16:41:55 +0000666 const GrBackendTexture& tex,
667 GrSurfaceOrigin origin,
668 int sampleCnt,
Brian Osman11052242016-10-27 14:47:55 -0400669 sk_sp<SkColorSpace> colorSpace,
Brian Osmanc1e37052017-03-09 14:19:20 -0500670 const SkSurfaceProps* props) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700671 ASSERT_SINGLE_OWNER_PRIV
robertphillips4fd74ae2016-08-03 14:26:53 -0700672
Greg Daniel7ef28f32017-04-20 16:41:55 +0000673 static const GrBackendTextureFlags kForceRT = kRenderTarget_GrBackendTextureFlag;
674 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(tex, origin, kForceRT,
675 sampleCnt));
robertphillips4fd74ae2016-08-03 14:26:53 -0700676 if (!surface) {
677 return nullptr;
678 }
679
Robert Phillips37430132016-11-09 06:50:43 -0500680 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500681 if (!proxy) {
682 return nullptr;
683 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400684
Robert Phillips37430132016-11-09 06:50:43 -0500685 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Brian Osman11052242016-10-27 14:47:55 -0400686 std::move(colorSpace), props);
robertphillips4fd74ae2016-08-03 14:26:53 -0700687}
688
Brian Osman11052242016-10-27 14:47:55 -0400689sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
Greg Danielbcf612b2017-05-01 13:50:58 +0000690 const GrBackendRenderTarget& backendRT,
691 GrSurfaceOrigin origin,
robertphillips4fd74ae2016-08-03 14:26:53 -0700692 sk_sp<SkColorSpace> colorSpace,
693 const SkSurfaceProps* surfaceProps) {
694 ASSERT_SINGLE_OWNER_PRIV
695
Greg Danielbcf612b2017-05-01 13:50:58 +0000696 sk_sp<GrRenderTarget> rt(fContext->resourceProvider()->wrapBackendRenderTarget(backendRT,
697 origin));
robertphillips4fd74ae2016-08-03 14:26:53 -0700698 if (!rt) {
699 return nullptr;
700 }
701
Robert Phillips37430132016-11-09 06:50:43 -0500702 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500703 if (!proxy) {
704 return nullptr;
705 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400706
Robert Phillips37430132016-11-09 06:50:43 -0500707 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400708 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400709 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700710}
711
Brian Osman11052242016-10-27 14:47:55 -0400712sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
Greg Daniel7ef28f32017-04-20 16:41:55 +0000713 const GrBackendTexture& tex,
714 GrSurfaceOrigin origin,
715 int sampleCnt,
robertphillips4fd74ae2016-08-03 14:26:53 -0700716 sk_sp<SkColorSpace> colorSpace,
717 const SkSurfaceProps* surfaceProps) {
718 ASSERT_SINGLE_OWNER_PRIV
robertphillips4fd74ae2016-08-03 14:26:53 -0700719
Greg Daniel7ef28f32017-04-20 16:41:55 +0000720 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(
721 tex,
722 origin,
723 sampleCnt));
robertphillips4fd74ae2016-08-03 14:26:53 -0700724 if (!surface) {
725 return nullptr;
726 }
727
Robert Phillips37430132016-11-09 06:50:43 -0500728 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500729 if (!proxy) {
730 return nullptr;
731 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400732
Robert Phillips37430132016-11-09 06:50:43 -0500733 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400734 std::move(colorSpace),
735 surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700736}
737
Chris Daltonfe199b72017-05-05 11:26:15 -0400738void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
739 fContext->fDrawingManager->addOnFlushCallbackObject(onFlushCBObject);
Robert Phillipseb35f4d2017-03-21 07:56:47 -0400740}
741
742
robertphillips48fde9c2016-09-06 05:20:20 -0700743static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
Brian Osman78f20e02017-01-12 10:28:01 -0500744 switch (config) {
745 case kAlpha_8_GrPixelConfig:
746 case kRGB_565_GrPixelConfig:
747 case kRGBA_4444_GrPixelConfig:
748 case kBGRA_8888_GrPixelConfig:
749 return kRGBA_8888_GrPixelConfig;
750 case kSBGRA_8888_GrPixelConfig:
751 return kSRGBA_8888_GrPixelConfig;
752 case kAlpha_half_GrPixelConfig:
753 return kRGBA_half_GrPixelConfig;
754 default:
755 return kUnknown_GrPixelConfig;
756 }
robertphillips48fde9c2016-09-06 05:20:20 -0700757}
758
robertphillipsd728f0c2016-11-21 11:05:03 -0800759sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallback(
760 SkBackingFit fit,
761 int width, int height,
762 GrPixelConfig config,
763 sk_sp<SkColorSpace> colorSpace,
764 int sampleCnt,
765 GrSurfaceOrigin origin,
766 const SkSurfaceProps* surfaceProps,
767 SkBudgeted budgeted) {
768 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
769 config = GrPixelConfigFallback(config);
770 }
771
772 return this->makeDeferredRenderTargetContext(fit, width, height, config, std::move(colorSpace),
773 sampleCnt, origin, surfaceProps, budgeted);
774}
775
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400776sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext(
777 SkBackingFit fit,
778 int width, int height,
779 GrPixelConfig config,
780 sk_sp<SkColorSpace> colorSpace,
781 int sampleCnt,
782 GrSurfaceOrigin origin,
783 const SkSurfaceProps* surfaceProps,
784 SkBudgeted budgeted) {
Robert Phillipsdd3b3f42017-04-24 10:57:28 -0400785 SkASSERT(kDefault_GrSurfaceOrigin != origin);
786
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400787 GrSurfaceDesc desc;
788 desc.fFlags = kRenderTarget_GrSurfaceFlag;
789 desc.fOrigin = origin;
790 desc.fWidth = width;
791 desc.fHeight = height;
792 desc.fConfig = config;
793 desc.fSampleCnt = sampleCnt;
794
Brian Osman32342f02017-03-04 08:12:46 -0500795 sk_sp<GrTextureProxy> rtp = GrSurfaceProxy::MakeDeferred(this->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400796 desc, fit, budgeted);
Robert Phillips08c5ec72017-01-30 12:26:47 -0500797 if (!rtp) {
798 return nullptr;
799 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400800
Robert Phillips1119dc32017-04-11 12:54:57 -0400801 sk_sp<GrRenderTargetContext> renderTargetContext(
802 fDrawingManager->makeRenderTargetContext(std::move(rtp),
803 std::move(colorSpace),
804 surfaceProps));
Robert Phillips1119dc32017-04-11 12:54:57 -0400805 if (!renderTargetContext) {
806 return nullptr;
807 }
808
809 renderTargetContext->discard();
810
811 return renderTargetContext;
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400812}
813
joshualitt1de610a2016-01-06 08:26:09 -0800814bool GrContext::abandoned() const {
815 ASSERT_SINGLE_OWNER
robertphillips7761d612016-05-16 09:14:53 -0700816 return fDrawingManager->wasAbandoned();
robertphillips77a2e522015-10-17 07:43:27 -0700817}
818
Brian Osman60cd57e2017-04-06 10:19:06 -0400819sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrFragmentProcessor> fp,
Brian Osman409e74f2017-04-17 11:48:28 -0400820 bool useConfigConversionEffect) {
Robert Phillips757914d2017-01-25 15:48:30 -0500821 ASSERT_SINGLE_OWNER
Brian Osman409e74f2017-04-17 11:48:28 -0400822 // We have specialized effects that guarantee round-trip conversion for some formats
823 if (useConfigConversionEffect) {
824 // We should have already called this->validPMUPMConversionExists() in this case
825 SkASSERT(fDidTestPMConversions);
826 // ...and it should have succeeded
827 SkASSERT(this->validPMUPMConversionExists());
828
Brian Osman28804f32017-04-20 10:24:36 -0400829 return GrConfigConversionEffect::Make(std::move(fp),
830 GrConfigConversionEffect::kToUnpremul_PMConversion);
Brian Osman2d2da4f2017-04-12 17:07:22 -0400831 } else {
832 // For everything else (sRGB, half-float, etc...), it doesn't make sense to try and
833 // explicitly round the results. Just do the obvious, naive thing in the shader.
834 return GrFragmentProcessor::UnpremulOutput(std::move(fp));
Robert Phillips757914d2017-01-25 15:48:30 -0500835 }
836}
837
Brian Osman60cd57e2017-04-06 10:19:06 -0400838sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrFragmentProcessor> fp,
Brian Osman409e74f2017-04-17 11:48:28 -0400839 bool useConfigConversionEffect) {
joshualitt1de610a2016-01-06 08:26:09 -0800840 ASSERT_SINGLE_OWNER
Brian Osman2d2da4f2017-04-12 17:07:22 -0400841 // We have specialized effects that guarantee round-trip conversion for these formats
Brian Osman409e74f2017-04-17 11:48:28 -0400842 if (useConfigConversionEffect) {
843 // We should have already called this->validPMUPMConversionExists() in this case
844 SkASSERT(fDidTestPMConversions);
845 // ...and it should have succeeded
846 SkASSERT(this->validPMUPMConversionExists());
847
Brian Osman28804f32017-04-20 10:24:36 -0400848 return GrConfigConversionEffect::Make(std::move(fp),
849 GrConfigConversionEffect::kToPremul_PMConversion);
Brian Osman2d2da4f2017-04-12 17:07:22 -0400850 } else {
851 // For everything else (sRGB, half-float, etc...), it doesn't make sense to try and
852 // explicitly round the results. Just do the obvious, naive thing in the shader.
853 return GrFragmentProcessor::PremulOutput(std::move(fp));
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000854 }
855}
856
Brian Osman409e74f2017-04-17 11:48:28 -0400857bool GrContext::validPMUPMConversionExists() {
joshualitt1de610a2016-01-06 08:26:09 -0800858 ASSERT_SINGLE_OWNER
Brian Osman409e74f2017-04-17 11:48:28 -0400859 if (!fDidTestPMConversions) {
Brian Osman28804f32017-04-20 10:24:36 -0400860 fPMUPMConversionsRoundTrip = GrConfigConversionEffect::TestForPreservingPMConversions(this);
Brian Osman409e74f2017-04-17 11:48:28 -0400861 fDidTestPMConversions = true;
862 }
863
bsalomon636e8022015-07-29 06:08:46 -0700864 // The PM<->UPM tests fail or succeed together so we only need to check one.
Brian Osman28804f32017-04-20 10:24:36 -0400865 return fPMUPMConversionsRoundTrip;
bsalomon636e8022015-07-29 06:08:46 -0700866}
867
bsalomon37f9a262015-02-02 13:00:10 -0800868//////////////////////////////////////////////////////////////////////////////
869
870void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800871 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800872 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800873 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800874 }
875 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800876 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800877 }
878}
879
880void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800881 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800882 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800883}
884
ericrk0a5fa482015-09-15 14:16:10 -0700885//////////////////////////////////////////////////////////////////////////////
886
887void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800888 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700889 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
890}