blob: df5c16df4a71e7fc87282b2f3b47512c9608165b [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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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 Phillipsaaee31f2017-04-05 12:18:58 -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) {
bungeman06ca8ec2016-06-09 08:01:03 -0700338 sk_sp<GrFragmentProcessor> fp;
bsalomonf0674512015-07-28 13:26:15 -0700339 if (applyPremulToSrc) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400340 fp = fContext->createUPMToPMEffect(tempProxy, SkMatrix::I());
Brian Osmance425512017-03-22 14:37:50 -0400341 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
bsalomonf0674512015-07-28 13:26:15 -0700342 // If premultiplying was the only reason for the draw, fall back to a straight write.
343 if (!fp) {
344 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
Robert Phillips2f493142017-03-02 18:18:38 -0500345 tempProxy.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700346 }
347 } else {
348 applyPremulToSrc = false;
349 }
350 }
Robert Phillips2f493142017-03-02 18:18:38 -0500351 if (tempProxy) {
bsalomonf0674512015-07-28 13:26:15 -0700352 if (!fp) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400353 fp = GrSimpleTextureEffect::Make(fContext->resourceProvider(), tempProxy, nullptr,
Brian Osmance425512017-03-22 14:37:50 -0400354 SkMatrix::I());
355 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
356
bsalomonf0674512015-07-28 13:26:15 -0700357 if (!fp) {
358 return false;
359 }
360 }
Robert Phillips7ee385e2017-03-30 08:02:11 -0400361 if (tempProxy->priv().hasPendingIO()) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400362 this->flush(tempProxy.get());
Robert Phillips7ee385e2017-03-30 08:02:11 -0400363 }
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400364 GrTexture* texture = tempProxy->instantiate(fContext->resourceProvider());
Robert Phillips757914d2017-01-25 15:48:30 -0500365 if (!texture) {
366 return false;
367 }
bsalomonf0674512015-07-28 13:26:15 -0700368 if (applyPremulToSrc) {
369 size_t tmpRowBytes = 4 * width;
370 tmpPixels.reset(width * height);
371 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
372 tmpPixels.get())) {
373 return false;
374 }
375 rowBytes = tmpRowBytes;
376 buffer = tmpPixels.get();
377 applyPremulToSrc = false;
378 }
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400379 if (!fContext->fGpu->writePixels(texture, 0, 0, width, height,
380 tempDrawInfo.fWriteConfig, buffer,
381 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700382 return false;
383 }
384 SkMatrix matrix;
385 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
brianosmandfe4f2e2016-07-21 13:28:36 -0700386 // TODO: Need to decide the semantics of this function for color spaces. Do we support
387 // conversion from a passed-in color space? For now, specifying nullptr means that this
388 // path will do no conversion, so it will match the behavior of the non-draw path.
Robert Phillips757914d2017-01-25 15:48:30 -0500389 GrRenderTarget* renderTarget = surface->asRenderTarget();
390 SkASSERT(renderTarget);
Brian Osman11052242016-10-27 14:47:55 -0400391 sk_sp<GrRenderTargetContext> renderTargetContext(
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400392 this->makeWrappedRenderTargetContext(sk_ref_sp(renderTarget), nullptr));
Brian Osman11052242016-10-27 14:47:55 -0400393 if (!renderTargetContext) {
bsalomonf0674512015-07-28 13:26:15 -0700394 return false;
395 }
egdanielc4b72722015-11-23 13:20:41 -0800396 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700397 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700398 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700399 paint.setAllowSRGBInputs(true);
bsalomonf0674512015-07-28 13:26:15 -0700400 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon82f44312017-01-11 13:42:54 -0500401 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect,
402 nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700403
404 if (kFlushWrites_PixelOp & pixelOpsFlags) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400405 this->flushSurfaceWrites(renderTargetContext->asRenderTargetProxy());
bsalomonf0674512015-07-28 13:26:15 -0700406 }
407 }
408 }
Robert Phillips2f493142017-03-02 18:18:38 -0500409 if (!tempProxy) {
bsalomonf0674512015-07-28 13:26:15 -0700410 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700411 size_t tmpRowBytes = 4 * width;
412 tmpPixels.reset(width * height);
413 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
414 tmpPixels.get())) {
415 return false;
416 }
417 rowBytes = tmpRowBytes;
418 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700419 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700420 }
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400421 return fContext->fGpu->writePixels(surface, left, top, width, height, srcConfig,
422 buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700423 }
bsalomon81beccc2014-10-13 12:32:55 -0700424 return true;
425}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000426
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400427bool GrContextPriv::readSurfacePixels(GrSurfaceProxy* srcProxy, SkColorSpace* srcColorSpace,
428 int left, int top, int width, int height,
429 GrPixelConfig dstConfig, SkColorSpace* dstColorSpace,
430 void* buffer, size_t rowBytes, uint32_t flags) {
Brian Osmanb62ea222016-12-22 11:12:16 -0500431 // TODO: Color space conversion
432
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400433 ASSERT_SINGLE_OWNER_PRIV
434 RETURN_FALSE_IF_ABANDONED_PRIV
435 ASSERT_OWNED_PROXY_PRIV(srcProxy);
436 SkASSERT(srcProxy);
437 GR_AUDIT_TRAIL_AUTO_FRAME(&fContext->fAuditTrail, "GrContextPriv::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700438
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400439 // MDB TODO: delay this instantiation until later in the method
440 GrSurface* src = srcProxy->instantiate(fContext->resourceProvider());
441 if (!src) {
442 return false;
443 }
444
445 fContext->testPMConversionsIfNecessary(flags);
bsalomon6c6f6582015-09-10 08:12:46 -0700446
bsalomone8d21e82015-07-16 08:23:13 -0700447 // Adjust the params so that if we wind up using an intermediate surface we've already done
448 // all the trimming and the temporary can be the min size required.
449 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
450 GrBytesPerPixel(dstConfig), &left,
451 &top, &width, &height, &buffer, &rowBytes)) {
452 return false;
453 }
454
455 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400456 this->flush(nullptr); // MDB TODO: tighten this
bsalomon@google.com6f379512011-11-16 20:36:03 +0000457 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000458
bsalomone8d21e82015-07-16 08:23:13 -0700459 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
Brian Osmance425512017-03-22 14:37:50 -0400460 if (unpremul && !valid_unpremul_config(dstConfig)) {
Brian Osmande1a6052017-03-22 10:57:00 -0400461 // The unpremul flag is only allowed for 8888 and F16 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000462 return false;
463 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500464 // We don't allow conversion between integer configs and float/fixed configs.
465 if (GrPixelConfigIsSint(src->config()) != GrPixelConfigIsSint(dstConfig)) {
466 return false;
467 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000468
bsalomon636e8022015-07-29 06:08:46 -0700469 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
470 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
471 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400472 if (unpremul && fContext->validPMUPMConversionExists(src->config())) {
bsalomon636e8022015-07-29 06:08:46 -0700473 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
474 }
475
bsalomon39826022015-07-23 08:07:21 -0700476 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400477 if (!fContext->fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig,
478 &drawPreference, &tempDrawInfo)) {
bsalomon39826022015-07-23 08:07:21 -0700479 return false;
480 }
bsalomon191bcc02014-11-14 11:31:13 -0800481
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400482 sk_sp<GrSurfaceProxy> proxyToRead = sk_ref_sp(srcProxy);
bsalomon39826022015-07-23 08:07:21 -0700483 bool didTempDraw = false;
484 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomonb117ff12016-07-19 07:24:40 -0700485 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) {
bsalomon39826022015-07-23 08:07:21 -0700486 // We only respect this when the entire src is being read. Otherwise we can trigger too
487 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700488 if (width != src->width() || height != src->height()) {
bsalomonb117ff12016-07-19 07:24:40 -0700489 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox;
bsalomon39826022015-07-23 08:07:21 -0700490 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000491 }
brianosmandfe4f2e2016-07-21 13:28:36 -0700492 // TODO: Need to decide the semantics of this function for color spaces. Do we support
493 // conversion to a passed-in color space? For now, specifying nullptr means that this
494 // path will do no conversion, so it will match the behavior of the non-draw path.
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400495 sk_sp<GrRenderTargetContext> tempRTC = fContext->makeRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400496 tempDrawInfo.fTempSurfaceFit,
bsalomonb117ff12016-07-19 07:24:40 -0700497 tempDrawInfo.fTempSurfaceDesc.fWidth,
498 tempDrawInfo.fTempSurfaceDesc.fHeight,
499 tempDrawInfo.fTempSurfaceDesc.fConfig,
brianosmandfe4f2e2016-07-21 13:28:36 -0700500 nullptr,
bsalomonb117ff12016-07-19 07:24:40 -0700501 tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
502 tempDrawInfo.fTempSurfaceDesc.fOrigin);
Brian Osman693a5402016-10-27 15:13:22 -0400503 if (tempRTC) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500504 SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top));
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400505 sk_sp<GrTextureProxy> proxy = sk_ref_sp(srcProxy->asTextureProxy());
bungeman06ca8ec2016-06-09 08:01:03 -0700506 sk_sp<GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000507 if (unpremul) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400508 fp = fContext->createPMToUPMEffect(proxy, textureMatrix);
Brian Osmance425512017-03-22 14:37:50 -0400509 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
joshualittb0a8a372014-09-23 09:50:21 -0700510 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000511 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon39826022015-07-23 08:07:21 -0700512 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
513 // We only wanted to do the draw in order to perform the unpremul so don't
514 // bother.
Brian Osman693a5402016-10-27 15:13:22 -0400515 tempRTC.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000516 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000517 }
Brian Osman693a5402016-10-27 15:13:22 -0400518 if (!fp && tempRTC) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400519 fp = GrSimpleTextureEffect::Make(fContext->resourceProvider(), std::move(proxy),
Robert Phillips769e80d2017-03-29 13:06:57 -0400520 nullptr, textureMatrix);
Brian Osmance425512017-03-22 14:37:50 -0400521 fp = GrFragmentProcessor::SwizzleOutput(std::move(fp), tempDrawInfo.fSwizzle);
bsalomon39826022015-07-23 08:07:21 -0700522 }
523 if (fp) {
egdanielc4b72722015-11-23 13:20:41 -0800524 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700525 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700526 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700527 paint.setAllowSRGBInputs(true);
bsalomon39826022015-07-23 08:07:21 -0700528 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon82f44312017-01-11 13:42:54 -0500529 tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect,
530 nullptr);
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400531 proxyToRead = tempRTC->asTextureProxyRef();
bsalomon39826022015-07-23 08:07:21 -0700532 left = 0;
533 top = 0;
534 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000535 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000536 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000537 }
joshualitt5c55fef2014-10-31 14:04:35 -0700538
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400539 if (!proxyToRead) {
540 return false;
541 }
542
543 GrSurface* surfaceToRead = proxyToRead->instantiate(fContext->resourceProvider());
Robert Phillips833dcf42016-11-18 08:44:13 -0500544 if (!surfaceToRead) {
545 return false;
546 }
547
bsalomon39826022015-07-23 08:07:21 -0700548 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000549 return false;
550 }
bsalomon39826022015-07-23 08:07:21 -0700551 GrPixelConfig configToRead = dstConfig;
552 if (didTempDraw) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400553 this->flushSurfaceWrites(proxyToRead.get());
bsalomon6c9cd552016-01-22 07:17:34 -0800554 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700555 }
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400556 if (!fContext->fGpu->readPixels(surfaceToRead, left, top, width, height, configToRead,
557 buffer, rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700558 return false;
559 }
560
561 // Perform umpremul conversion if we weren't able to perform it as a draw.
562 if (unpremul) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500563 SkColorType colorType;
564 if (!GrPixelConfigToColorType(dstConfig, &colorType) ||
565 4 != SkColorTypeBytesPerPixel(colorType))
566 {
reed@google.com7111d462014-03-25 16:20:24 +0000567 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000568 }
reed@google.com7111d462014-03-25 16:20:24 +0000569
Matt Sarettc7b29082017-02-09 16:22:39 -0500570 for (int y = 0; y < height; y++) {
571 SkUnpremultiplyRow<false>((uint32_t*) buffer, (const uint32_t*) buffer, width);
572 buffer = SkTAddOffset<void>(buffer, rowBytes);
573 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000574 }
575 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000576}
577
Robert Phillips7ee385e2017-03-30 08:02:11 -0400578void GrContextPriv::prepareSurfaceForExternalIO(GrSurfaceProxy* proxy) {
579 ASSERT_SINGLE_OWNER_PRIV
580 RETURN_IF_ABANDONED_PRIV
581 SkASSERT(proxy);
582 ASSERT_OWNED_PROXY_PRIV(proxy);
583 fContext->fDrawingManager->prepareSurfaceForExternalIO(proxy);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000584}
585
Robert Phillips7ee385e2017-03-30 08:02:11 -0400586void GrContextPriv::flushSurfaceWrites(GrSurfaceProxy* proxy) {
587 ASSERT_SINGLE_OWNER_PRIV
588 RETURN_IF_ABANDONED_PRIV
589 SkASSERT(proxy);
590 ASSERT_OWNED_PROXY_PRIV(proxy);
591 if (proxy->priv().hasPendingWrite()) {
592 this->flush(proxy);
bsalomonf80bfed2014-10-07 05:56:02 -0700593 }
594}
595
Robert Phillips7ee385e2017-03-30 08:02:11 -0400596void GrContextPriv::flushSurfaceIO(GrSurfaceProxy* proxy) {
597 ASSERT_SINGLE_OWNER_PRIV
598 RETURN_IF_ABANDONED_PRIV
599 SkASSERT(proxy);
600 ASSERT_OWNED_PROXY_PRIV(proxy);
601 if (proxy->priv().hasPendingIO()) {
602 this->flush(proxy);
ajuma95243eb2016-08-24 08:19:02 -0700603 }
604}
605
bsalomon@google.com27847de2011-02-22 20:59:41 +0000606////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000607int GrContext::getRecommendedSampleCount(GrPixelConfig config,
608 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800609 ASSERT_SINGLE_OWNER
610
bsalomon76228632015-05-29 08:02:10 -0700611 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000612 return 0;
613 }
614 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700615 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000616 if (dpi >= 250.0f) {
617 chosenSampleCount = 4;
618 } else {
619 chosenSampleCount = 16;
620 }
621 }
egdanieleed519e2016-01-15 11:36:18 -0800622 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000623}
624
Brian Osman11052242016-10-27 14:47:55 -0400625sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext(
626 sk_sp<GrRenderTarget> rt,
627 sk_sp<SkColorSpace> colorSpace,
628 const SkSurfaceProps* surfaceProps) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700629 ASSERT_SINGLE_OWNER_PRIV
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400630
Robert Phillips37430132016-11-09 06:50:43 -0500631 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500632 if (!proxy) {
633 return nullptr;
634 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400635
Robert Phillips37430132016-11-09 06:50:43 -0500636 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400637 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400638 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700639}
robertphillips77a2e522015-10-17 07:43:27 -0700640
Robert Phillips2c862492017-01-18 10:08:39 -0500641sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
642 sk_sp<SkColorSpace> colorSpace) {
Brian Osman45580d32016-11-23 09:37:01 -0500643 ASSERT_SINGLE_OWNER_PRIV
644
Brian Osman45580d32016-11-23 09:37:01 -0500645 if (proxy->asRenderTargetProxy()) {
Robert Phillips2c862492017-01-18 10:08:39 -0500646 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
647 std::move(colorSpace), nullptr);
Brian Osman45580d32016-11-23 09:37:01 -0500648 } else {
649 SkASSERT(proxy->asTextureProxy());
Robert Phillips2c862492017-01-18 10:08:39 -0500650 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
Brian Osman45580d32016-11-23 09:37:01 -0500651 }
652}
653
Robert Phillips31c26082016-12-14 15:12:15 -0500654sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface> surface) {
655 ASSERT_SINGLE_OWNER_PRIV
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 Phillips31c26082016-12-14 15:12:15 -0500661
Robert Phillips2c862492017-01-18 10:08:39 -0500662 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr);
Robert Phillips31c26082016-12-14 15:12:15 -0500663}
664
Robert Phillipse2f7d182016-12-15 09:23:05 -0500665sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
666 SkBackingFit fit,
667 SkBudgeted isDstBudgeted) {
668
Brian Osman32342f02017-03-04 08:12:46 -0500669 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400670 dstDesc, fit, isDstBudgeted);
Robert Phillips77b3f322017-01-31 18:24:12 -0500671 if (!proxy) {
672 return nullptr;
673 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500674
Robert Phillips2c862492017-01-18 10:08:39 -0500675 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500676}
677
Robert Phillips26caf892017-01-27 10:58:31 -0500678sk_sp<GrSurfaceContext> GrContextPriv::makeBackendSurfaceContext(const GrBackendTextureDesc& desc,
Brian Osmanc1e37052017-03-09 14:19:20 -0500679 sk_sp<SkColorSpace> colorSpace) {
Robert Phillips26caf892017-01-27 10:58:31 -0500680 ASSERT_SINGLE_OWNER_PRIV
681
Brian Osmanc1e37052017-03-09 14:19:20 -0500682 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc));
Robert Phillips26caf892017-01-27 10:58:31 -0500683 if (!surface) {
684 return nullptr;
685 }
686
687 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500688 if (!proxy) {
689 return nullptr;
690 }
Robert Phillips26caf892017-01-27 10:58:31 -0500691
692 return this->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace));
693}
694
Brian Osman11052242016-10-27 14:47:55 -0400695sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
Robert Phillipse305cc1f2016-12-14 12:19:05 -0500696 const GrBackendTextureDesc& desc,
Brian Osman11052242016-10-27 14:47:55 -0400697 sk_sp<SkColorSpace> colorSpace,
Brian Osmanc1e37052017-03-09 14:19:20 -0500698 const SkSurfaceProps* props) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700699 ASSERT_SINGLE_OWNER_PRIV
700 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
701
Brian Osmanc1e37052017-03-09 14:19:20 -0500702 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc));
robertphillips4fd74ae2016-08-03 14:26:53 -0700703 if (!surface) {
704 return nullptr;
705 }
706
Robert Phillips37430132016-11-09 06:50:43 -0500707 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500708 if (!proxy) {
709 return nullptr;
710 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400711
Robert Phillips37430132016-11-09 06:50:43 -0500712 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Brian Osman11052242016-10-27 14:47:55 -0400713 std::move(colorSpace), props);
robertphillips4fd74ae2016-08-03 14:26:53 -0700714}
715
Brian Osman11052242016-10-27 14:47:55 -0400716sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
robertphillips4fd74ae2016-08-03 14:26:53 -0700717 const GrBackendRenderTargetDesc& desc,
718 sk_sp<SkColorSpace> colorSpace,
719 const SkSurfaceProps* surfaceProps) {
720 ASSERT_SINGLE_OWNER_PRIV
721
Brian Osman32342f02017-03-04 08:12:46 -0500722 sk_sp<GrRenderTarget> rt(fContext->resourceProvider()->wrapBackendRenderTarget(desc));
robertphillips4fd74ae2016-08-03 14:26:53 -0700723 if (!rt) {
724 return nullptr;
725 }
726
Robert Phillips37430132016-11-09 06:50:43 -0500727 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500728 if (!proxy) {
729 return nullptr;
730 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400731
Robert Phillips37430132016-11-09 06:50:43 -0500732 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400733 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400734 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700735}
736
Brian Osman11052242016-10-27 14:47:55 -0400737sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
egdaniela95d46b2016-08-15 08:06:29 -0700738 const GrBackendTextureDesc& desc,
robertphillips4fd74ae2016-08-03 14:26:53 -0700739 sk_sp<SkColorSpace> colorSpace,
740 const SkSurfaceProps* surfaceProps) {
741 ASSERT_SINGLE_OWNER_PRIV
742 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
743
744 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
745 if (!surface) {
746 return nullptr;
747 }
748
Robert Phillips37430132016-11-09 06:50:43 -0500749 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500750 if (!proxy) {
751 return nullptr;
752 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400753
Robert Phillips37430132016-11-09 06:50:43 -0500754 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400755 std::move(colorSpace),
756 surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700757}
758
Robert Phillipseb35f4d2017-03-21 07:56:47 -0400759void GrContextPriv::addPreFlushCallbackObject(sk_sp<GrPreFlushCallbackObject> preFlushCBObject) {
760 fContext->fDrawingManager->addPreFlushCallbackObject(std::move(preFlushCBObject));
761}
762
763
robertphillips48fde9c2016-09-06 05:20:20 -0700764static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
Brian Osman78f20e02017-01-12 10:28:01 -0500765 switch (config) {
766 case kAlpha_8_GrPixelConfig:
767 case kRGB_565_GrPixelConfig:
768 case kRGBA_4444_GrPixelConfig:
769 case kBGRA_8888_GrPixelConfig:
770 return kRGBA_8888_GrPixelConfig;
771 case kSBGRA_8888_GrPixelConfig:
772 return kSRGBA_8888_GrPixelConfig;
773 case kAlpha_half_GrPixelConfig:
774 return kRGBA_half_GrPixelConfig;
775 default:
776 return kUnknown_GrPixelConfig;
777 }
robertphillips48fde9c2016-09-06 05:20:20 -0700778}
779
Brian Osman11052242016-10-27 14:47:55 -0400780sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContextWithFallback(
781 SkBackingFit fit,
782 int width, int height,
783 GrPixelConfig config,
784 sk_sp<SkColorSpace> colorSpace,
785 int sampleCnt,
786 GrSurfaceOrigin origin,
787 const SkSurfaceProps* surfaceProps,
788 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700789 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
790 config = GrPixelConfigFallback(config);
791 }
792
Brian Osman11052242016-10-27 14:47:55 -0400793 return this->makeRenderTargetContext(fit, width, height, config, std::move(colorSpace),
794 sampleCnt, origin, surfaceProps, budgeted);
robertphillips48fde9c2016-09-06 05:20:20 -0700795}
796
robertphillipsd728f0c2016-11-21 11:05:03 -0800797sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallback(
798 SkBackingFit fit,
799 int width, int height,
800 GrPixelConfig config,
801 sk_sp<SkColorSpace> colorSpace,
802 int sampleCnt,
803 GrSurfaceOrigin origin,
804 const SkSurfaceProps* surfaceProps,
805 SkBudgeted budgeted) {
806 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
807 config = GrPixelConfigFallback(config);
808 }
809
810 return this->makeDeferredRenderTargetContext(fit, width, height, config, std::move(colorSpace),
811 sampleCnt, origin, surfaceProps, budgeted);
812}
813
Brian Osman11052242016-10-27 14:47:55 -0400814sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContext(SkBackingFit fit,
815 int width, int height,
816 GrPixelConfig config,
817 sk_sp<SkColorSpace> colorSpace,
818 int sampleCnt,
819 GrSurfaceOrigin origin,
820 const SkSurfaceProps* surfaceProps,
821 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700822 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
823 return nullptr;
824 }
825
robertphillipsd4c741e2016-04-28 09:55:15 -0700826 GrSurfaceDesc desc;
827 desc.fFlags = kRenderTarget_GrSurfaceFlag;
828 desc.fOrigin = origin;
829 desc.fWidth = width;
830 desc.fHeight = height;
831 desc.fConfig = config;
832 desc.fSampleCnt = sampleCnt;
833
834 sk_sp<GrTexture> tex;
robertphillips76948d42016-05-04 12:47:41 -0700835 if (SkBackingFit::kExact == fit) {
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400836 tex = this->resourceProvider()->createTexture(desc, budgeted);
robertphillipsd4c741e2016-04-28 09:55:15 -0700837 } else {
Brian Osman32342f02017-03-04 08:12:46 -0500838 tex.reset(this->resourceProvider()->createApproxTexture(desc, 0));
robertphillipsd4c741e2016-04-28 09:55:15 -0700839 }
840 if (!tex) {
841 return nullptr;
842 }
843
Brian Osman11052242016-10-27 14:47:55 -0400844 sk_sp<GrRenderTargetContext> renderTargetContext(
845 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(tex->asRenderTarget()),
robertphillips6738c702016-07-27 12:13:51 -0700846 std::move(colorSpace), surfaceProps));
Brian Osman11052242016-10-27 14:47:55 -0400847 if (!renderTargetContext) {
robertphillipsd4c741e2016-04-28 09:55:15 -0700848 return nullptr;
849 }
850
Brian Osman11052242016-10-27 14:47:55 -0400851 return renderTargetContext;
robertphillipsd4c741e2016-04-28 09:55:15 -0700852}
853
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400854sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext(
855 SkBackingFit fit,
856 int width, int height,
857 GrPixelConfig config,
858 sk_sp<SkColorSpace> colorSpace,
859 int sampleCnt,
860 GrSurfaceOrigin origin,
861 const SkSurfaceProps* surfaceProps,
862 SkBudgeted budgeted) {
863 GrSurfaceDesc desc;
864 desc.fFlags = kRenderTarget_GrSurfaceFlag;
865 desc.fOrigin = origin;
866 desc.fWidth = width;
867 desc.fHeight = height;
868 desc.fConfig = config;
869 desc.fSampleCnt = sampleCnt;
870
Brian Osman32342f02017-03-04 08:12:46 -0500871 sk_sp<GrTextureProxy> rtp = GrSurfaceProxy::MakeDeferred(this->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400872 desc, fit, budgeted);
Robert Phillips08c5ec72017-01-30 12:26:47 -0500873 if (!rtp) {
874 return nullptr;
875 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400876
877 return fDrawingManager->makeRenderTargetContext(std::move(rtp),
878 std::move(colorSpace),
879 surfaceProps);
880}
881
joshualitt1de610a2016-01-06 08:26:09 -0800882bool GrContext::abandoned() const {
883 ASSERT_SINGLE_OWNER
robertphillips7761d612016-05-16 09:14:53 -0700884 return fDrawingManager->wasAbandoned();
robertphillips77a2e522015-10-17 07:43:27 -0700885}
886
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000887namespace {
888void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
889 GrConfigConversionEffect::PMConversion pmToUPM;
890 GrConfigConversionEffect::PMConversion upmToPM;
891 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
892 *pmToUPMValue = pmToUPM;
893 *upmToPMValue = upmToPM;
894}
895}
896
bsalomon6c6f6582015-09-10 08:12:46 -0700897void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800898 ASSERT_SINGLE_OWNER
Robert Phillipsaaee31f2017-04-05 12:18:58 -0400899 if (SkToBool(GrContextPriv::kUnpremul_PixelOpsFlag & flags)) {
bsalomon6c6f6582015-09-10 08:12:46 -0700900 if (!fDidTestPMConversions) {
901 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
902 fDidTestPMConversions = true;
903 }
904 }
905}
906
Robert Phillips757914d2017-01-25 15:48:30 -0500907sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrTextureProxy> proxy,
Robert Phillips757914d2017-01-25 15:48:30 -0500908 const SkMatrix& matrix) {
909 ASSERT_SINGLE_OWNER
910 // We should have already called this->testPMConversionsIfNecessary().
911 SkASSERT(fDidTestPMConversions);
Brian Osmanee805322017-04-05 10:09:00 -0400912 GrPixelConfig config = proxy->config();
913 sk_sp<GrFragmentProcessor> fp = GrSimpleTextureEffect::Make(this->resourceProvider(),
914 std::move(proxy), nullptr, matrix);
915 if (kRGBA_half_GrPixelConfig == config) {
916 return GrFragmentProcessor::UnpremulOutput(std::move(fp));
917 } else if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
Brian Osmande1a6052017-03-22 10:57:00 -0400918 GrConfigConversionEffect::PMConversion pmToUPM =
919 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
Brian Osmance425512017-03-22 14:37:50 -0400920 if (GrConfigConversionEffect::kPMConversionCnt != pmToUPM) {
Brian Osmanee805322017-04-05 10:09:00 -0400921 return GrConfigConversionEffect::Make(std::move(fp), pmToUPM);
Brian Osmande1a6052017-03-22 10:57:00 -0400922 }
Robert Phillips757914d2017-01-25 15:48:30 -0500923 }
Brian Osmanee805322017-04-05 10:09:00 -0400924 return nullptr;
Robert Phillips757914d2017-01-25 15:48:30 -0500925}
926
927sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrTextureProxy> proxy,
Robert Phillips757914d2017-01-25 15:48:30 -0500928 const SkMatrix& matrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800929 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700930 // We should have already called this->testPMConversionsIfNecessary().
931 SkASSERT(fDidTestPMConversions);
Brian Osmanee805322017-04-05 10:09:00 -0400932 GrPixelConfig config = proxy->config();
933 sk_sp<GrFragmentProcessor> fp = GrSimpleTextureEffect::Make(this->resourceProvider(),
934 std::move(proxy), nullptr, matrix);
935 if (kRGBA_half_GrPixelConfig == config) {
936 return GrFragmentProcessor::PremulOutput(std::move(fp));
937 } else if (kRGBA_8888_GrPixelConfig == config || kBGRA_8888_GrPixelConfig == config) {
Brian Osmande1a6052017-03-22 10:57:00 -0400938 GrConfigConversionEffect::PMConversion upmToPM =
939 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
Brian Osmance425512017-03-22 14:37:50 -0400940 if (GrConfigConversionEffect::kPMConversionCnt != upmToPM) {
Brian Osmanee805322017-04-05 10:09:00 -0400941 return GrConfigConversionEffect::Make(std::move(fp), upmToPM);
Brian Osmande1a6052017-03-22 10:57:00 -0400942 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000943 }
Brian Osmanee805322017-04-05 10:09:00 -0400944 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000945}
946
Brian Osmande1a6052017-03-22 10:57:00 -0400947bool GrContext::validPMUPMConversionExists(GrPixelConfig config) const {
joshualitt1de610a2016-01-06 08:26:09 -0800948 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700949 // We should have already called this->testPMConversionsIfNecessary().
950 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700951 // The PM<->UPM tests fail or succeed together so we only need to check one.
Brian Osmande1a6052017-03-22 10:57:00 -0400952 // 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 -0400953 return GrConfigConversionEffect::kPMConversionCnt != fPMToUPMConversion ||
Brian Osmande1a6052017-03-22 10:57:00 -0400954 kRGBA_half_GrPixelConfig == config;
bsalomon636e8022015-07-29 06:08:46 -0700955}
956
bsalomon37f9a262015-02-02 13:00:10 -0800957//////////////////////////////////////////////////////////////////////////////
958
959void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800960 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800961 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800962 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800963 }
964 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800965 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800966 }
967}
968
969void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800970 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800971 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800972}
973
ericrk0a5fa482015-09-15 14:16:10 -0700974//////////////////////////////////////////////////////////////////////////////
975
976void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800977 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700978 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
979}