blob: c0d63a33b05f5cde4f12384521526cbcdf947106 [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
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000029#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
joshualitt1de610a2016-01-06 08:26:09 -080030#define ASSERT_SINGLE_OWNER \
31 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fSingleOwner);)
robertphillips4fd74ae2016-08-03 14:26:53 -070032#define ASSERT_SINGLE_OWNER_PRIV \
33 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(&fContext->fSingleOwner);)
robertphillips7761d612016-05-16 09:14:53 -070034#define RETURN_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return; }
35#define RETURN_FALSE_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return false; }
36#define RETURN_NULL_IF_ABANDONED if (fDrawingManager->wasAbandoned()) { return nullptr; }
bsalomon@google.combc4b6542011-11-19 13:56:11 +000037
robertphillipsea461502015-05-26 11:38:03 -070038////////////////////////////////////////////////////////////////////////////////
39
bsalomon682c2692015-05-22 14:01:46 -070040GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
41 GrContextOptions defaultOptions;
42 return Create(backend, backendContext, defaultOptions);
43}
bsalomonf28cff72015-05-22 12:25:41 -070044
bsalomon682c2692015-05-22 14:01:46 -070045GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
46 const GrContextOptions& options) {
halcanary385fe4d2015-08-26 13:07:48 -070047 GrContext* context = new GrContext;
bsalomon682c2692015-05-22 14:01:46 -070048
49 if (context->init(backend, backendContext, options)) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000050 return context;
51 } else {
52 context->unref();
halcanary96fcdcc2015-08-27 07:41:13 -070053 return nullptr;
bsalomon@google.com27847de2011-02-22 20:59:41 +000054 }
bsalomon@google.com27847de2011-02-22 20:59:41 +000055}
56
joshualitt0acd0d32015-05-07 08:23:19 -070057static int32_t gNextID = 1;
58static int32_t next_id() {
59 int32_t id;
60 do {
61 id = sk_atomic_inc(&gNextID);
62 } while (id == SK_InvalidGenID);
63 return id;
64}
65
bsalomon682c2692015-05-22 14:01:46 -070066GrContext::GrContext() : fUniqueID(next_id()) {
halcanary96fcdcc2015-08-27 07:41:13 -070067 fGpu = nullptr;
68 fCaps = nullptr;
69 fResourceCache = nullptr;
70 fResourceProvider = nullptr;
Brian Salomonf856fd12016-12-16 14:24:34 -050071 fAtlasGlyphCache = nullptr;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000072}
73
bsalomon682c2692015-05-22 14:01:46 -070074bool GrContext::init(GrBackend backend, GrBackendContext backendContext,
75 const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080076 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -070077 SkASSERT(!fGpu);
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000078
bsalomon682c2692015-05-22 14:01:46 -070079 fGpu = GrGpu::Create(backend, backendContext, options, this);
robertphillipsea461502015-05-26 11:38:03 -070080 if (!fGpu) {
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000081 return false;
82 }
bsalomon69cfe952015-11-30 13:27:47 -080083 this->initCommon(options);
bsalomon33435572014-11-05 14:47:41 -080084 return true;
85}
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000086
bsalomon69cfe952015-11-30 13:27:47 -080087void GrContext::initCommon(const GrContextOptions& options) {
joshualitt1de610a2016-01-06 08:26:09 -080088 ASSERT_SINGLE_OWNER
89
bsalomon76228632015-05-29 08:02:10 -070090 fCaps = SkRef(fGpu->caps());
halcanary385fe4d2015-08-26 13:07:48 -070091 fResourceCache = new GrResourceCache(fCaps);
joshualitt6d0872d2016-01-11 08:27:48 -080092 fResourceProvider = new GrResourceProvider(fGpu, fResourceCache, &fSingleOwner);
commit-bot@chromium.org1836d332013-07-16 22:55:03 +000093
Brian Osman46da1cc2017-02-14 14:15:48 -050094 fDisableGpuYUVConversion = options.fDisableGpuYUVConversion;
bsalomon@google.com6e4e6502013-02-25 20:12:45 +000095 fDidTestPMConversions = false;
96
Robert Phillipsf2361d22016-10-25 14:20:06 -040097 GrRenderTargetOpList::Options rtOpListOptions;
Brian Salomon09d994e2016-12-21 11:14:46 -050098 rtOpListOptions.fMaxOpCombineLookback = options.fMaxOpCombineLookback;
99 rtOpListOptions.fMaxOpCombineLookahead = options.fMaxOpCombineLookahead;
bsalomon6b2552f2016-09-15 13:50:26 -0700100 GrPathRendererChain::Options prcOptions;
bsalomon39ef7fb2016-09-21 11:16:05 -0700101 prcOptions.fAllowPathMaskCaching = options.fAllowPathMaskCaching;
csmartdalton008b9d82017-02-22 12:00:42 -0700102 prcOptions.fGpuPathRenderers = options.fGpuPathRenderers;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400103 fDrawingManager.reset(new GrDrawingManager(this, rtOpListOptions, prcOptions,
104 options.fImmediateMode, &fSingleOwner));
joshualitt7c3a2f82015-03-31 13:32:05 -0700105
Brian Salomonf856fd12016-12-16 14:24:34 -0500106 fAtlasGlyphCache = new GrAtlasGlyphCache(this);
joshualittb7133be2015-04-08 09:08:31 -0700107
halcanary385fe4d2015-08-26 13:07:48 -0700108 fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
bsalomon@google.comc0af3172012-06-15 14:10:09 +0000109}
110
bsalomon@google.com27847de2011-02-22 20:59:41 +0000111GrContext::~GrContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800112 ASSERT_SINGLE_OWNER
113
robertphillipsea461502015-05-26 11:38:03 -0700114 if (!fGpu) {
bsalomon76228632015-05-29 08:02:10 -0700115 SkASSERT(!fCaps);
bsalomon@google.com733c0622013-04-24 17:59:32 +0000116 return;
117 }
118
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000119 this->flush();
robertphillips@google.com5acc0e32012-05-17 12:01:02 +0000120
robertphillips77a2e522015-10-17 07:43:27 -0700121 fDrawingManager->cleanup();
robertphillips2334fb62015-06-17 05:43:33 -0700122
robertphillips@google.com950b1b02013-10-21 17:37:28 +0000123 for (int i = 0; i < fCleanUpData.count(); ++i) {
124 (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
125 }
126
halcanary385fe4d2015-08-26 13:07:48 -0700127 delete fResourceProvider;
128 delete fResourceCache;
Brian Salomonf856fd12016-12-16 14:24:34 -0500129 delete fAtlasGlyphCache;
robertphillips@google.comf6747b02012-06-12 00:32:28 +0000130
bsalomon@google.com205d4602011-04-25 12:43:45 +0000131 fGpu->unref();
bsalomon76228632015-05-29 08:02:10 -0700132 fCaps->unref();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000133}
134
bungeman6bd52842016-10-27 09:30:08 -0700135sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() {
bsalomon41b952c2016-03-11 06:46:33 -0800136 if (!fThreadSafeProxy) {
bungeman6bd52842016-10-27 09:30:08 -0700137 fThreadSafeProxy.reset(new GrContextThreadSafeProxy(sk_ref_sp(fCaps), this->uniqueID()));
bsalomon41b952c2016-03-11 06:46:33 -0800138 }
bungeman6bd52842016-10-27 09:30:08 -0700139 return fThreadSafeProxy;
bsalomon41b952c2016-03-11 06:46:33 -0800140}
141
bsalomon2354f842014-07-28 13:48:36 -0700142void GrContext::abandonContext() {
joshualitt1de610a2016-01-06 08:26:09 -0800143 ASSERT_SINGLE_OWNER
144
bsalomond309e7a2015-04-30 14:18:54 -0700145 fResourceProvider->abandon();
robertphillips0dfa62c2015-11-16 06:23:31 -0800146
147 // Need to abandon the drawing manager first so all the render targets
148 // will be released/forgotten before they too are abandoned.
149 fDrawingManager->abandon();
150
bsalomon@google.com205d4602011-04-25 12:43:45 +0000151 // abandon first to so destructors
152 // don't try to free the resources in the API.
bsalomon0ea80f42015-02-11 10:49:59 -0800153 fResourceCache->abandonAll();
bsalomonc8dc1f72014-08-21 13:02:13 -0700154
bsalomon6e2aad42016-04-01 11:54:31 -0700155 fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
156
Brian Salomonf856fd12016-12-16 14:24:34 -0500157 fAtlasGlyphCache->freeAll();
bsalomon6e2aad42016-04-01 11:54:31 -0700158 fTextBlobCache->freeAll();
159}
160
161void GrContext::releaseResourcesAndAbandonContext() {
162 ASSERT_SINGLE_OWNER
163
164 fResourceProvider->abandon();
165
166 // Need to abandon the drawing manager first so all the render targets
167 // will be released/forgotten before they too are abandoned.
168 fDrawingManager->abandon();
169
170 // Release all resources in the backend 3D API.
171 fResourceCache->releaseAll();
172
173 fGpu->disconnect(GrGpu::DisconnectType::kCleanup);
bsalomon@google.com205d4602011-04-25 12:43:45 +0000174
Brian Salomonf856fd12016-12-16 14:24:34 -0500175 fAtlasGlyphCache->freeAll();
joshualitt26ffc002015-04-16 11:24:04 -0700176 fTextBlobCache->freeAll();
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000177}
178
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000179void GrContext::resetContext(uint32_t state) {
joshualitt1de610a2016-01-06 08:26:09 -0800180 ASSERT_SINGLE_OWNER
bsalomon@google.com0a208a12013-06-28 18:57:35 +0000181 fGpu->markContextDirty(state);
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000182}
183
184void GrContext::freeGpuResources() {
joshualitt1de610a2016-01-06 08:26:09 -0800185 ASSERT_SINGLE_OWNER
186
bsalomon@google.com8fe72472011-03-30 21:26:44 +0000187 this->flush();
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000188
Brian Salomonf856fd12016-12-16 14:24:34 -0500189 fAtlasGlyphCache->freeAll();
robertphillips68737822015-10-29 12:12:21 -0700190
191 fDrawingManager->freeGpuResources();
bsalomon3033b9f2015-04-13 11:09:56 -0700192
193 fResourceCache->purgeAllUnlocked();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000194}
195
commit-bot@chromium.org95c20032014-05-09 14:29:32 +0000196void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800197 ASSERT_SINGLE_OWNER
198
bsalomon71cb0c22014-11-14 12:10:14 -0800199 if (resourceCount) {
bsalomon0ea80f42015-02-11 10:49:59 -0800200 *resourceCount = fResourceCache->getBudgetedResourceCount();
bsalomon71cb0c22014-11-14 12:10:14 -0800201 }
202 if (resourceBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800203 *resourceBytes = fResourceCache->getBudgetedResourceBytes();
bsalomon71cb0c22014-11-14 12:10:14 -0800204 }
commit-bot@chromium.orgd8a57af2014-03-19 21:19:16 +0000205}
206
bsalomon@google.comfea37b52011-04-25 15:51:06 +0000207////////////////////////////////////////////////////////////////////////////////
208
joshualitt0db6dfa2015-04-10 07:01:30 -0700209void GrContext::TextBlobCacheOverBudgetCB(void* data) {
210 SkASSERT(data);
Brian Osman11052242016-10-27 14:47:55 -0400211 // TextBlobs are drawn at the SkGpuDevice level, therefore they cannot rely on
212 // GrRenderTargetContext to perform a necessary flush. The solution is to move drawText calls
213 // to below the GrContext level, but this is not trivial because they call drawPath on
214 // SkGpuDevice.
joshualitt0db6dfa2015-04-10 07:01:30 -0700215 GrContext* context = reinterpret_cast<GrContext*>(data);
216 context->flush();
217}
218
bsalomon@google.com27847de2011-02-22 20:59:41 +0000219////////////////////////////////////////////////////////////////////////////////
220
bsalomonb77a9072016-09-07 10:02:04 -0700221void GrContext::flush() {
joshualitt1de610a2016-01-06 08:26:09 -0800222 ASSERT_SINGLE_OWNER
robertphillipsea461502015-05-26 11:38:03 -0700223 RETURN_IF_ABANDONED
bsalomonb77a9072016-09-07 10:02:04 -0700224 fDrawingManager->flush();
bsalomon@google.com27847de2011-02-22 20:59:41 +0000225}
226
bsalomon81beccc2014-10-13 12:32:55 -0700227bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
228 const void* inPixels, size_t outRowBytes, void* outPixels) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500229 SkColorType colorType;
230 if (!GrPixelConfigToColorType(srcConfig, &colorType) ||
231 4 != SkColorTypeBytesPerPixel(colorType))
232 {
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000233 return false;
234 }
bsalomon81beccc2014-10-13 12:32:55 -0700235
Matt Sarettc7b29082017-02-09 16:22:39 -0500236 for (int y = 0; y < height; y++) {
237 SkOpts::RGBA_to_rgbA((uint32_t*) outPixels, inPixels, width);
238 outPixels = SkTAddOffset<void>(outPixels, outRowBytes);
239 inPixels = SkTAddOffset<const void>(inPixels, inRowBytes);
240 }
bsalomon81beccc2014-10-13 12:32:55 -0700241
Matt Sarettc7b29082017-02-09 16:22:39 -0500242 return true;
bsalomon@google.com669fdc42011-04-05 17:08:27 +0000243}
244
Brian Osmanb62ea222016-12-22 11:12:16 -0500245bool GrContext::writeSurfacePixels(GrSurface* surface, SkColorSpace* dstColorSpace,
bsalomon81beccc2014-10-13 12:32:55 -0700246 int left, int top, int width, int height,
Brian Osmanb62ea222016-12-22 11:12:16 -0500247 GrPixelConfig srcConfig, SkColorSpace* srcColorSpace,
248 const void* buffer, size_t rowBytes, uint32_t pixelOpsFlags) {
249 // TODO: Color space conversion
250
joshualitt1de610a2016-01-06 08:26:09 -0800251 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800252 RETURN_FALSE_IF_ABANDONED
bsalomon6c6f6582015-09-10 08:12:46 -0700253 ASSERT_OWNED_RESOURCE(surface);
254 SkASSERT(surface);
joshualittbc907352016-01-13 06:45:40 -0800255 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::writeSurfacePixels");
bsalomon6c6f6582015-09-10 08:12:46 -0700256
257 this->testPMConversionsIfNecessary(pixelOpsFlags);
bsalomon81beccc2014-10-13 12:32:55 -0700258
bsalomone8d21e82015-07-16 08:23:13 -0700259 // 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 -0700260 // necessary and because GrGpu::getWritePixelsInfo requires it.
bsalomone8d21e82015-07-16 08:23:13 -0700261 if (!GrSurfacePriv::AdjustWritePixelParams(surface->width(), surface->height(),
262 GrBytesPerPixel(srcConfig), &left, &top, &width,
263 &height, &buffer, &rowBytes)) {
264 return false;
265 }
266
bsalomonf0674512015-07-28 13:26:15 -0700267 bool applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700268 if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
Brian Salomonbf7b6202016-11-11 16:08:03 -0500269 if (!GrPixelConfigIs8888Unorm(srcConfig)) {
bsalomon81beccc2014-10-13 12:32:55 -0700270 return false;
271 }
bsalomonf0674512015-07-28 13:26:15 -0700272 applyPremulToSrc = true;
273 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500274 // We don't allow conversion between integer configs and float/fixed configs.
275 if (GrPixelConfigIsSint(surface->config()) != GrPixelConfigIsSint(srcConfig)) {
276 return false;
277 }
bsalomon636e8022015-07-29 06:08:46 -0700278
279 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
280 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
281 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
282 if (applyPremulToSrc && !this->didFailPMUPMConversionTest()) {
283 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
284 }
285
bsalomonf0674512015-07-28 13:26:15 -0700286 GrGpu::WritePixelTempDrawInfo tempDrawInfo;
cblumeed828002016-02-16 13:00:01 -0800287 if (!fGpu->getWritePixelsInfo(surface, width, height, srcConfig, &drawPreference,
bsalomonf0674512015-07-28 13:26:15 -0700288 &tempDrawInfo)) {
289 return false;
290 }
291
292 if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) && surface->surfacePriv().hasPendingIO()) {
293 this->flush();
294 }
295
Robert Phillips2f493142017-03-02 18:18:38 -0500296 sk_sp<GrTextureProxy> tempProxy;
bsalomonf0674512015-07-28 13:26:15 -0700297 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
Brian Osman32342f02017-03-04 08:12:46 -0500298 tempProxy = GrSurfaceProxy::MakeDeferred(this->resourceProvider(),
Robert Phillips2f493142017-03-02 18:18:38 -0500299 tempDrawInfo.fTempSurfaceDesc,
300 SkBackingFit::kApprox,
301 SkBudgeted::kYes);
302 if (!tempProxy && GrGpu::kRequireDraw_DrawPreference == drawPreference) {
bsalomonf0674512015-07-28 13:26:15 -0700303 return false;
304 }
305 }
306
307 // temp buffer for doing sw premul conversion, if needed.
308 SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
Robert Phillips2f493142017-03-02 18:18:38 -0500309 if (tempProxy) {
bungeman06ca8ec2016-06-09 08:01:03 -0700310 sk_sp<GrFragmentProcessor> fp;
bsalomonf0674512015-07-28 13:26:15 -0700311 if (applyPremulToSrc) {
Robert Phillips2f493142017-03-02 18:18:38 -0500312 fp = this->createUPMToPMEffect(tempProxy, tempDrawInfo.fSwizzle, SkMatrix::I());
bsalomonf0674512015-07-28 13:26:15 -0700313 // If premultiplying was the only reason for the draw, fall back to a straight write.
314 if (!fp) {
315 if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
Robert Phillips2f493142017-03-02 18:18:38 -0500316 tempProxy.reset(nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700317 }
318 } else {
319 applyPremulToSrc = false;
320 }
321 }
Robert Phillips2f493142017-03-02 18:18:38 -0500322 if (tempProxy) {
bsalomonf0674512015-07-28 13:26:15 -0700323 if (!fp) {
Robert Phillips296b1cc2017-03-15 10:42:12 -0400324 fp = GrConfigConversionEffect::Make(this->resourceProvider(),
325 tempProxy, tempDrawInfo.fSwizzle,
bungeman06ca8ec2016-06-09 08:01:03 -0700326 GrConfigConversionEffect::kNone_PMConversion,
Robert Phillips67c18d62017-01-20 12:44:06 -0500327 SkMatrix::I());
bsalomonf0674512015-07-28 13:26:15 -0700328 if (!fp) {
329 return false;
330 }
331 }
Brian Osman32342f02017-03-04 08:12:46 -0500332 GrTexture* texture = tempProxy->instantiate(this->resourceProvider());
Robert Phillips757914d2017-01-25 15:48:30 -0500333 if (!texture) {
334 return false;
335 }
336 if (texture->surfacePriv().hasPendingIO()) {
bsalomonf0674512015-07-28 13:26:15 -0700337 this->flush();
338 }
339 if (applyPremulToSrc) {
340 size_t tmpRowBytes = 4 * width;
341 tmpPixels.reset(width * height);
342 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
343 tmpPixels.get())) {
344 return false;
345 }
346 rowBytes = tmpRowBytes;
347 buffer = tmpPixels.get();
348 applyPremulToSrc = false;
349 }
Robert Phillips757914d2017-01-25 15:48:30 -0500350 if (!fGpu->writePixels(texture, 0, 0, width, height,
bsalomon6c9cd552016-01-22 07:17:34 -0800351 tempDrawInfo.fWriteConfig, buffer,
bsalomon6cb3cbe2015-07-30 07:34:27 -0700352 rowBytes)) {
bsalomonf0674512015-07-28 13:26:15 -0700353 return false;
354 }
355 SkMatrix matrix;
356 matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
brianosmandfe4f2e2016-07-21 13:28:36 -0700357 // TODO: Need to decide the semantics of this function for color spaces. Do we support
358 // conversion from a passed-in color space? For now, specifying nullptr means that this
359 // path will do no conversion, so it will match the behavior of the non-draw path.
Robert Phillips757914d2017-01-25 15:48:30 -0500360 GrRenderTarget* renderTarget = surface->asRenderTarget();
361 SkASSERT(renderTarget);
Brian Osman11052242016-10-27 14:47:55 -0400362 sk_sp<GrRenderTargetContext> renderTargetContext(
363 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(renderTarget),
364 nullptr));
365 if (!renderTargetContext) {
bsalomonf0674512015-07-28 13:26:15 -0700366 return false;
367 }
egdanielc4b72722015-11-23 13:20:41 -0800368 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700369 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700370 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700371 paint.setAllowSRGBInputs(true);
bsalomonf0674512015-07-28 13:26:15 -0700372 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon82f44312017-01-11 13:42:54 -0500373 renderTargetContext->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, matrix, rect,
374 nullptr);
bsalomonf0674512015-07-28 13:26:15 -0700375
376 if (kFlushWrites_PixelOp & pixelOpsFlags) {
377 this->flushSurfaceWrites(surface);
378 }
379 }
380 }
Robert Phillips2f493142017-03-02 18:18:38 -0500381 if (!tempProxy) {
bsalomonf0674512015-07-28 13:26:15 -0700382 if (applyPremulToSrc) {
bsalomon81beccc2014-10-13 12:32:55 -0700383 size_t tmpRowBytes = 4 * width;
384 tmpPixels.reset(width * height);
385 if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
386 tmpPixels.get())) {
387 return false;
388 }
389 rowBytes = tmpRowBytes;
390 buffer = tmpPixels.get();
bsalomonf0674512015-07-28 13:26:15 -0700391 applyPremulToSrc = false;
bsalomon81beccc2014-10-13 12:32:55 -0700392 }
bsalomon6cb3cbe2015-07-30 07:34:27 -0700393 return fGpu->writePixels(surface, left, top, width, height, srcConfig, buffer, rowBytes);
bsalomon81beccc2014-10-13 12:32:55 -0700394 }
bsalomon81beccc2014-10-13 12:32:55 -0700395 return true;
396}
bsalomon@google.coma91e9232012-02-23 15:39:54 +0000397
Brian Osmanb62ea222016-12-22 11:12:16 -0500398bool GrContext::readSurfacePixels(GrSurface* src, SkColorSpace* srcColorSpace,
bsalomone8d21e82015-07-16 08:23:13 -0700399 int left, int top, int width, int height,
Brian Osmanb62ea222016-12-22 11:12:16 -0500400 GrPixelConfig dstConfig, SkColorSpace* dstColorSpace,
401 void* buffer, size_t rowBytes, uint32_t flags) {
402 // TODO: Color space conversion
403
joshualitt1de610a2016-01-06 08:26:09 -0800404 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800405 RETURN_FALSE_IF_ABANDONED
bsalomone8d21e82015-07-16 08:23:13 -0700406 ASSERT_OWNED_RESOURCE(src);
407 SkASSERT(src);
joshualittbc907352016-01-13 06:45:40 -0800408 GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::readSurfacePixels");
bsalomon32ab2602015-09-09 18:57:49 -0700409
bsalomon6c6f6582015-09-10 08:12:46 -0700410 this->testPMConversionsIfNecessary(flags);
bsalomon6c6f6582015-09-10 08:12:46 -0700411
bsalomone8d21e82015-07-16 08:23:13 -0700412 // Adjust the params so that if we wind up using an intermediate surface we've already done
413 // all the trimming and the temporary can be the min size required.
414 if (!GrSurfacePriv::AdjustReadPixelParams(src->width(), src->height(),
415 GrBytesPerPixel(dstConfig), &left,
416 &top, &width, &height, &buffer, &rowBytes)) {
417 return false;
418 }
419
420 if (!(kDontFlush_PixelOpsFlag & flags) && src->surfacePriv().hasPendingWrite()) {
bsalomon@google.com6f379512011-11-16 20:36:03 +0000421 this->flush();
422 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000423
bsalomone8d21e82015-07-16 08:23:13 -0700424 bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
Brian Salomonbf7b6202016-11-11 16:08:03 -0500425 if (unpremul && !GrPixelConfigIs8888Unorm(dstConfig)) {
bsalomon39826022015-07-23 08:07:21 -0700426 // The unpremul flag is only allowed for 8888 configs.
bsalomon@google.com0a97be22011-11-08 19:20:57 +0000427 return false;
428 }
Brian Salomonbf7b6202016-11-11 16:08:03 -0500429 // We don't allow conversion between integer configs and float/fixed configs.
430 if (GrPixelConfigIsSint(src->config()) != GrPixelConfigIsSint(dstConfig)) {
431 return false;
432 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000433
bsalomon636e8022015-07-29 06:08:46 -0700434 GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference;
435 // Don't prefer to draw for the conversion (and thereby access a texture from the cache) when
436 // we've already determined that there isn't a roundtrip preserving conversion processor pair.
437 if (unpremul && !this->didFailPMUPMConversionTest()) {
438 drawPreference = GrGpu::kCallerPrefersDraw_DrawPreference;
439 }
440
bsalomon39826022015-07-23 08:07:21 -0700441 GrGpu::ReadPixelTempDrawInfo tempDrawInfo;
442 if (!fGpu->getReadPixelsInfo(src, width, height, rowBytes, dstConfig, &drawPreference,
443 &tempDrawInfo)) {
444 return false;
445 }
bsalomon191bcc02014-11-14 11:31:13 -0800446
Hal Canary144caf52016-11-07 17:57:18 -0500447 sk_sp<GrSurface> surfaceToRead(SkRef(src));
bsalomon39826022015-07-23 08:07:21 -0700448 bool didTempDraw = false;
449 if (GrGpu::kNoDraw_DrawPreference != drawPreference) {
bsalomonb117ff12016-07-19 07:24:40 -0700450 if (SkBackingFit::kExact == tempDrawInfo.fTempSurfaceFit) {
bsalomon39826022015-07-23 08:07:21 -0700451 // We only respect this when the entire src is being read. Otherwise we can trigger too
452 // many odd ball texture sizes and trash the cache.
bsalomoneae62002015-07-31 13:59:30 -0700453 if (width != src->width() || height != src->height()) {
bsalomonb117ff12016-07-19 07:24:40 -0700454 tempDrawInfo.fTempSurfaceFit= SkBackingFit::kApprox;
bsalomon39826022015-07-23 08:07:21 -0700455 }
bsalomon@google.com56d11e02011-11-30 19:59:08 +0000456 }
brianosmandfe4f2e2016-07-21 13:28:36 -0700457 // TODO: Need to decide the semantics of this function for color spaces. Do we support
458 // conversion to a passed-in color space? For now, specifying nullptr means that this
459 // path will do no conversion, so it will match the behavior of the non-draw path.
Brian Osman693a5402016-10-27 15:13:22 -0400460 sk_sp<GrRenderTargetContext> tempRTC = this->makeRenderTargetContext(
Brian Osman11052242016-10-27 14:47:55 -0400461 tempDrawInfo.fTempSurfaceFit,
bsalomonb117ff12016-07-19 07:24:40 -0700462 tempDrawInfo.fTempSurfaceDesc.fWidth,
463 tempDrawInfo.fTempSurfaceDesc.fHeight,
464 tempDrawInfo.fTempSurfaceDesc.fConfig,
brianosmandfe4f2e2016-07-21 13:28:36 -0700465 nullptr,
bsalomonb117ff12016-07-19 07:24:40 -0700466 tempDrawInfo.fTempSurfaceDesc.fSampleCnt,
467 tempDrawInfo.fTempSurfaceDesc.fOrigin);
Brian Osman693a5402016-10-27 15:13:22 -0400468 if (tempRTC) {
Robert Phillips67c18d62017-01-20 12:44:06 -0500469 SkMatrix textureMatrix = SkMatrix::MakeTrans(SkIntToScalar(left), SkIntToScalar(top));
bungeman06ca8ec2016-06-09 08:01:03 -0700470 sk_sp<GrFragmentProcessor> fp;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000471 if (unpremul) {
bungeman06ca8ec2016-06-09 08:01:03 -0700472 fp = this->createPMToUPMEffect(src->asTexture(), tempDrawInfo.fSwizzle,
473 textureMatrix);
joshualittb0a8a372014-09-23 09:50:21 -0700474 if (fp) {
bsalomon@google.com9c680582013-02-06 18:17:50 +0000475 unpremul = false; // we no longer need to do this on CPU after the read back.
bsalomon39826022015-07-23 08:07:21 -0700476 } else if (GrGpu::kCallerPrefersDraw_DrawPreference == drawPreference) {
477 // We only wanted to do the draw in order to perform the unpremul so don't
478 // bother.
Brian Osman693a5402016-10-27 15:13:22 -0400479 tempRTC.reset(nullptr);
bsalomon@google.comd8b5fac2012-11-01 17:02:46 +0000480 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000481 }
Brian Osman693a5402016-10-27 15:13:22 -0400482 if (!fp && tempRTC) {
bungeman06ca8ec2016-06-09 08:01:03 -0700483 fp = GrConfigConversionEffect::Make(src->asTexture(), tempDrawInfo.fSwizzle,
484 GrConfigConversionEffect::kNone_PMConversion,
485 textureMatrix);
bsalomon39826022015-07-23 08:07:21 -0700486 }
487 if (fp) {
egdanielc4b72722015-11-23 13:20:41 -0800488 GrPaint paint;
bungeman06ca8ec2016-06-09 08:01:03 -0700489 paint.addColorFragmentProcessor(std::move(fp));
reed374772b2016-10-05 17:33:02 -0700490 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
brianosmana167e742016-05-24 06:18:48 -0700491 paint.setAllowSRGBInputs(true);
bsalomon39826022015-07-23 08:07:21 -0700492 SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
Brian Salomon82f44312017-01-11 13:42:54 -0500493 tempRTC->drawRect(GrNoClip(), std::move(paint), GrAA::kNo, SkMatrix::I(), rect,
494 nullptr);
Brian Osman693a5402016-10-27 15:13:22 -0400495 surfaceToRead.reset(tempRTC->asTexture().release());
bsalomon39826022015-07-23 08:07:21 -0700496 left = 0;
497 top = 0;
498 didTempDraw = true;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000499 }
bsalomon@google.com0342a852012-08-20 19:22:38 +0000500 }
bsalomon@google.comc4364992011-11-07 15:54:49 +0000501 }
joshualitt5c55fef2014-10-31 14:04:35 -0700502
Robert Phillips833dcf42016-11-18 08:44:13 -0500503 if (!surfaceToRead) {
504 return false;
505 }
506
bsalomon39826022015-07-23 08:07:21 -0700507 if (GrGpu::kRequireDraw_DrawPreference == drawPreference && !didTempDraw) {
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000508 return false;
509 }
bsalomon39826022015-07-23 08:07:21 -0700510 GrPixelConfig configToRead = dstConfig;
511 if (didTempDraw) {
Hal Canary144caf52016-11-07 17:57:18 -0500512 this->flushSurfaceWrites(surfaceToRead.get());
bsalomon6c9cd552016-01-22 07:17:34 -0800513 configToRead = tempDrawInfo.fReadConfig;
bsalomon39826022015-07-23 08:07:21 -0700514 }
Hal Canary144caf52016-11-07 17:57:18 -0500515 if (!fGpu->readPixels(surfaceToRead.get(), left, top, width, height, configToRead, buffer,
516 rowBytes)) {
bsalomon39826022015-07-23 08:07:21 -0700517 return false;
518 }
519
520 // Perform umpremul conversion if we weren't able to perform it as a draw.
521 if (unpremul) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500522 SkColorType colorType;
523 if (!GrPixelConfigToColorType(dstConfig, &colorType) ||
524 4 != SkColorTypeBytesPerPixel(colorType))
525 {
reed@google.com7111d462014-03-25 16:20:24 +0000526 return false;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000527 }
reed@google.com7111d462014-03-25 16:20:24 +0000528
Matt Sarettc7b29082017-02-09 16:22:39 -0500529 for (int y = 0; y < height; y++) {
530 SkUnpremultiplyRow<false>((uint32_t*) buffer, (const uint32_t*) buffer, width);
531 buffer = SkTAddOffset<void>(buffer, rowBytes);
532 }
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000533 }
534 return true;
bsalomon@google.com27847de2011-02-22 20:59:41 +0000535}
536
bsalomonc49e8682015-06-30 11:37:35 -0700537void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800538 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800539 RETURN_IF_ABANDONED
bsalomon87a94eb2014-11-03 14:28:32 -0800540 SkASSERT(surface);
541 ASSERT_OWNED_RESOURCE(surface);
bsalomon6a2b1942016-09-08 11:28:59 -0700542 fDrawingManager->prepareSurfaceForExternalIO(surface);
bsalomon@google.com75f9f252012-01-31 13:35:56 +0000543}
544
bsalomonf80bfed2014-10-07 05:56:02 -0700545void GrContext::flushSurfaceWrites(GrSurface* surface) {
joshualitt1de610a2016-01-06 08:26:09 -0800546 ASSERT_SINGLE_OWNER
joshualitt5f5a8d72015-02-25 14:09:45 -0800547 RETURN_IF_ABANDONED
bsalomonf80bfed2014-10-07 05:56:02 -0700548 if (surface->surfacePriv().hasPendingWrite()) {
549 this->flush();
550 }
551}
552
ajuma95243eb2016-08-24 08:19:02 -0700553void GrContext::flushSurfaceIO(GrSurface* surface) {
554 ASSERT_SINGLE_OWNER
555 RETURN_IF_ABANDONED
556 if (surface->surfacePriv().hasPendingIO()) {
557 this->flush();
558 }
559}
560
bsalomon@google.com27847de2011-02-22 20:59:41 +0000561////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000562int GrContext::getRecommendedSampleCount(GrPixelConfig config,
563 SkScalar dpi) const {
joshualitt1de610a2016-01-06 08:26:09 -0800564 ASSERT_SINGLE_OWNER
565
bsalomon76228632015-05-29 08:02:10 -0700566 if (!this->caps()->isConfigRenderable(config, true)) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000567 return 0;
568 }
569 int chosenSampleCount = 0;
jvanverthe9c0fc62015-04-29 11:18:05 -0700570 if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000571 if (dpi >= 250.0f) {
572 chosenSampleCount = 4;
573 } else {
574 chosenSampleCount = 16;
575 }
576 }
egdanieleed519e2016-01-15 11:36:18 -0800577 return chosenSampleCount <= fGpu->caps()->maxSampleCount() ? chosenSampleCount : 0;
commit-bot@chromium.orgb471a322014-03-10 07:40:03 +0000578}
579
Brian Osman11052242016-10-27 14:47:55 -0400580sk_sp<GrRenderTargetContext> GrContextPriv::makeWrappedRenderTargetContext(
581 sk_sp<GrRenderTarget> rt,
582 sk_sp<SkColorSpace> colorSpace,
583 const SkSurfaceProps* surfaceProps) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700584 ASSERT_SINGLE_OWNER_PRIV
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400585
Robert Phillips37430132016-11-09 06:50:43 -0500586 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500587 if (!proxy) {
588 return nullptr;
589 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400590
Robert Phillips37430132016-11-09 06:50:43 -0500591 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400592 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400593 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700594}
robertphillips77a2e522015-10-17 07:43:27 -0700595
Robert Phillips2c862492017-01-18 10:08:39 -0500596sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurfaceProxy> proxy,
597 sk_sp<SkColorSpace> colorSpace) {
Brian Osman45580d32016-11-23 09:37:01 -0500598 ASSERT_SINGLE_OWNER_PRIV
599
Brian Osman45580d32016-11-23 09:37:01 -0500600 if (proxy->asRenderTargetProxy()) {
Robert Phillips2c862492017-01-18 10:08:39 -0500601 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
602 std::move(colorSpace), nullptr);
Brian Osman45580d32016-11-23 09:37:01 -0500603 } else {
604 SkASSERT(proxy->asTextureProxy());
Robert Phillips2c862492017-01-18 10:08:39 -0500605 return this->drawingManager()->makeTextureContext(std::move(proxy), std::move(colorSpace));
Brian Osman45580d32016-11-23 09:37:01 -0500606 }
607}
608
Robert Phillips31c26082016-12-14 15:12:15 -0500609sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface> surface) {
610 ASSERT_SINGLE_OWNER_PRIV
611
612 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500613 if (!proxy) {
614 return nullptr;
615 }
Robert Phillips31c26082016-12-14 15:12:15 -0500616
Robert Phillips2c862492017-01-18 10:08:39 -0500617 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr);
Robert Phillips31c26082016-12-14 15:12:15 -0500618}
619
Robert Phillipse2f7d182016-12-15 09:23:05 -0500620sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
621 SkBackingFit fit,
622 SkBudgeted isDstBudgeted) {
623
Brian Osman32342f02017-03-04 08:12:46 -0500624 sk_sp<GrTextureProxy> proxy = GrSurfaceProxy::MakeDeferred(fContext->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400625 dstDesc, fit, isDstBudgeted);
Robert Phillips77b3f322017-01-31 18:24:12 -0500626 if (!proxy) {
627 return nullptr;
628 }
Robert Phillipse2f7d182016-12-15 09:23:05 -0500629
Robert Phillips2c862492017-01-18 10:08:39 -0500630 return this->makeWrappedSurfaceContext(std::move(proxy), nullptr);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500631}
632
Robert Phillips26caf892017-01-27 10:58:31 -0500633sk_sp<GrSurfaceContext> GrContextPriv::makeBackendSurfaceContext(const GrBackendTextureDesc& desc,
Brian Osmanc1e37052017-03-09 14:19:20 -0500634 sk_sp<SkColorSpace> colorSpace) {
Robert Phillips26caf892017-01-27 10:58:31 -0500635 ASSERT_SINGLE_OWNER_PRIV
636
Brian Osmanc1e37052017-03-09 14:19:20 -0500637 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc));
Robert Phillips26caf892017-01-27 10:58:31 -0500638 if (!surface) {
639 return nullptr;
640 }
641
642 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500643 if (!proxy) {
644 return nullptr;
645 }
Robert Phillips26caf892017-01-27 10:58:31 -0500646
647 return this->makeWrappedSurfaceContext(std::move(proxy), std::move(colorSpace));
648}
649
Brian Osman11052242016-10-27 14:47:55 -0400650sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
Robert Phillipse305cc1f2016-12-14 12:19:05 -0500651 const GrBackendTextureDesc& desc,
Brian Osman11052242016-10-27 14:47:55 -0400652 sk_sp<SkColorSpace> colorSpace,
Brian Osmanc1e37052017-03-09 14:19:20 -0500653 const SkSurfaceProps* props) {
robertphillips4fd74ae2016-08-03 14:26:53 -0700654 ASSERT_SINGLE_OWNER_PRIV
655 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
656
Brian Osmanc1e37052017-03-09 14:19:20 -0500657 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTexture(desc));
robertphillips4fd74ae2016-08-03 14:26:53 -0700658 if (!surface) {
659 return nullptr;
660 }
661
Robert Phillips37430132016-11-09 06:50:43 -0500662 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500663 if (!proxy) {
664 return nullptr;
665 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400666
Robert Phillips37430132016-11-09 06:50:43 -0500667 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Brian Osman11052242016-10-27 14:47:55 -0400668 std::move(colorSpace), props);
robertphillips4fd74ae2016-08-03 14:26:53 -0700669}
670
Brian Osman11052242016-10-27 14:47:55 -0400671sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendRenderTargetRenderTargetContext(
robertphillips4fd74ae2016-08-03 14:26:53 -0700672 const GrBackendRenderTargetDesc& desc,
673 sk_sp<SkColorSpace> colorSpace,
674 const SkSurfaceProps* surfaceProps) {
675 ASSERT_SINGLE_OWNER_PRIV
676
Brian Osman32342f02017-03-04 08:12:46 -0500677 sk_sp<GrRenderTarget> rt(fContext->resourceProvider()->wrapBackendRenderTarget(desc));
robertphillips4fd74ae2016-08-03 14:26:53 -0700678 if (!rt) {
679 return nullptr;
680 }
681
Robert Phillips37430132016-11-09 06:50:43 -0500682 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(rt)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500683 if (!proxy) {
684 return nullptr;
685 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400686
Robert Phillips37430132016-11-09 06:50:43 -0500687 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400688 std::move(colorSpace),
Brian Osman11052242016-10-27 14:47:55 -0400689 surfaceProps);
robertphillips4fd74ae2016-08-03 14:26:53 -0700690}
691
Brian Osman11052242016-10-27 14:47:55 -0400692sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureAsRenderTargetRenderTargetContext(
egdaniela95d46b2016-08-15 08:06:29 -0700693 const GrBackendTextureDesc& desc,
robertphillips4fd74ae2016-08-03 14:26:53 -0700694 sk_sp<SkColorSpace> colorSpace,
695 const SkSurfaceProps* surfaceProps) {
696 ASSERT_SINGLE_OWNER_PRIV
697 SkASSERT(desc.fFlags & kRenderTarget_GrBackendTextureFlag);
698
699 sk_sp<GrSurface> surface(fContext->resourceProvider()->wrapBackendTextureAsRenderTarget(desc));
700 if (!surface) {
701 return nullptr;
702 }
703
Robert Phillips37430132016-11-09 06:50:43 -0500704 sk_sp<GrSurfaceProxy> proxy(GrSurfaceProxy::MakeWrapped(std::move(surface)));
Robert Phillips77b3f322017-01-31 18:24:12 -0500705 if (!proxy) {
706 return nullptr;
707 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400708
Robert Phillips37430132016-11-09 06:50:43 -0500709 return this->drawingManager()->makeRenderTargetContext(std::move(proxy),
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400710 std::move(colorSpace),
711 surfaceProps);
robertphillips77a2e522015-10-17 07:43:27 -0700712}
713
robertphillips48fde9c2016-09-06 05:20:20 -0700714static inline GrPixelConfig GrPixelConfigFallback(GrPixelConfig config) {
Brian Osman78f20e02017-01-12 10:28:01 -0500715 switch (config) {
716 case kAlpha_8_GrPixelConfig:
717 case kRGB_565_GrPixelConfig:
718 case kRGBA_4444_GrPixelConfig:
719 case kBGRA_8888_GrPixelConfig:
720 return kRGBA_8888_GrPixelConfig;
721 case kSBGRA_8888_GrPixelConfig:
722 return kSRGBA_8888_GrPixelConfig;
723 case kAlpha_half_GrPixelConfig:
724 return kRGBA_half_GrPixelConfig;
725 default:
726 return kUnknown_GrPixelConfig;
727 }
robertphillips48fde9c2016-09-06 05:20:20 -0700728}
729
Brian Osman11052242016-10-27 14:47:55 -0400730sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContextWithFallback(
731 SkBackingFit fit,
732 int width, int height,
733 GrPixelConfig config,
734 sk_sp<SkColorSpace> colorSpace,
735 int sampleCnt,
736 GrSurfaceOrigin origin,
737 const SkSurfaceProps* surfaceProps,
738 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700739 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
740 config = GrPixelConfigFallback(config);
741 }
742
Brian Osman11052242016-10-27 14:47:55 -0400743 return this->makeRenderTargetContext(fit, width, height, config, std::move(colorSpace),
744 sampleCnt, origin, surfaceProps, budgeted);
robertphillips48fde9c2016-09-06 05:20:20 -0700745}
746
robertphillipsd728f0c2016-11-21 11:05:03 -0800747sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContextWithFallback(
748 SkBackingFit fit,
749 int width, int height,
750 GrPixelConfig config,
751 sk_sp<SkColorSpace> colorSpace,
752 int sampleCnt,
753 GrSurfaceOrigin origin,
754 const SkSurfaceProps* surfaceProps,
755 SkBudgeted budgeted) {
756 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
757 config = GrPixelConfigFallback(config);
758 }
759
760 return this->makeDeferredRenderTargetContext(fit, width, height, config, std::move(colorSpace),
761 sampleCnt, origin, surfaceProps, budgeted);
762}
763
Brian Osman11052242016-10-27 14:47:55 -0400764sk_sp<GrRenderTargetContext> GrContext::makeRenderTargetContext(SkBackingFit fit,
765 int width, int height,
766 GrPixelConfig config,
767 sk_sp<SkColorSpace> colorSpace,
768 int sampleCnt,
769 GrSurfaceOrigin origin,
770 const SkSurfaceProps* surfaceProps,
771 SkBudgeted budgeted) {
robertphillips48fde9c2016-09-06 05:20:20 -0700772 if (!this->caps()->isConfigRenderable(config, sampleCnt > 0)) {
773 return nullptr;
774 }
775
robertphillipsd4c741e2016-04-28 09:55:15 -0700776 GrSurfaceDesc desc;
777 desc.fFlags = kRenderTarget_GrSurfaceFlag;
778 desc.fOrigin = origin;
779 desc.fWidth = width;
780 desc.fHeight = height;
781 desc.fConfig = config;
782 desc.fSampleCnt = sampleCnt;
783
784 sk_sp<GrTexture> tex;
robertphillips76948d42016-05-04 12:47:41 -0700785 if (SkBackingFit::kExact == fit) {
Brian Osman32342f02017-03-04 08:12:46 -0500786 tex.reset(this->resourceProvider()->createTexture(desc, budgeted));
robertphillipsd4c741e2016-04-28 09:55:15 -0700787 } else {
Brian Osman32342f02017-03-04 08:12:46 -0500788 tex.reset(this->resourceProvider()->createApproxTexture(desc, 0));
robertphillipsd4c741e2016-04-28 09:55:15 -0700789 }
790 if (!tex) {
791 return nullptr;
792 }
793
Brian Osman11052242016-10-27 14:47:55 -0400794 sk_sp<GrRenderTargetContext> renderTargetContext(
795 this->contextPriv().makeWrappedRenderTargetContext(sk_ref_sp(tex->asRenderTarget()),
robertphillips6738c702016-07-27 12:13:51 -0700796 std::move(colorSpace), surfaceProps));
Brian Osman11052242016-10-27 14:47:55 -0400797 if (!renderTargetContext) {
robertphillipsd4c741e2016-04-28 09:55:15 -0700798 return nullptr;
799 }
800
Brian Osman11052242016-10-27 14:47:55 -0400801 return renderTargetContext;
robertphillipsd4c741e2016-04-28 09:55:15 -0700802}
803
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400804sk_sp<GrRenderTargetContext> GrContext::makeDeferredRenderTargetContext(
805 SkBackingFit fit,
806 int width, int height,
807 GrPixelConfig config,
808 sk_sp<SkColorSpace> colorSpace,
809 int sampleCnt,
810 GrSurfaceOrigin origin,
811 const SkSurfaceProps* surfaceProps,
812 SkBudgeted budgeted) {
813 GrSurfaceDesc desc;
814 desc.fFlags = kRenderTarget_GrSurfaceFlag;
815 desc.fOrigin = origin;
816 desc.fWidth = width;
817 desc.fHeight = height;
818 desc.fConfig = config;
819 desc.fSampleCnt = sampleCnt;
820
Brian Osman32342f02017-03-04 08:12:46 -0500821 sk_sp<GrTextureProxy> rtp = GrSurfaceProxy::MakeDeferred(this->resourceProvider(),
Robert Phillips26c90e02017-03-14 14:39:29 -0400822 desc, fit, budgeted);
Robert Phillips08c5ec72017-01-30 12:26:47 -0500823 if (!rtp) {
824 return nullptr;
825 }
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400826
827 return fDrawingManager->makeRenderTargetContext(std::move(rtp),
828 std::move(colorSpace),
829 surfaceProps);
830}
831
joshualitt1de610a2016-01-06 08:26:09 -0800832bool GrContext::abandoned() const {
833 ASSERT_SINGLE_OWNER
robertphillips7761d612016-05-16 09:14:53 -0700834 return fDrawingManager->wasAbandoned();
robertphillips77a2e522015-10-17 07:43:27 -0700835}
836
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000837namespace {
838void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
839 GrConfigConversionEffect::PMConversion pmToUPM;
840 GrConfigConversionEffect::PMConversion upmToPM;
841 GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
842 *pmToUPMValue = pmToUPM;
843 *upmToPMValue = upmToPM;
844}
845}
846
bsalomon6c6f6582015-09-10 08:12:46 -0700847void GrContext::testPMConversionsIfNecessary(uint32_t flags) {
joshualitt1de610a2016-01-06 08:26:09 -0800848 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700849 if (SkToBool(kUnpremul_PixelOpsFlag & flags)) {
bsalomon6c6f6582015-09-10 08:12:46 -0700850 if (!fDidTestPMConversions) {
851 test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
852 fDidTestPMConversions = true;
853 }
854 }
855}
856
bungeman06ca8ec2016-06-09 08:01:03 -0700857sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(GrTexture* texture,
bsalomon6c9cd552016-01-22 07:17:34 -0800858 const GrSwizzle& swizzle,
Robert Phillips757914d2017-01-25 15:48:30 -0500859 const SkMatrix& matrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800860 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700861 // We should have already called this->testPMConversionsIfNecessary().
862 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000863 GrConfigConversionEffect::PMConversion pmToUPM =
864 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
865 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
bungeman06ca8ec2016-06-09 08:01:03 -0700866 return GrConfigConversionEffect::Make(texture, swizzle, pmToUPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000867 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700868 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000869 }
870}
871
Robert Phillips757914d2017-01-25 15:48:30 -0500872sk_sp<GrFragmentProcessor> GrContext::createPMToUPMEffect(sk_sp<GrTextureProxy> proxy,
bsalomon6c9cd552016-01-22 07:17:34 -0800873 const GrSwizzle& swizzle,
Robert Phillips757914d2017-01-25 15:48:30 -0500874 const SkMatrix& matrix) {
875 ASSERT_SINGLE_OWNER
876 // We should have already called this->testPMConversionsIfNecessary().
877 SkASSERT(fDidTestPMConversions);
878 GrConfigConversionEffect::PMConversion pmToUPM =
879 static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
880 if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
Robert Phillips296b1cc2017-03-15 10:42:12 -0400881 return GrConfigConversionEffect::Make(this->resourceProvider(),
882 proxy, swizzle, pmToUPM, matrix);
Robert Phillips757914d2017-01-25 15:48:30 -0500883 } else {
884 return nullptr;
885 }
886}
887
888sk_sp<GrFragmentProcessor> GrContext::createUPMToPMEffect(sk_sp<GrTextureProxy> proxy,
889 const GrSwizzle& swizzle,
890 const SkMatrix& matrix) {
joshualitt1de610a2016-01-06 08:26:09 -0800891 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700892 // We should have already called this->testPMConversionsIfNecessary().
893 SkASSERT(fDidTestPMConversions);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000894 GrConfigConversionEffect::PMConversion upmToPM =
895 static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
896 if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
Robert Phillips296b1cc2017-03-15 10:42:12 -0400897 return GrConfigConversionEffect::Make(this->resourceProvider(),
898 std::move(proxy), swizzle, upmToPM, matrix);
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000899 } else {
halcanary96fcdcc2015-08-27 07:41:13 -0700900 return nullptr;
bsalomon@google.coma04e8e82012-08-27 12:53:13 +0000901 }
902}
903
bsalomon636e8022015-07-29 06:08:46 -0700904bool GrContext::didFailPMUPMConversionTest() const {
joshualitt1de610a2016-01-06 08:26:09 -0800905 ASSERT_SINGLE_OWNER
bsalomon6c6f6582015-09-10 08:12:46 -0700906 // We should have already called this->testPMConversionsIfNecessary().
907 SkASSERT(fDidTestPMConversions);
bsalomon636e8022015-07-29 06:08:46 -0700908 // The PM<->UPM tests fail or succeed together so we only need to check one.
bsalomon6c6f6582015-09-10 08:12:46 -0700909 return GrConfigConversionEffect::kNone_PMConversion == fPMToUPMConversion;
bsalomon636e8022015-07-29 06:08:46 -0700910}
911
bsalomon37f9a262015-02-02 13:00:10 -0800912//////////////////////////////////////////////////////////////////////////////
913
914void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
joshualitt1de610a2016-01-06 08:26:09 -0800915 ASSERT_SINGLE_OWNER
bsalomon37f9a262015-02-02 13:00:10 -0800916 if (maxTextures) {
bsalomon0ea80f42015-02-11 10:49:59 -0800917 *maxTextures = fResourceCache->getMaxResourceCount();
bsalomon37f9a262015-02-02 13:00:10 -0800918 }
919 if (maxTextureBytes) {
bsalomon0ea80f42015-02-11 10:49:59 -0800920 *maxTextureBytes = fResourceCache->getMaxResourceBytes();
bsalomon37f9a262015-02-02 13:00:10 -0800921 }
922}
923
924void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
joshualitt1de610a2016-01-06 08:26:09 -0800925 ASSERT_SINGLE_OWNER
bsalomon0ea80f42015-02-11 10:49:59 -0800926 fResourceCache->setLimits(maxTextures, maxTextureBytes);
bsalomon37f9a262015-02-02 13:00:10 -0800927}
928
ericrk0a5fa482015-09-15 14:16:10 -0700929//////////////////////////////////////////////////////////////////////////////
930
931void GrContext::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
joshualitt1de610a2016-01-06 08:26:09 -0800932 ASSERT_SINGLE_OWNER
ericrk0a5fa482015-09-15 14:16:10 -0700933 fResourceCache->dumpMemoryStatistics(traceMemoryDump);
934}