blob: a82559cb499c6e8f1a6d169c1f959c5897686350 [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 Danielf91aeb22019-06-18 09:58:02 -040019#include "src/gpu/GrOpList.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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050029#include "include/gpu/GrRenderTarget.h"
30#include "src/gpu/GrRenderTargetPriv.h"
Robert Phillipsc7c2baf2018-03-08 09:51:04 -050031
Greg Daniel65fa8ca2018-01-10 17:06:31 -050032static bool is_valid_fully_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
33 return desc.fWidth <= 0 &&
34 desc.fHeight <= 0 &&
35 desc.fConfig != kUnknown_GrPixelConfig &&
Brian Salomonbdecacf2018-02-02 20:32:49 -050036 desc.fSampleCnt == 1 &&
Greg Daniel65fa8ca2018-01-10 17:06:31 -050037 SkBackingFit::kApprox == fit;
38}
39
40static bool is_valid_partially_lazy(const GrSurfaceDesc& desc) {
41 return ((desc.fWidth > 0 && desc.fHeight > 0) ||
42 (desc.fWidth <= 0 && desc.fHeight <= 0)) &&
43 desc.fConfig != kUnknown_GrPixelConfig;
44}
45
46static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
47 return desc.fWidth > 0 &&
48 desc.fHeight > 0 &&
49 desc.fConfig != kUnknown_GrPixelConfig;
50}
51#endif
52
Chris Dalton706a6ff2017-11-29 22:01:06 -070053// Lazy-callback version
Greg Daniel457469c2018-02-08 15:05:44 -050054GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
Greg Daniel4065d452018-11-16 15:43:41 -050055 const GrBackendFormat& format, const GrSurfaceDesc& desc,
Brian Salomonf2c2ba92019-07-17 09:59:59 -040056 GrRenderable renderable, GrSurfaceOrigin origin,
57 const GrSwizzle& textureSwizzle, SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -040058 SkBudgeted budgeted, GrProtected isProtected,
59 GrInternalSurfaceFlags surfaceFlags)
Greg Daniele3204862018-04-16 11:24:10 -040060 : fSurfaceFlags(surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -050061 , fFormat(format)
Greg Daniele3204862018-04-16 11:24:10 -040062 , fConfig(desc.fConfig)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050063 , fWidth(desc.fWidth)
64 , fHeight(desc.fHeight)
Brian Salomon2a4f9832018-03-03 22:43:43 -050065 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040066 , fTextureSwizzle(textureSwizzle)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050067 , fFit(fit)
68 , fBudgeted(budgeted)
Chris Dalton706a6ff2017-11-29 22:01:06 -070069 , fLazyInstantiateCallback(std::move(callback))
Greg Daniel457469c2018-02-08 15:05:44 -050070 , fLazyInstantiationType(lazyType)
Brian Salomone8a766b2019-07-19 14:24:36 -040071 , fIsProtected(isProtected)
Chris Dalton706a6ff2017-11-29 22:01:06 -070072 , fGpuMemorySize(kInvalidGpuMemorySize)
73 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -050074 SkASSERT(fFormat.isValid());
Chris Dalton706a6ff2017-11-29 22:01:06 -070075 // NOTE: the default fUniqueID ctor pulls a value from the same pool as the GrGpuResources.
Greg Daniel65fa8ca2018-01-10 17:06:31 -050076 if (fLazyInstantiateCallback) {
77 SkASSERT(is_valid_fully_lazy(desc, fit) || is_valid_partially_lazy(desc));
78 } else {
79 SkASSERT(is_valid_non_lazy(desc));
80 }
Jim Van Verth1676cb92019-01-15 13:24:45 -050081
82 if (GrPixelConfigIsCompressed(desc.fConfig)) {
Brian Salomonf2c2ba92019-07-17 09:59:59 -040083 SkASSERT(renderable == GrRenderable::kNo);
Jim Van Verth1676cb92019-01-15 13:24:45 -050084 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
85 }
Chris Dalton706a6ff2017-11-29 22:01:06 -070086}
87
88// Wrapped version
Greg Daniel2c19e7f2019-06-18 13:29:21 -040089GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin,
90 const GrSwizzle& textureSwizzle, SkBackingFit fit)
Robert Phillipsb5204762019-06-19 14:12:13 -040091 : fTarget(std::move(surface))
Greg Daniele3204862018-04-16 11:24:10 -040092 , fSurfaceFlags(fTarget->surfacePriv().flags())
Greg Daniel4065d452018-11-16 15:43:41 -050093 , fFormat(fTarget->backendFormat())
Brian Salomonbb5711a2017-05-17 13:49:59 -040094 , fConfig(fTarget->config())
95 , fWidth(fTarget->width())
96 , fHeight(fTarget->height())
Robert Phillips066f0202017-07-25 10:16:35 -040097 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040098 , fTextureSwizzle(textureSwizzle)
Brian Salomonbb5711a2017-05-17 13:49:59 -040099 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500100 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
101 ? SkBudgeted::kYes
102 : SkBudgeted::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400103 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400104 , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400105 , fGpuMemorySize(kInvalidGpuMemorySize)
Robert Phillips019ff272017-07-24 14:47:57 -0400106 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -0500107 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400108}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400109
Robert Phillipsf2361d22016-10-25 14:20:06 -0400110GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400111 // For this to be deleted the opList that held a ref on it (if there was one) must have been
112 // deleted. Which would have cleared out this back pointer.
113 SkASSERT(!fLastOpList);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400114}
115
Robert Phillipseafd48a2017-11-16 07:52:08 -0500116bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
Chris Daltoneffee202019-07-01 22:28:03 -0600117 GrSurface* surface, int minStencilSampleCount) {
118 if (minStencilSampleCount) {
Robert Phillips65048132017-08-10 08:44:49 -0400119 GrRenderTarget* rt = surface->asRenderTarget();
120 if (!rt) {
121 SkASSERT(0);
122 return false;
123 }
124
Chris Daltoneffee202019-07-01 22:28:03 -0600125 if (!resourceProvider->attachStencilAttachment(rt, minStencilSampleCount)) {
Robert Phillips65048132017-08-10 08:44:49 -0400126 return false;
127 }
128 }
129
130 return true;
131}
132
Robert Phillipsba5c4392018-07-25 12:37:14 -0400133sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
Chris Daltoneffee202019-07-01 22:28:03 -0600134 int sampleCnt, int minStencilSampleCount,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400135 GrRenderable renderable,
Robert Phillips10d17212019-04-24 14:09:10 -0400136 GrMipMapped mipMapped) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500137 SkASSERT(GrSurfaceProxy::LazyState::kNot == this->lazyInstantiationState());
Greg Danield2d8e922018-02-12 12:07:39 -0500138 SkASSERT(!fTarget);
Brian Salomonbb5711a2017-05-17 13:49:59 -0400139 GrSurfaceDesc desc;
Robert Phillips16d8ec62017-07-27 16:16:25 -0400140 desc.fWidth = fWidth;
141 desc.fHeight = fHeight;
142 desc.fConfig = fConfig;
143 desc.fSampleCnt = sampleCnt;
Robert Phillipseaa86252016-11-08 13:49:39 +0000144
Robert Phillips10d17212019-04-24 14:09:10 -0400145 // The explicit resource allocator requires that any resources it pulls out of the
146 // cache have no pending IO.
147 GrResourceProvider::Flags resourceProviderFlags = GrResourceProvider::Flags::kNoPendingIO;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400148
Robert Phillips5af44de2017-07-18 14:49:38 -0400149 sk_sp<GrSurface> surface;
Greg Danielf6f7b672018-02-15 13:06:26 -0500150 if (GrMipMapped::kYes == mipMapped) {
151 SkASSERT(SkBackingFit::kExact == fFit);
152
153 // SkMipMap doesn't include the base level in the level count so we have to add 1
154 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
155 // We should have caught the case where mipCount == 1 when making the proxy and instead
156 // created a non-mipmapped proxy.
157 SkASSERT(mipCount > 1);
158 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
159
160 // We don't want to upload any texel data
161 for (int i = 0; i < mipCount; i++) {
162 texels[i].fPixels = nullptr;
163 texels[i].fRowBytes = 0;
164 }
165
Brian Salomone8a766b2019-07-19 14:24:36 -0400166 surface = resourceProvider->createTexture(desc, renderable, fBudgeted, fIsProtected,
167 texels.get(), mipCount);
Greg Danielf6f7b672018-02-15 13:06:26 -0500168 if (surface) {
169 SkASSERT(surface->asTexture());
170 SkASSERT(GrMipMapped::kYes == surface->asTexture()->texturePriv().mipMapped());
171 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000172 } else {
Greg Danielf6f7b672018-02-15 13:06:26 -0500173 if (SkBackingFit::kApprox == fFit) {
Brian Salomone8a766b2019-07-19 14:24:36 -0400174 surface = resourceProvider->createApproxTexture(desc, renderable, fIsProtected,
175 resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500176 } else {
Brian Salomone8a766b2019-07-19 14:24:36 -0400177 surface = resourceProvider->createTexture(desc, renderable, fBudgeted, fIsProtected,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400178 resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500179 }
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 {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400194 if (this->ignoredByResourceAllocator()) {
195 // 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) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500234 SkASSERT(LazyState::kNot == this->lazyInstantiationState());
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 {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500266 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
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,
Greg Daniele252f082017-10-23 16:05:23 -0400284 mipMapped, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400285}
286
Robert Phillipsf2361d22016-10-25 14:20:06 -0400287void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400288#ifdef SK_DEBUG
Robert Phillipsf2361d22016-10-25 14:20:06 -0400289 if (fLastOpList) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400290 SkASSERT(fLastOpList->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
295 fLastOpList = opList;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400296}
Robert Phillips37430132016-11-09 06:50:43 -0500297
Brian Osman45580d32016-11-23 09:37:01 -0500298GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
299 return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
300}
301
302GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
303 return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
304}
305
Robert Phillipsa108c922017-10-10 10:42:19 -0400306int GrSurfaceProxy::worstCaseWidth() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500307 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400308 if (fTarget) {
309 return fTarget->width();
310 }
311
312 if (SkBackingFit::kExact == fFit) {
313 return fWidth;
314 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400315 return GrResourceProvider::MakeApprox(fWidth);
Robert Phillipsa108c922017-10-10 10:42:19 -0400316}
317
318int GrSurfaceProxy::worstCaseHeight() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500319 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400320 if (fTarget) {
321 return fTarget->height();
322 }
323
324 if (SkBackingFit::kExact == fFit) {
325 return fHeight;
326 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400327 return GrResourceProvider::MakeApprox(fHeight);
Robert Phillipsa108c922017-10-10 10:42:19 -0400328}
329
Brian Osman45580d32016-11-23 09:37:01 -0500330#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500331void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500332 if (fTarget) {
333 SkASSERT(fTarget->getContext() == context);
334 }
Brian Osman45580d32016-11-23 09:37:01 -0500335}
336#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500337
Robert Phillipsd44146b2019-02-15 14:44:28 -0500338sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500339 GrSurfaceProxy* src,
Greg Daniel65c7f662017-10-30 13:39:09 -0400340 GrMipMapped mipMapped,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500341 SkIRect srcRect,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500342 SkBackingFit fit,
Greg Daniel46cfbc62019-06-07 11:43:30 -0400343 SkBudgeted budgeted,
344 RectsMustMatch rectsMustMatch) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500345 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Brian Salomon947efe22019-07-16 15:36:11 -0400346 GrProtected isProtected = src->isProtected() ? GrProtected::kYes : GrProtected::kNo;
347 int width;
348 int height;
Greg Daniel46cfbc62019-06-07 11:43:30 -0400349
350 SkIPoint dstPoint;
351 if (rectsMustMatch == RectsMustMatch::kYes) {
Brian Salomon947efe22019-07-16 15:36:11 -0400352 width = src->width();
353 height = src->height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400354 dstPoint = {srcRect.fLeft, srcRect.fTop};
355 } else {
Brian Salomon947efe22019-07-16 15:36:11 -0400356 width = srcRect.width();
357 height = srcRect.height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400358 dstPoint = {0, 0};
359 }
360
Robert Phillipse2f7d182016-12-15 09:23:05 -0500361 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
362 return nullptr;
363 }
Brian Salomond6287472019-06-24 15:50:07 -0400364 auto colorType = GrPixelConfigToColorType(src->config());
Greg Daniel46cfbc62019-06-07 11:43:30 -0400365 if (src->backendFormat().textureType() != GrTextureType::kExternal) {
Brian Salomon947efe22019-07-16 15:36:11 -0400366 sk_sp<GrTextureContext> dstContext(context->priv().makeDeferredTextureContext(
367 fit, width, height, colorType, kUnknown_SkAlphaType, nullptr, mipMapped,
368 src->origin(), budgeted, isProtected));
Greg Daniel46cfbc62019-06-07 11:43:30 -0400369 if (!dstContext) {
370 return nullptr;
371 }
372 if (dstContext->copy(src, srcRect, dstPoint)) {
373 return dstContext->asTextureProxyRef();
374 }
Greg Danielc5167c02019-06-05 17:36:53 +0000375 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400376 if (src->asTextureProxy()) {
Greg Daniel46cfbc62019-06-07 11:43:30 -0400377 sk_sp<GrRenderTargetContext> dstContext = context->priv().makeDeferredRenderTargetContext(
Brian Salomon947efe22019-07-16 15:36:11 -0400378 fit, width, height, colorType, nullptr, 1, mipMapped, src->origin(), nullptr,
379 budgeted);
Greg Daniel46cfbc62019-06-07 11:43:30 -0400380
381 if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
382 return dstContext->asTextureProxyRef();
383 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400384 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400385 // Can't use backend copies or draws.
386 return nullptr;
Robert Phillips63c67462017-02-15 14:19:01 -0500387}
388
Robert Phillipsd44146b2019-02-15 14:44:28 -0500389sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500390 GrMipMapped mipMapped, SkBackingFit fit,
391 SkBudgeted budgeted) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500392 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500393 return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
394 budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500395}
396
Robert Phillipsb5204762019-06-19 14:12:13 -0400397#if GR_TEST_UTILS
398int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
399 if (fTarget) {
400 return fTarget->testingOnly_getRefCnt();
401 }
402
403 return -1; // no backing GrSurface
404}
405
406GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
407 return fSurfaceFlags;
408}
409#endif
410
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400411void GrSurfaceProxyPriv::exactify() {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500412 SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400413 if (this->isExact()) {
414 return;
415 }
416
417 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
418
419 if (fProxy->fTarget) {
420 // The kApprox but already instantiated case. Setting the proxy's width & height to
421 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400422 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400423 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
424 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400425 fProxy->fWidth = fProxy->fTarget->width();
426 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400427 return;
428 }
429
430 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
431 // It could mess things up if prior decisions were based on the approximate size.
432 fProxy->fFit = SkBackingFit::kExact;
433 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400434 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400435 // the special image goes away. If it hasn't been computed yet it might as well compute the
436 // exact amount.
437}
438
Greg Danielbddcc952018-01-24 13:22:24 -0500439bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500440 SkASSERT(GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700441
Robert Phillips0790f8a2018-09-18 13:11:03 -0400442 sk_sp<GrSurface> surface;
443 if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
444 // First try to reattach to a cached version if the proxy is uniquely keyed
445 surface = resourceProvider->findByUniqueKey<GrSurface>(
446 fProxy->asTextureProxy()->getUniqueKey());
447 }
448
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400449 bool syncKey = true;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400450 if (!surface) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400451 auto result = fProxy->fLazyInstantiateCallback(resourceProvider);
452 surface = std::move(result.fSurface);
453 syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400454 }
Greg Daniel457469c2018-02-08 15:05:44 -0500455 if (GrSurfaceProxy::LazyInstantiationType::kSingleUse == fProxy->fLazyInstantiationType) {
Greg Daniel457469c2018-02-08 15:05:44 -0500456 fProxy->fLazyInstantiateCallback = nullptr;
457 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500458 if (!surface) {
Chris Dalton706a6ff2017-11-29 22:01:06 -0700459 fProxy->fWidth = 0;
460 fProxy->fHeight = 0;
Greg Danielbddcc952018-01-24 13:22:24 -0500461 return false;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700462 }
463
Robert Phillipsc1b60662018-06-26 10:20:08 -0400464 if (fProxy->fWidth <= 0 || fProxy->fHeight <= 0) {
465 // This was a fully lazy proxy. We need to fill in the width & height. For partially
466 // lazy proxies we must preserve the original width & height since that indicates
467 // the content area.
468 SkASSERT(fProxy->fWidth <= 0 && fProxy->fHeight <= 0);
469 fProxy->fWidth = surface->width();
470 fProxy->fHeight = surface->height();
471 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700472
Chris Daltonf91b7552019-04-29 16:21:18 -0600473 SkASSERT(fProxy->fWidth <= surface->width());
474 SkASSERT(fProxy->fHeight <= surface->height());
475
Chris Daltoneffee202019-07-01 22:28:03 -0600476 int minStencilSampleCount = (fProxy->asRenderTargetProxy())
477 ? fProxy->asRenderTargetProxy()->numSamples()
478 : 0;
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500479
Chris Daltoneffee202019-07-01 22:28:03 -0600480 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(
481 resourceProvider, surface.get(), minStencilSampleCount)) {
Robert Phillips01a91282018-07-26 08:03:04 -0400482 return false;
483 }
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500484
Greg Daniel303e83e2018-09-10 14:10:19 -0400485 if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400486 texProxy->setTargetKeySync(syncKey);
487 if (syncKey) {
488 const GrUniqueKey& key = texProxy->getUniqueKey();
489 if (key.isValid()) {
490 if (!surface->asTexture()->getUniqueKey().isValid()) {
491 // If 'surface' is newly created, attach the unique key
492 resourceProvider->assignUniqueKeyToResource(key, surface.get());
493 } else {
494 // otherwise we had better have reattached to a cached version
495 SkASSERT(surface->asTexture()->getUniqueKey() == key);
496 }
Robert Phillips0790f8a2018-09-18 13:11:03 -0400497 } else {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400498 SkASSERT(!surface->getUniqueKey().isValid());
Robert Phillips0790f8a2018-09-18 13:11:03 -0400499 }
Greg Daniel303e83e2018-09-10 14:10:19 -0400500 }
501 }
502
Robert Phillipse8fabb22018-02-04 14:33:21 -0500503 this->assign(std::move(surface));
Greg Danielbddcc952018-01-24 13:22:24 -0500504 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700505}
506
Greg Daniel849dce12018-04-24 14:32:53 -0400507#ifdef SK_DEBUG
508void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
509 SkASSERT(surface->config() == fConfig);
510
Greg Daniel849dce12018-04-24 14:32:53 -0400511 this->onValidateSurface(surface);
512}
513#endif