blob: 9bcfa7c76bb18ee981290eb79d67aa3bec487a75 [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"
13#include "src/gpu/GrCaps.h"
Greg Daniel46cfbc62019-06-07 11:43:30 -040014#include "src/gpu/GrClip.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/gpu/GrContextPriv.h"
16#include "src/gpu/GrGpuResourcePriv.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040017#include "src/gpu/GrOpList.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrProxyProvider.h"
19#include "src/gpu/GrRecordingContextPriv.h"
Chris Daltoneffee202019-07-01 22:28:03 -060020#include "src/gpu/GrStencilAttachment.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "src/gpu/GrSurfaceContext.h"
Greg Daniel46cfbc62019-06-07 11:43:30 -040022#include "src/gpu/GrSurfaceContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050023#include "src/gpu/GrSurfacePriv.h"
24#include "src/gpu/GrTexturePriv.h"
25#include "src/gpu/GrTextureRenderTargetProxy.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040026
Mike Kleinc0bd9f92019-04-23 12:05:21 -050027#include "src/core/SkMathPriv.h"
28#include "src/core/SkMipMap.h"
Robert Phillips93f16332016-11-23 19:37:13 -050029
Greg Daniel65fa8ca2018-01-10 17:06:31 -050030#ifdef SK_DEBUG
Mike Kleinc0bd9f92019-04-23 12:05:21 -050031#include "include/gpu/GrRenderTarget.h"
32#include "src/gpu/GrRenderTargetPriv.h"
Robert Phillipsc7c2baf2018-03-08 09:51:04 -050033
Greg Daniel65fa8ca2018-01-10 17:06:31 -050034static bool is_valid_fully_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
35 return desc.fWidth <= 0 &&
36 desc.fHeight <= 0 &&
37 desc.fConfig != kUnknown_GrPixelConfig &&
Brian Salomonbdecacf2018-02-02 20:32:49 -050038 desc.fSampleCnt == 1 &&
Greg Daniel65fa8ca2018-01-10 17:06:31 -050039 SkBackingFit::kApprox == fit;
40}
41
42static bool is_valid_partially_lazy(const GrSurfaceDesc& desc) {
43 return ((desc.fWidth > 0 && desc.fHeight > 0) ||
44 (desc.fWidth <= 0 && desc.fHeight <= 0)) &&
45 desc.fConfig != kUnknown_GrPixelConfig;
46}
47
48static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
49 return desc.fWidth > 0 &&
50 desc.fHeight > 0 &&
51 desc.fConfig != kUnknown_GrPixelConfig;
52}
53#endif
54
Chris Dalton706a6ff2017-11-29 22:01:06 -070055// Lazy-callback version
Greg Daniel457469c2018-02-08 15:05:44 -050056GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
Greg Daniel4065d452018-11-16 15:43:41 -050057 const GrBackendFormat& format, const GrSurfaceDesc& desc,
Greg Daniel2c19e7f2019-06-18 13:29:21 -040058 GrSurfaceOrigin origin, const GrSwizzle& textureSwizzle,
59 SkBackingFit fit, SkBudgeted budgeted,
60 GrInternalSurfaceFlags surfaceFlags)
Greg Daniele3204862018-04-16 11:24:10 -040061 : fSurfaceFlags(surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -050062 , fFormat(format)
Greg Daniele3204862018-04-16 11:24:10 -040063 , fConfig(desc.fConfig)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050064 , fWidth(desc.fWidth)
65 , fHeight(desc.fHeight)
Brian Salomon2a4f9832018-03-03 22:43:43 -050066 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040067 , fTextureSwizzle(textureSwizzle)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050068 , fFit(fit)
69 , fBudgeted(budgeted)
Chris Dalton706a6ff2017-11-29 22:01:06 -070070 , fLazyInstantiateCallback(std::move(callback))
Greg Daniel457469c2018-02-08 15:05:44 -050071 , fLazyInstantiationType(lazyType)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050072 , fNeedsClear(SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag))
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040073 , fIsProtected(desc.fIsProtected)
Chris Dalton706a6ff2017-11-29 22:01:06 -070074 , fGpuMemorySize(kInvalidGpuMemorySize)
75 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -050076 SkASSERT(fFormat.isValid());
Chris Dalton706a6ff2017-11-29 22:01:06 -070077 // NOTE: the default fUniqueID ctor pulls a value from the same pool as the GrGpuResources.
Greg Daniel65fa8ca2018-01-10 17:06:31 -050078 if (fLazyInstantiateCallback) {
79 SkASSERT(is_valid_fully_lazy(desc, fit) || is_valid_partially_lazy(desc));
80 } else {
81 SkASSERT(is_valid_non_lazy(desc));
82 }
Jim Van Verth1676cb92019-01-15 13:24:45 -050083
84 if (GrPixelConfigIsCompressed(desc.fConfig)) {
85 SkASSERT(!SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag));
86 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
87 }
Chris Dalton706a6ff2017-11-29 22:01:06 -070088}
89
90// Wrapped version
Greg Daniel2c19e7f2019-06-18 13:29:21 -040091GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin,
92 const GrSwizzle& textureSwizzle, SkBackingFit fit)
Robert Phillipsb5204762019-06-19 14:12:13 -040093 : fTarget(std::move(surface))
Greg Daniele3204862018-04-16 11:24:10 -040094 , fSurfaceFlags(fTarget->surfacePriv().flags())
Greg Daniel4065d452018-11-16 15:43:41 -050095 , fFormat(fTarget->backendFormat())
Brian Salomonbb5711a2017-05-17 13:49:59 -040096 , fConfig(fTarget->config())
97 , fWidth(fTarget->width())
98 , fHeight(fTarget->height())
Robert Phillips066f0202017-07-25 10:16:35 -040099 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400100 , fTextureSwizzle(textureSwizzle)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400101 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500102 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
103 ? SkBudgeted::kYes
104 : SkBudgeted::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400105 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Brian Salomond17b4a62017-05-23 16:53:47 -0400106 , fNeedsClear(false)
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400107 , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400108 , fGpuMemorySize(kInvalidGpuMemorySize)
Robert Phillips019ff272017-07-24 14:47:57 -0400109 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -0500110 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400111}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400112
Robert Phillipsf2361d22016-10-25 14:20:06 -0400113GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400114 // For this to be deleted the opList that held a ref on it (if there was one) must have been
115 // deleted. Which would have cleared out this back pointer.
116 SkASSERT(!fLastOpList);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400117}
118
Robert Phillipseafd48a2017-11-16 07:52:08 -0500119bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
Chris Daltoneffee202019-07-01 22:28:03 -0600120 GrSurface* surface, int minStencilSampleCount) {
121 if (minStencilSampleCount) {
Robert Phillips65048132017-08-10 08:44:49 -0400122 GrRenderTarget* rt = surface->asRenderTarget();
123 if (!rt) {
124 SkASSERT(0);
125 return false;
126 }
127
Chris Daltoneffee202019-07-01 22:28:03 -0600128 if (!resourceProvider->attachStencilAttachment(rt, minStencilSampleCount)) {
Robert Phillips65048132017-08-10 08:44:49 -0400129 return false;
130 }
131 }
132
133 return true;
134}
135
Robert Phillipsba5c4392018-07-25 12:37:14 -0400136sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
Chris Daltoneffee202019-07-01 22:28:03 -0600137 int sampleCnt, int minStencilSampleCount,
Robert Phillipsba5c4392018-07-25 12:37:14 -0400138 GrSurfaceDescFlags descFlags,
Robert Phillips10d17212019-04-24 14:09:10 -0400139 GrMipMapped mipMapped) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500140 SkASSERT(GrSurfaceProxy::LazyState::kNot == this->lazyInstantiationState());
Greg Danield2d8e922018-02-12 12:07:39 -0500141 SkASSERT(!fTarget);
Brian Salomonbb5711a2017-05-17 13:49:59 -0400142 GrSurfaceDesc desc;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400143 desc.fFlags = descFlags;
Brian Salomond17b4a62017-05-23 16:53:47 -0400144 if (fNeedsClear) {
145 desc.fFlags |= kPerformInitialClear_GrSurfaceFlag;
146 }
Robert Phillips16d8ec62017-07-27 16:16:25 -0400147 desc.fWidth = fWidth;
148 desc.fHeight = fHeight;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400149 desc.fIsProtected = fIsProtected;
Robert Phillips16d8ec62017-07-27 16:16:25 -0400150 desc.fConfig = fConfig;
151 desc.fSampleCnt = sampleCnt;
Robert Phillipseaa86252016-11-08 13:49:39 +0000152
Robert Phillips10d17212019-04-24 14:09:10 -0400153 // The explicit resource allocator requires that any resources it pulls out of the
154 // cache have no pending IO.
155 GrResourceProvider::Flags resourceProviderFlags = GrResourceProvider::Flags::kNoPendingIO;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400156
Robert Phillips5af44de2017-07-18 14:49:38 -0400157 sk_sp<GrSurface> surface;
Greg Danielf6f7b672018-02-15 13:06:26 -0500158 if (GrMipMapped::kYes == mipMapped) {
159 SkASSERT(SkBackingFit::kExact == fFit);
160
161 // SkMipMap doesn't include the base level in the level count so we have to add 1
162 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
163 // We should have caught the case where mipCount == 1 when making the proxy and instead
164 // created a non-mipmapped proxy.
165 SkASSERT(mipCount > 1);
166 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
167
168 // We don't want to upload any texel data
169 for (int i = 0; i < mipCount; i++) {
170 texels[i].fPixels = nullptr;
171 texels[i].fRowBytes = 0;
172 }
173
Brian Osman2b23c4b2018-06-01 12:25:08 -0400174 surface = resourceProvider->createTexture(desc, fBudgeted, texels.get(), mipCount);
Greg Danielf6f7b672018-02-15 13:06:26 -0500175 if (surface) {
176 SkASSERT(surface->asTexture());
177 SkASSERT(GrMipMapped::kYes == surface->asTexture()->texturePriv().mipMapped());
178 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000179 } else {
Greg Danielf6f7b672018-02-15 13:06:26 -0500180 if (SkBackingFit::kApprox == fFit) {
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400181 surface = resourceProvider->createApproxTexture(desc, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500182 } else {
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400183 surface = resourceProvider->createTexture(desc, fBudgeted, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500184 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000185 }
Robert Phillips65048132017-08-10 08:44:49 -0400186 if (!surface) {
187 return nullptr;
188 }
189
Robert Phillipse5f73282019-06-18 17:15:04 -0400190 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(),
Chris Daltoneffee202019-07-01 22:28:03 -0600191 minStencilSampleCount)) {
Robert Phillips65048132017-08-10 08:44:49 -0400192 return nullptr;
Robert Phillipseaa86252016-11-08 13:49:39 +0000193 }
194
Robert Phillips5af44de2017-07-18 14:49:38 -0400195 return surface;
196}
197
Brian Salomon7d94bb52018-10-12 14:37:19 -0400198bool GrSurfaceProxy::canSkipResourceAllocator() const {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400199 if (this->ignoredByResourceAllocator()) {
200 // Usually an atlas or onFlush proxy
201 return true;
202 }
203
Brian Salomon7d94bb52018-10-12 14:37:19 -0400204 auto peek = this->peekSurface();
205 if (!peek) {
206 return false;
207 }
208 // If this resource is already allocated and not recyclable then the resource allocator does
209 // not need to do anything with it.
210 return !peek->resourcePriv().getScratchKey().isValid();
211}
212
Robert Phillips5af44de2017-07-18 14:49:38 -0400213void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
214 SkASSERT(!fTarget && surface);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400215
Greg Daniel849dce12018-04-24 14:32:53 -0400216 SkDEBUGCODE(this->validateSurface(surface.get());)
Robert Phillipsabf7b762018-03-21 12:13:37 -0400217
Robert Phillipse5f73282019-06-18 17:15:04 -0400218 fTarget = std::move(surface);
robertphillips1125a032016-11-16 11:17:17 -0800219
Robert Phillipseaa86252016-11-08 13:49:39 +0000220#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500221 if (this->asRenderTargetProxy()) {
222 SkASSERT(fTarget->asRenderTarget());
Chris Daltoneffee202019-07-01 22:28:03 -0600223 if (int minStencilSampleCount = this->asRenderTargetProxy()->numStencilSamples()) {
224 auto* stencil = fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment();
225 SkASSERT(stencil);
226 SkASSERT(stencil->numSamples() >= minStencilSampleCount);
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500227 }
228 }
229
Robert Phillipseaa86252016-11-08 13:49:39 +0000230 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500231 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +0000232 }
233#endif
Robert Phillips5af44de2017-07-18 14:49:38 -0400234}
Robert Phillipseaa86252016-11-08 13:49:39 +0000235
Robert Phillips5af44de2017-07-18 14:49:38 -0400236bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Chris Daltoneffee202019-07-01 22:28:03 -0600237 int minStencilSampleCount, GrSurfaceDescFlags descFlags,
Robert Phillips10d17212019-04-24 14:09:10 -0400238 GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500239 SkASSERT(LazyState::kNot == this->lazyInstantiationState());
Robert Phillips5af44de2017-07-18 14:49:38 -0400240 if (fTarget) {
Brian Salomon57904202018-12-17 14:45:00 -0500241 if (uniqueKey && uniqueKey->isValid()) {
242 SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400243 }
Robert Phillipse5f73282019-06-18 17:15:04 -0400244 return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget.get(),
Chris Daltoneffee202019-07-01 22:28:03 -0600245 minStencilSampleCount);
Robert Phillips5af44de2017-07-18 14:49:38 -0400246 }
247
Chris Daltoneffee202019-07-01 22:28:03 -0600248 sk_sp<GrSurface> surface = this->createSurfaceImpl(
249 resourceProvider, sampleCnt, minStencilSampleCount, descFlags, mipMapped);
Robert Phillips5af44de2017-07-18 14:49:38 -0400250 if (!surface) {
251 return false;
252 }
253
Brian Osman28c434b2017-09-27 13:11:16 -0400254 // If there was an invalidation message pending for this key, we might have just processed it,
255 // causing the key (stored on this proxy) to become invalid.
256 if (uniqueKey && uniqueKey->isValid()) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400257 resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
258 }
259
Robert Phillips5af44de2017-07-18 14:49:38 -0400260 this->assign(std::move(surface));
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400261
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400262 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +0000263}
264
Brian Salomon967df202018-12-07 11:15:53 -0500265void GrSurfaceProxy::deinstantiate() {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400266 SkASSERT(this->isInstantiated());
Robert Phillipse5f73282019-06-18 17:15:04 -0400267 fTarget = nullptr;
Robert Phillips4bc70112018-03-01 10:24:02 -0500268}
269
Robert Phillips57aa3672017-07-21 11:38:13 -0400270void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500271 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillips57aa3672017-07-21 11:38:13 -0400272 const GrRenderTargetProxy* rtp = this->asRenderTargetProxy();
Brian Salomonbdecacf2018-02-02 20:32:49 -0500273 int sampleCount = 1;
Robert Phillips57aa3672017-07-21 11:38:13 -0400274 if (rtp) {
Chris Dalton6ce447a2019-06-23 18:07:38 -0600275 sampleCount = rtp->numSamples();
Robert Phillips57aa3672017-07-21 11:38:13 -0400276 }
277
278 const GrTextureProxy* tp = this->asTextureProxy();
Greg Daniele252f082017-10-23 16:05:23 -0400279 GrMipMapped mipMapped = GrMipMapped::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400280 if (tp) {
Greg Daniele252f082017-10-23 16:05:23 -0400281 mipMapped = tp->mipMapped();
Robert Phillips57aa3672017-07-21 11:38:13 -0400282 }
283
Robert Phillipsa108c922017-10-10 10:42:19 -0400284 int width = this->worstCaseWidth();
285 int height = this->worstCaseHeight();
Robert Phillips57aa3672017-07-21 11:38:13 -0400286
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400287 GrTexturePriv::ComputeScratchKey(this->config(), width, height, SkToBool(rtp), sampleCount,
Greg Daniele252f082017-10-23 16:05:23 -0400288 mipMapped, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400289}
290
Robert Phillipsf2361d22016-10-25 14:20:06 -0400291void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400292#ifdef SK_DEBUG
Robert Phillipsf2361d22016-10-25 14:20:06 -0400293 if (fLastOpList) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400294 SkASSERT(fLastOpList->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +0000295 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400296#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -0400297
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400298 // Un-reffed
299 fLastOpList = opList;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400300}
Robert Phillips37430132016-11-09 06:50:43 -0500301
Brian Osman45580d32016-11-23 09:37:01 -0500302GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
303 return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
304}
305
306GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
307 return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
308}
309
Robert Phillipsa108c922017-10-10 10:42:19 -0400310int GrSurfaceProxy::worstCaseWidth() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500311 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400312 if (fTarget) {
313 return fTarget->width();
314 }
315
316 if (SkBackingFit::kExact == fFit) {
317 return fWidth;
318 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400319 return GrResourceProvider::MakeApprox(fWidth);
Robert Phillipsa108c922017-10-10 10:42:19 -0400320}
321
322int GrSurfaceProxy::worstCaseHeight() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500323 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400324 if (fTarget) {
325 return fTarget->height();
326 }
327
328 if (SkBackingFit::kExact == fFit) {
329 return fHeight;
330 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400331 return GrResourceProvider::MakeApprox(fHeight);
Robert Phillipsa108c922017-10-10 10:42:19 -0400332}
333
Brian Osman45580d32016-11-23 09:37:01 -0500334#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500335void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500336 if (fTarget) {
337 SkASSERT(fTarget->getContext() == context);
338 }
Brian Osman45580d32016-11-23 09:37:01 -0500339}
340#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500341
Robert Phillipsd44146b2019-02-15 14:44:28 -0500342sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500343 GrSurfaceProxy* src,
Greg Daniel65c7f662017-10-30 13:39:09 -0400344 GrMipMapped mipMapped,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500345 SkIRect srcRect,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500346 SkBackingFit fit,
Greg Daniel46cfbc62019-06-07 11:43:30 -0400347 SkBudgeted budgeted,
348 RectsMustMatch rectsMustMatch) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500349 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Greg Daniel46cfbc62019-06-07 11:43:30 -0400350 GrSurfaceDesc dstDesc;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400351 dstDesc.fIsProtected = src->isProtected() ? GrProtected::kYes : GrProtected::kNo;
Greg Daniel46cfbc62019-06-07 11:43:30 -0400352 dstDesc.fConfig = src->config();
353
354 SkIPoint dstPoint;
355 if (rectsMustMatch == RectsMustMatch::kYes) {
356 dstDesc.fWidth = src->width();
357 dstDesc.fHeight = src->height();
358 dstPoint = {srcRect.fLeft, srcRect.fTop};
359 } else {
360 dstDesc.fWidth = srcRect.width();
361 dstDesc.fHeight = srcRect.height();
362 dstPoint = {0, 0};
363 }
364
Robert Phillipse2f7d182016-12-15 09:23:05 -0500365 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
366 return nullptr;
367 }
Brian Salomond6287472019-06-24 15:50:07 -0400368 auto colorType = GrPixelConfigToColorType(src->config());
Greg Daniel46cfbc62019-06-07 11:43:30 -0400369 if (src->backendFormat().textureType() != GrTextureType::kExternal) {
370 sk_sp<GrSurfaceContext> dstContext(context->priv().makeDeferredSurfaceContext(
371 src->backendFormat().makeTexture2D(), dstDesc, src->origin(), mipMapped, fit,
Brian Salomond6287472019-06-24 15:50:07 -0400372 budgeted, colorType, kUnknown_SkAlphaType));
Greg Daniel46cfbc62019-06-07 11:43:30 -0400373 if (!dstContext) {
374 return nullptr;
375 }
376 if (dstContext->copy(src, srcRect, dstPoint)) {
377 return dstContext->asTextureProxyRef();
378 }
Greg Danielc5167c02019-06-05 17:36:53 +0000379 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400380 if (src->asTextureProxy()) {
Greg Daniel46cfbc62019-06-07 11:43:30 -0400381 sk_sp<GrRenderTargetContext> dstContext = context->priv().makeDeferredRenderTargetContext(
Brian Salomon27ae52c2019-07-03 11:27:44 -0400382 fit, dstDesc.fWidth, dstDesc.fHeight, colorType, nullptr, 1, mipMapped,
383 src->origin(), nullptr, budgeted);
Greg Daniel46cfbc62019-06-07 11:43:30 -0400384
385 if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
386 return dstContext->asTextureProxyRef();
387 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400388 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400389 // Can't use backend copies or draws.
390 return nullptr;
Robert Phillips63c67462017-02-15 14:19:01 -0500391}
392
Robert Phillipsd44146b2019-02-15 14:44:28 -0500393sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500394 GrMipMapped mipMapped, SkBackingFit fit,
395 SkBudgeted budgeted) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500396 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500397 return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
398 budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500399}
400
Robert Phillipsb5204762019-06-19 14:12:13 -0400401#if GR_TEST_UTILS
402int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
403 if (fTarget) {
404 return fTarget->testingOnly_getRefCnt();
405 }
406
407 return -1; // no backing GrSurface
408}
409
410GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
411 return fSurfaceFlags;
412}
413#endif
414
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400415void GrSurfaceProxyPriv::exactify() {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500416 SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400417 if (this->isExact()) {
418 return;
419 }
420
421 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
422
423 if (fProxy->fTarget) {
424 // The kApprox but already instantiated case. Setting the proxy's width & height to
425 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400426 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400427 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
428 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400429 fProxy->fWidth = fProxy->fTarget->width();
430 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400431 return;
432 }
433
434 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
435 // It could mess things up if prior decisions were based on the approximate size.
436 fProxy->fFit = SkBackingFit::kExact;
437 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400438 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400439 // the special image goes away. If it hasn't been computed yet it might as well compute the
440 // exact amount.
441}
442
Greg Danielbddcc952018-01-24 13:22:24 -0500443bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500444 SkASSERT(GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700445
Robert Phillips0790f8a2018-09-18 13:11:03 -0400446 sk_sp<GrSurface> surface;
447 if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
448 // First try to reattach to a cached version if the proxy is uniquely keyed
449 surface = resourceProvider->findByUniqueKey<GrSurface>(
450 fProxy->asTextureProxy()->getUniqueKey());
451 }
452
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400453 bool syncKey = true;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400454 if (!surface) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400455 auto result = fProxy->fLazyInstantiateCallback(resourceProvider);
456 surface = std::move(result.fSurface);
457 syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400458 }
Greg Daniel457469c2018-02-08 15:05:44 -0500459 if (GrSurfaceProxy::LazyInstantiationType::kSingleUse == fProxy->fLazyInstantiationType) {
Greg Daniel457469c2018-02-08 15:05:44 -0500460 fProxy->fLazyInstantiateCallback = nullptr;
461 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500462 if (!surface) {
Chris Dalton706a6ff2017-11-29 22:01:06 -0700463 fProxy->fWidth = 0;
464 fProxy->fHeight = 0;
Greg Danielbddcc952018-01-24 13:22:24 -0500465 return false;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700466 }
467
Robert Phillipsc1b60662018-06-26 10:20:08 -0400468 if (fProxy->fWidth <= 0 || fProxy->fHeight <= 0) {
469 // This was a fully lazy proxy. We need to fill in the width & height. For partially
470 // lazy proxies we must preserve the original width & height since that indicates
471 // the content area.
472 SkASSERT(fProxy->fWidth <= 0 && fProxy->fHeight <= 0);
473 fProxy->fWidth = surface->width();
474 fProxy->fHeight = surface->height();
475 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700476
Chris Daltonf91b7552019-04-29 16:21:18 -0600477 SkASSERT(fProxy->fWidth <= surface->width());
478 SkASSERT(fProxy->fHeight <= surface->height());
479
Chris Daltoneffee202019-07-01 22:28:03 -0600480 int minStencilSampleCount = (fProxy->asRenderTargetProxy())
481 ? fProxy->asRenderTargetProxy()->numSamples()
482 : 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));
Greg Danielbddcc952018-01-24 13:22:24 -0500508 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700509}
510
Greg Daniel849dce12018-04-24 14:32:53 -0400511#ifdef SK_DEBUG
512void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
513 SkASSERT(surface->config() == fConfig);
514
Greg Daniel849dce12018-04-24 14:32:53 -0400515 this->onValidateSurface(surface);
516}
517#endif