blob: 2abefc8bc0078c615a235094e05ce7d334fc0f9d [file] [log] [blame]
robertphillips76948d42016-05-04 12:47:41 -07001/*
2 * Copyright 2016 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.
6 */
7
Greg Danielf91aeb22019-06-18 09:58:02 -04008#include "src/gpu/GrSurfaceProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -05009#include "src/gpu/GrSurfaceProxyPriv.h"
robertphillips76948d42016-05-04 12:47:41 -070010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/gpu/GrContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/private/GrRecordingContext.h"
Brian Salomon947efe22019-07-16 15:36:11 -040013#include "src/core/SkMathPriv.h"
14#include "src/core/SkMipMap.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrCaps.h"
Greg Daniel46cfbc62019-06-07 11:43:30 -040016#include "src/gpu/GrClip.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050017#include "src/gpu/GrContextPriv.h"
18#include "src/gpu/GrGpuResourcePriv.h"
Greg Danielf41b2bd2019-08-22 16:19:24 -040019#include "src/gpu/GrOpsTask.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrProxyProvider.h"
21#include "src/gpu/GrRecordingContextPriv.h"
Chris Daltoneffee202019-07-01 22:28:03 -060022#include "src/gpu/GrStencilAttachment.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/gpu/GrSurfacePriv.h"
Brian Salomon947efe22019-07-16 15:36:11 -040024#include "src/gpu/GrTextureContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrTexturePriv.h"
26#include "src/gpu/GrTextureRenderTargetProxy.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040027
Greg Daniel65fa8ca2018-01-10 17:06:31 -050028#ifdef SK_DEBUG
Brian Salomon201cdbb2019-08-14 17:00:30 -040029#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "src/gpu/GrRenderTargetPriv.h"
Robert Phillipsc7c2baf2018-03-08 09:51:04 -050031
Brian Salomon1d19da02019-09-11 17:39:30 -040032static bool is_valid_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
33 // A "fully" lazy proxy's width and height are not known until instantiation time.
34 // So fully lazy proxies are created with width and height < 0. Regular lazy proxies must be
35 // created with positive widths and heights. The width and height are set to 0 only after a
36 // failed instantiation. The former must be "approximate" fit while the latter can be either.
37 return desc.fConfig != kUnknown_GrPixelConfig &&
38 ((desc.fWidth < 0 && desc.fHeight < 0 && SkBackingFit::kApprox == fit) ||
39 (desc.fWidth > 0 && desc.fHeight > 0));
Greg Daniel65fa8ca2018-01-10 17:06:31 -050040}
41
42static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
Brian Salomon1d19da02019-09-11 17:39:30 -040043 return desc.fWidth > 0 && desc.fHeight > 0 && desc.fConfig != kUnknown_GrPixelConfig;
Greg Daniel65fa8ca2018-01-10 17:06:31 -050044}
45#endif
46
Brian Salomonbeb7f522019-08-30 16:19:42 -040047// Deferred version
48GrSurfaceProxy::GrSurfaceProxy(const GrBackendFormat& format,
49 const GrSurfaceDesc& desc,
50 GrRenderable renderable,
51 GrSurfaceOrigin origin,
52 const GrSwizzle& textureSwizzle,
53 SkBackingFit fit,
54 SkBudgeted budgeted,
55 GrProtected isProtected,
56 GrInternalSurfaceFlags surfaceFlags,
57 UseAllocator useAllocator)
Greg Daniele3204862018-04-16 11:24:10 -040058 : fSurfaceFlags(surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -050059 , fFormat(format)
Greg Daniele3204862018-04-16 11:24:10 -040060 , fConfig(desc.fConfig)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050061 , fWidth(desc.fWidth)
62 , fHeight(desc.fHeight)
Brian Salomon2a4f9832018-03-03 22:43:43 -050063 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040064 , fTextureSwizzle(textureSwizzle)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050065 , fFit(fit)
66 , fBudgeted(budgeted)
Brian Salomonbeb7f522019-08-30 16:19:42 -040067 , fUseAllocator(useAllocator)
Brian Salomone8a766b2019-07-19 14:24:36 -040068 , fIsProtected(isProtected)
Brian Salomonbeb7f522019-08-30 16:19:42 -040069 , fGpuMemorySize(kInvalidGpuMemorySize) {
Greg Daniel4065d452018-11-16 15:43:41 -050070 SkASSERT(fFormat.isValid());
Brian Salomonbeb7f522019-08-30 16:19:42 -040071 SkASSERT(is_valid_non_lazy(desc));
72 if (GrPixelConfigIsCompressed(desc.fConfig)) {
73 SkASSERT(renderable == GrRenderable::kNo);
74 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
Greg Daniel65fa8ca2018-01-10 17:06:31 -050075 }
Brian Salomonbeb7f522019-08-30 16:19:42 -040076}
Jim Van Verth1676cb92019-01-15 13:24:45 -050077
Brian Salomonbeb7f522019-08-30 16:19:42 -040078// Lazy-callback version
79GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback,
80 const GrBackendFormat& format,
81 const GrSurfaceDesc& desc,
82 GrRenderable renderable,
83 GrSurfaceOrigin origin,
84 const GrSwizzle& textureSwizzle,
85 SkBackingFit fit,
86 SkBudgeted budgeted,
87 GrProtected isProtected,
88 GrInternalSurfaceFlags surfaceFlags,
89 UseAllocator useAllocator)
90 : fSurfaceFlags(surfaceFlags)
91 , fFormat(format)
92 , fConfig(desc.fConfig)
93 , fWidth(desc.fWidth)
94 , fHeight(desc.fHeight)
95 , fOrigin(origin)
96 , fTextureSwizzle(textureSwizzle)
97 , fFit(fit)
98 , fBudgeted(budgeted)
99 , fUseAllocator(useAllocator)
100 , fLazyInstantiateCallback(std::move(callback))
101 , fIsProtected(isProtected)
102 , fGpuMemorySize(kInvalidGpuMemorySize) {
103 SkASSERT(fFormat.isValid());
104 SkASSERT(fLazyInstantiateCallback);
Brian Salomon1d19da02019-09-11 17:39:30 -0400105 SkASSERT(is_valid_lazy(desc, fit));
Jim Van Verth1676cb92019-01-15 13:24:45 -0500106 if (GrPixelConfigIsCompressed(desc.fConfig)) {
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400107 SkASSERT(renderable == GrRenderable::kNo);
Jim Van Verth1676cb92019-01-15 13:24:45 -0500108 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
109 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700110}
111
112// Wrapped version
Brian Salomonbeb7f522019-08-30 16:19:42 -0400113GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface,
114 GrSurfaceOrigin origin,
115 const GrSwizzle& textureSwizzle,
116 SkBackingFit fit,
117 UseAllocator useAllocator)
Robert Phillipsb5204762019-06-19 14:12:13 -0400118 : fTarget(std::move(surface))
Greg Daniele3204862018-04-16 11:24:10 -0400119 , fSurfaceFlags(fTarget->surfacePriv().flags())
Greg Daniel4065d452018-11-16 15:43:41 -0500120 , fFormat(fTarget->backendFormat())
Brian Salomonbb5711a2017-05-17 13:49:59 -0400121 , fConfig(fTarget->config())
122 , fWidth(fTarget->width())
123 , fHeight(fTarget->height())
Robert Phillips066f0202017-07-25 10:16:35 -0400124 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400125 , fTextureSwizzle(textureSwizzle)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400126 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500127 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
128 ? SkBudgeted::kYes
129 : SkBudgeted::kNo)
Brian Salomonbeb7f522019-08-30 16:19:42 -0400130 , fUseAllocator(useAllocator)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400131 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400132 , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
Brian Salomonbeb7f522019-08-30 16:19:42 -0400133 , fGpuMemorySize(kInvalidGpuMemorySize) {
Greg Daniel4065d452018-11-16 15:43:41 -0500134 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400135}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400136
Robert Phillipsf2361d22016-10-25 14:20:06 -0400137GrSurfaceProxy::~GrSurfaceProxy() {
Greg Danielf41b2bd2019-08-22 16:19:24 -0400138 // For this to be deleted the opsTask that held a ref on it (if there was one) must have been
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400139 // deleted. Which would have cleared out this back pointer.
Chris Dalton6b498102019-08-01 14:14:52 -0600140 SkASSERT(!fLastRenderTask);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400141}
142
Robert Phillipseafd48a2017-11-16 07:52:08 -0500143bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
Chris Daltoneffee202019-07-01 22:28:03 -0600144 GrSurface* surface, int minStencilSampleCount) {
145 if (minStencilSampleCount) {
Robert Phillips65048132017-08-10 08:44:49 -0400146 GrRenderTarget* rt = surface->asRenderTarget();
147 if (!rt) {
148 SkASSERT(0);
149 return false;
150 }
151
Chris Daltoneffee202019-07-01 22:28:03 -0600152 if (!resourceProvider->attachStencilAttachment(rt, minStencilSampleCount)) {
Robert Phillips65048132017-08-10 08:44:49 -0400153 return false;
154 }
155 }
156
157 return true;
158}
159
Robert Phillipsba5c4392018-07-25 12:37:14 -0400160sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400161 int sampleCnt,
162 int minStencilSampleCount,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400163 GrRenderable renderable,
Robert Phillips10d17212019-04-24 14:09:10 -0400164 GrMipMapped mipMapped) const {
Brian Salomona90382f2019-09-17 09:01:56 -0400165 SkASSERT(mipMapped == GrMipMapped::kNo || fFit == SkBackingFit::kExact);
Brian Salomonbeb7f522019-08-30 16:19:42 -0400166 SkASSERT(!this->isLazy());
Greg Danield2d8e922018-02-12 12:07:39 -0500167 SkASSERT(!fTarget);
Brian Salomonbb5711a2017-05-17 13:49:59 -0400168 GrSurfaceDesc desc;
Robert Phillips16d8ec62017-07-27 16:16:25 -0400169 desc.fWidth = fWidth;
170 desc.fHeight = fHeight;
171 desc.fConfig = fConfig;
Robert Phillipseaa86252016-11-08 13:49:39 +0000172
Robert Phillips5af44de2017-07-18 14:49:38 -0400173 sk_sp<GrSurface> surface;
Brian Salomona90382f2019-09-17 09:01:56 -0400174 if (SkBackingFit::kApprox == fFit) {
175 surface = resourceProvider->createApproxTexture(desc, fFormat, renderable, sampleCnt,
176 fIsProtected);
Robert Phillipseaa86252016-11-08 13:49:39 +0000177 } else {
Brian Salomona90382f2019-09-17 09:01:56 -0400178 surface = resourceProvider->createTexture(desc, fFormat, renderable, sampleCnt, mipMapped,
179 fBudgeted, fIsProtected);
Robert Phillipseaa86252016-11-08 13:49:39 +0000180 }
Robert Phillips65048132017-08-10 08:44:49 -0400181 if (!surface) {
182 return nullptr;
183 }
184
Robert Phillipse5f73282019-06-18 17:15:04 -0400185 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(),
Chris Daltoneffee202019-07-01 22:28:03 -0600186 minStencilSampleCount)) {
Robert Phillips65048132017-08-10 08:44:49 -0400187 return nullptr;
Robert Phillipseaa86252016-11-08 13:49:39 +0000188 }
189
Robert Phillips5af44de2017-07-18 14:49:38 -0400190 return surface;
191}
192
Brian Salomon7d94bb52018-10-12 14:37:19 -0400193bool GrSurfaceProxy::canSkipResourceAllocator() const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400194 if (fUseAllocator == UseAllocator::kNo) {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400195 // Usually an atlas or onFlush proxy
196 return true;
197 }
198
Brian Salomon7d94bb52018-10-12 14:37:19 -0400199 auto peek = this->peekSurface();
200 if (!peek) {
201 return false;
202 }
203 // If this resource is already allocated and not recyclable then the resource allocator does
204 // not need to do anything with it.
205 return !peek->resourcePriv().getScratchKey().isValid();
206}
207
Robert Phillips5af44de2017-07-18 14:49:38 -0400208void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
209 SkASSERT(!fTarget && surface);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400210
Greg Daniel849dce12018-04-24 14:32:53 -0400211 SkDEBUGCODE(this->validateSurface(surface.get());)
Robert Phillipsabf7b762018-03-21 12:13:37 -0400212
Robert Phillipse5f73282019-06-18 17:15:04 -0400213 fTarget = std::move(surface);
robertphillips1125a032016-11-16 11:17:17 -0800214
Robert Phillipseaa86252016-11-08 13:49:39 +0000215#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500216 if (this->asRenderTargetProxy()) {
217 SkASSERT(fTarget->asRenderTarget());
Chris Daltoneffee202019-07-01 22:28:03 -0600218 if (int minStencilSampleCount = this->asRenderTargetProxy()->numStencilSamples()) {
219 auto* stencil = fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment();
220 SkASSERT(stencil);
221 SkASSERT(stencil->numSamples() >= minStencilSampleCount);
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500222 }
223 }
224
Robert Phillipseaa86252016-11-08 13:49:39 +0000225 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500226 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +0000227 }
228#endif
Robert Phillips5af44de2017-07-18 14:49:38 -0400229}
Robert Phillipseaa86252016-11-08 13:49:39 +0000230
Robert Phillips5af44de2017-07-18 14:49:38 -0400231bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400232 int minStencilSampleCount, GrRenderable renderable,
Robert Phillips10d17212019-04-24 14:09:10 -0400233 GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400234 SkASSERT(!this->isLazy());
Robert Phillips5af44de2017-07-18 14:49:38 -0400235 if (fTarget) {
Brian Salomon57904202018-12-17 14:45:00 -0500236 if (uniqueKey && uniqueKey->isValid()) {
237 SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400238 }
Robert Phillipse5f73282019-06-18 17:15:04 -0400239 return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget.get(),
Chris Daltoneffee202019-07-01 22:28:03 -0600240 minStencilSampleCount);
Robert Phillips5af44de2017-07-18 14:49:38 -0400241 }
242
Chris Daltoneffee202019-07-01 22:28:03 -0600243 sk_sp<GrSurface> surface = this->createSurfaceImpl(
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400244 resourceProvider, sampleCnt, minStencilSampleCount, renderable, mipMapped);
Robert Phillips5af44de2017-07-18 14:49:38 -0400245 if (!surface) {
246 return false;
247 }
248
Brian Osman28c434b2017-09-27 13:11:16 -0400249 // If there was an invalidation message pending for this key, we might have just processed it,
250 // causing the key (stored on this proxy) to become invalid.
251 if (uniqueKey && uniqueKey->isValid()) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400252 resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
253 }
254
Robert Phillips5af44de2017-07-18 14:49:38 -0400255 this->assign(std::move(surface));
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400256
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400257 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +0000258}
259
Brian Salomon967df202018-12-07 11:15:53 -0500260void GrSurfaceProxy::deinstantiate() {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400261 SkASSERT(this->isInstantiated());
Robert Phillipse5f73282019-06-18 17:15:04 -0400262 fTarget = nullptr;
Robert Phillips4bc70112018-03-01 10:24:02 -0500263}
264
Robert Phillips57aa3672017-07-21 11:38:13 -0400265void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400266 SkASSERT(!this->isFullyLazy());
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400267 GrRenderable renderable = GrRenderable::kNo;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500268 int sampleCount = 1;
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400269 if (const auto* rtp = this->asRenderTargetProxy()) {
270 renderable = GrRenderable::kYes;
Chris Dalton6ce447a2019-06-23 18:07:38 -0600271 sampleCount = rtp->numSamples();
Robert Phillips57aa3672017-07-21 11:38:13 -0400272 }
273
274 const GrTextureProxy* tp = this->asTextureProxy();
Greg Daniele252f082017-10-23 16:05:23 -0400275 GrMipMapped mipMapped = GrMipMapped::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400276 if (tp) {
Greg Daniele252f082017-10-23 16:05:23 -0400277 mipMapped = tp->mipMapped();
Robert Phillips57aa3672017-07-21 11:38:13 -0400278 }
279
Robert Phillipsa108c922017-10-10 10:42:19 -0400280 int width = this->worstCaseWidth();
281 int height = this->worstCaseHeight();
Robert Phillips57aa3672017-07-21 11:38:13 -0400282
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400283 GrTexturePriv::ComputeScratchKey(this->config(), width, height, renderable, sampleCount,
Brian Salomon14cb4132019-09-16 13:14:47 -0400284 mipMapped, fIsProtected, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400285}
286
Chris Dalton6b498102019-08-01 14:14:52 -0600287void GrSurfaceProxy::setLastRenderTask(GrRenderTask* renderTask) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400288#ifdef SK_DEBUG
Chris Dalton6b498102019-08-01 14:14:52 -0600289 if (fLastRenderTask) {
290 SkASSERT(fLastRenderTask->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +0000291 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400292#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -0400293
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400294 // Un-reffed
Chris Dalton6b498102019-08-01 14:14:52 -0600295 fLastRenderTask = renderTask;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400296}
Robert Phillips37430132016-11-09 06:50:43 -0500297
Greg Danielf41b2bd2019-08-22 16:19:24 -0400298GrOpsTask* GrSurfaceProxy::getLastOpsTask() {
299 return fLastRenderTask ? fLastRenderTask->asOpsTask() : nullptr;
Brian Osman45580d32016-11-23 09:37:01 -0500300}
301
Robert Phillipsa108c922017-10-10 10:42:19 -0400302int GrSurfaceProxy::worstCaseWidth() const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400303 SkASSERT(!this->isFullyLazy());
Robert Phillipsa108c922017-10-10 10:42:19 -0400304 if (fTarget) {
305 return fTarget->width();
306 }
307
308 if (SkBackingFit::kExact == fFit) {
309 return fWidth;
310 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400311 return GrResourceProvider::MakeApprox(fWidth);
Robert Phillipsa108c922017-10-10 10:42:19 -0400312}
313
314int GrSurfaceProxy::worstCaseHeight() const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400315 SkASSERT(!this->isFullyLazy());
Robert Phillipsa108c922017-10-10 10:42:19 -0400316 if (fTarget) {
317 return fTarget->height();
318 }
319
320 if (SkBackingFit::kExact == fFit) {
321 return fHeight;
322 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400323 return GrResourceProvider::MakeApprox(fHeight);
Robert Phillipsa108c922017-10-10 10:42:19 -0400324}
325
Brian Osman45580d32016-11-23 09:37:01 -0500326#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500327void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500328 if (fTarget) {
329 SkASSERT(fTarget->getContext() == context);
330 }
Brian Osman45580d32016-11-23 09:37:01 -0500331}
332#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500333
Robert Phillipsd44146b2019-02-15 14:44:28 -0500334sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500335 GrSurfaceProxy* src,
Greg Daniel65c7f662017-10-30 13:39:09 -0400336 GrMipMapped mipMapped,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500337 SkIRect srcRect,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500338 SkBackingFit fit,
Greg Daniel46cfbc62019-06-07 11:43:30 -0400339 SkBudgeted budgeted,
340 RectsMustMatch rectsMustMatch) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400341 SkASSERT(!src->isFullyLazy());
Brian Salomon947efe22019-07-16 15:36:11 -0400342 GrProtected isProtected = src->isProtected() ? GrProtected::kYes : GrProtected::kNo;
343 int width;
344 int height;
Greg Daniel46cfbc62019-06-07 11:43:30 -0400345
346 SkIPoint dstPoint;
347 if (rectsMustMatch == RectsMustMatch::kYes) {
Brian Salomon947efe22019-07-16 15:36:11 -0400348 width = src->width();
349 height = src->height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400350 dstPoint = {srcRect.fLeft, srcRect.fTop};
351 } else {
Brian Salomon947efe22019-07-16 15:36:11 -0400352 width = srcRect.width();
353 height = srcRect.height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400354 dstPoint = {0, 0};
355 }
356
Robert Phillipse2f7d182016-12-15 09:23:05 -0500357 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
358 return nullptr;
359 }
Brian Salomond6287472019-06-24 15:50:07 -0400360 auto colorType = GrPixelConfigToColorType(src->config());
Greg Daniel46cfbc62019-06-07 11:43:30 -0400361 if (src->backendFormat().textureType() != GrTextureType::kExternal) {
Brian Salomonbf6b9792019-08-21 09:38:10 -0400362 auto dstContext = context->priv().makeDeferredTextureContext(
Brian Salomon947efe22019-07-16 15:36:11 -0400363 fit, width, height, colorType, kUnknown_SkAlphaType, nullptr, mipMapped,
Brian Salomonbf6b9792019-08-21 09:38:10 -0400364 src->origin(), budgeted, isProtected);
Greg Daniel46cfbc62019-06-07 11:43:30 -0400365 if (!dstContext) {
366 return nullptr;
367 }
368 if (dstContext->copy(src, srcRect, dstPoint)) {
369 return dstContext->asTextureProxyRef();
370 }
Greg Danielc5167c02019-06-05 17:36:53 +0000371 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400372 if (src->asTextureProxy()) {
Brian Salomonbf6b9792019-08-21 09:38:10 -0400373 auto dstContext = context->priv().makeDeferredRenderTargetContext(
Brian Salomon947efe22019-07-16 15:36:11 -0400374 fit, width, height, colorType, nullptr, 1, mipMapped, src->origin(), nullptr,
375 budgeted);
Greg Daniel46cfbc62019-06-07 11:43:30 -0400376
377 if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
378 return dstContext->asTextureProxyRef();
379 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400380 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400381 // Can't use backend copies or draws.
382 return nullptr;
Robert Phillips63c67462017-02-15 14:19:01 -0500383}
384
Robert Phillipsd44146b2019-02-15 14:44:28 -0500385sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500386 GrMipMapped mipMapped, SkBackingFit fit,
387 SkBudgeted budgeted) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400388 SkASSERT(!src->isFullyLazy());
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500389 return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
390 budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500391}
392
Robert Phillipsb5204762019-06-19 14:12:13 -0400393#if GR_TEST_UTILS
394int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
395 if (fTarget) {
396 return fTarget->testingOnly_getRefCnt();
397 }
398
399 return -1; // no backing GrSurface
400}
401
402GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
403 return fSurfaceFlags;
404}
405#endif
406
Robert Phillipse8976842019-08-09 08:27:26 -0400407void GrSurfaceProxyPriv::exactify(bool allocatedCaseOnly) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400408 SkASSERT(!fProxy->isFullyLazy());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400409 if (this->isExact()) {
410 return;
411 }
412
413 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
414
415 if (fProxy->fTarget) {
416 // The kApprox but already instantiated case. Setting the proxy's width & height to
417 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400418 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400419 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
420 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400421 fProxy->fWidth = fProxy->fTarget->width();
422 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400423 return;
424 }
425
Robert Phillipse8976842019-08-09 08:27:26 -0400426#ifndef SK_CRIPPLE_TEXTURE_REUSE
427 // In the post-implicit-allocation world we can't convert this proxy to be exact fit
428 // at this point. With explicit allocation switching this to exact will result in a
429 // different allocation at flush time. With implicit allocation, allocation would occur
430 // at draw time (rather than flush time) so this pathway was encountered less often (if
431 // at all).
432 if (allocatedCaseOnly) {
433 return;
434 }
435#endif
436
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400437 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
438 // It could mess things up if prior decisions were based on the approximate size.
439 fProxy->fFit = SkBackingFit::kExact;
440 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400441 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400442 // the special image goes away. If it hasn't been computed yet it might as well compute the
443 // exact amount.
444}
445
Greg Danielbddcc952018-01-24 13:22:24 -0500446bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400447 SkASSERT(fProxy->isLazy());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700448
Robert Phillips0790f8a2018-09-18 13:11:03 -0400449 sk_sp<GrSurface> surface;
450 if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
451 // First try to reattach to a cached version if the proxy is uniquely keyed
452 surface = resourceProvider->findByUniqueKey<GrSurface>(
453 fProxy->asTextureProxy()->getUniqueKey());
454 }
455
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400456 bool syncKey = true;
Brian Salomonbeb7f522019-08-30 16:19:42 -0400457 bool releaseCallback = false;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400458 if (!surface) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400459 auto result = fProxy->fLazyInstantiateCallback(resourceProvider);
460 surface = std::move(result.fSurface);
461 syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
Brian Salomonbeb7f522019-08-30 16:19:42 -0400462 releaseCallback = surface && result.fReleaseCallback;
Greg Daniel457469c2018-02-08 15:05:44 -0500463 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500464 if (!surface) {
Chris Dalton706a6ff2017-11-29 22:01:06 -0700465 fProxy->fWidth = 0;
466 fProxy->fHeight = 0;
Greg Danielbddcc952018-01-24 13:22:24 -0500467 return false;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700468 }
469
Brian Salomon1d19da02019-09-11 17:39:30 -0400470 if (fProxy->isFullyLazy()) {
Robert Phillipsc1b60662018-06-26 10:20:08 -0400471 // This was a fully lazy proxy. We need to fill in the width & height. For partially
472 // lazy proxies we must preserve the original width & height since that indicates
473 // the content area.
Robert Phillipsc1b60662018-06-26 10:20:08 -0400474 fProxy->fWidth = surface->width();
475 fProxy->fHeight = surface->height();
476 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700477
Chris Daltonf91b7552019-04-29 16:21:18 -0600478 SkASSERT(fProxy->fWidth <= surface->width());
479 SkASSERT(fProxy->fHeight <= surface->height());
480
Brian Salomonbeb7f522019-08-30 16:19:42 -0400481 auto rt = fProxy->asRenderTargetProxy();
482 int minStencilSampleCount = rt ? rt->numSamples() : 0;
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500483
Chris Daltoneffee202019-07-01 22:28:03 -0600484 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(
485 resourceProvider, surface.get(), minStencilSampleCount)) {
Robert Phillips01a91282018-07-26 08:03:04 -0400486 return false;
487 }
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500488
Greg Daniel303e83e2018-09-10 14:10:19 -0400489 if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400490 texProxy->setTargetKeySync(syncKey);
491 if (syncKey) {
492 const GrUniqueKey& key = texProxy->getUniqueKey();
493 if (key.isValid()) {
494 if (!surface->asTexture()->getUniqueKey().isValid()) {
495 // If 'surface' is newly created, attach the unique key
496 resourceProvider->assignUniqueKeyToResource(key, surface.get());
497 } else {
498 // otherwise we had better have reattached to a cached version
499 SkASSERT(surface->asTexture()->getUniqueKey() == key);
500 }
Robert Phillips0790f8a2018-09-18 13:11:03 -0400501 } else {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400502 SkASSERT(!surface->getUniqueKey().isValid());
Robert Phillips0790f8a2018-09-18 13:11:03 -0400503 }
Greg Daniel303e83e2018-09-10 14:10:19 -0400504 }
505 }
506
Robert Phillipse8fabb22018-02-04 14:33:21 -0500507 this->assign(std::move(surface));
Brian Salomonbeb7f522019-08-30 16:19:42 -0400508 if (releaseCallback) {
509 fProxy->fLazyInstantiateCallback = nullptr;
510 }
511
Greg Danielbddcc952018-01-24 13:22:24 -0500512 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700513}
514
Greg Daniel849dce12018-04-24 14:32:53 -0400515#ifdef SK_DEBUG
516void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
517 SkASSERT(surface->config() == fConfig);
518
Greg Daniel849dce12018-04-24 14:32:53 -0400519 this->onValidateSurface(surface);
520}
521#endif