blob: 09224be126fba211fd90d91567eea6730a7cffe7 [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"
20#include "src/gpu/GrSurfaceContext.h"
Greg Daniel46cfbc62019-06-07 11:43:30 -040021#include "src/gpu/GrSurfaceContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050022#include "src/gpu/GrSurfacePriv.h"
23#include "src/gpu/GrTexturePriv.h"
24#include "src/gpu/GrTextureRenderTargetProxy.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040025
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/core/SkMathPriv.h"
27#include "src/core/SkMipMap.h"
Robert Phillips93f16332016-11-23 19:37:13 -050028
Greg Daniel65fa8ca2018-01-10 17:06:31 -050029#ifdef SK_DEBUG
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "include/gpu/GrRenderTarget.h"
31#include "src/gpu/GrRenderTargetPriv.h"
Robert Phillipsc7c2baf2018-03-08 09:51:04 -050032
Greg Daniel65fa8ca2018-01-10 17:06:31 -050033static bool is_valid_fully_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
34 return desc.fWidth <= 0 &&
35 desc.fHeight <= 0 &&
36 desc.fConfig != kUnknown_GrPixelConfig &&
Brian Salomonbdecacf2018-02-02 20:32:49 -050037 desc.fSampleCnt == 1 &&
Greg Daniel65fa8ca2018-01-10 17:06:31 -050038 SkBackingFit::kApprox == fit;
39}
40
41static bool is_valid_partially_lazy(const GrSurfaceDesc& desc) {
42 return ((desc.fWidth > 0 && desc.fHeight > 0) ||
43 (desc.fWidth <= 0 && desc.fHeight <= 0)) &&
44 desc.fConfig != kUnknown_GrPixelConfig;
45}
46
47static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
48 return desc.fWidth > 0 &&
49 desc.fHeight > 0 &&
50 desc.fConfig != kUnknown_GrPixelConfig;
51}
52#endif
53
Chris Dalton706a6ff2017-11-29 22:01:06 -070054// Lazy-callback version
Greg Daniel457469c2018-02-08 15:05:44 -050055GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
Greg Daniel4065d452018-11-16 15:43:41 -050056 const GrBackendFormat& format, const GrSurfaceDesc& desc,
Greg Daniel2c19e7f2019-06-18 13:29:21 -040057 GrSurfaceOrigin origin, const GrSwizzle& textureSwizzle,
58 SkBackingFit fit, SkBudgeted budgeted,
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)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050071 , fNeedsClear(SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag))
Emircan Uysaler23ca4e72019-06-24 10:53:09 -040072 , fIsProtected(desc.fIsProtected)
Chris Dalton706a6ff2017-11-29 22:01:06 -070073 , fGpuMemorySize(kInvalidGpuMemorySize)
74 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -050075 SkASSERT(fFormat.isValid());
Chris Dalton706a6ff2017-11-29 22:01:06 -070076 // NOTE: the default fUniqueID ctor pulls a value from the same pool as the GrGpuResources.
Greg Daniel65fa8ca2018-01-10 17:06:31 -050077 if (fLazyInstantiateCallback) {
78 SkASSERT(is_valid_fully_lazy(desc, fit) || is_valid_partially_lazy(desc));
79 } else {
80 SkASSERT(is_valid_non_lazy(desc));
81 }
Jim Van Verth1676cb92019-01-15 13:24:45 -050082
83 if (GrPixelConfigIsCompressed(desc.fConfig)) {
84 SkASSERT(!SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag));
85 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
86 }
Chris Dalton706a6ff2017-11-29 22:01:06 -070087}
88
89// Wrapped version
Greg Daniel2c19e7f2019-06-18 13:29:21 -040090GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin,
91 const GrSwizzle& textureSwizzle, SkBackingFit fit)
Robert Phillipsb5204762019-06-19 14:12:13 -040092 : fTarget(std::move(surface))
Greg Daniele3204862018-04-16 11:24:10 -040093 , fSurfaceFlags(fTarget->surfacePriv().flags())
Greg Daniel4065d452018-11-16 15:43:41 -050094 , fFormat(fTarget->backendFormat())
Brian Salomonbb5711a2017-05-17 13:49:59 -040095 , fConfig(fTarget->config())
96 , fWidth(fTarget->width())
97 , fHeight(fTarget->height())
Robert Phillips066f0202017-07-25 10:16:35 -040098 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040099 , fTextureSwizzle(textureSwizzle)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400100 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500101 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
102 ? SkBudgeted::kYes
103 : SkBudgeted::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400104 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Brian Salomond17b4a62017-05-23 16:53:47 -0400105 , fNeedsClear(false)
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400106 , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400107 , fGpuMemorySize(kInvalidGpuMemorySize)
Robert Phillips019ff272017-07-24 14:47:57 -0400108 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -0500109 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400110}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400111
Robert Phillipsf2361d22016-10-25 14:20:06 -0400112GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400113 // For this to be deleted the opList that held a ref on it (if there was one) must have been
114 // deleted. Which would have cleared out this back pointer.
115 SkASSERT(!fLastOpList);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400116}
117
Robert Phillipseafd48a2017-11-16 07:52:08 -0500118bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
119 GrSurface* surface, bool needsStencil) {
Robert Phillips65048132017-08-10 08:44:49 -0400120 if (needsStencil) {
121 GrRenderTarget* rt = surface->asRenderTarget();
122 if (!rt) {
123 SkASSERT(0);
124 return false;
125 }
126
127 if (!resourceProvider->attachStencilAttachment(rt)) {
128 return false;
129 }
130 }
131
132 return true;
133}
134
Robert Phillipsba5c4392018-07-25 12:37:14 -0400135sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
136 int sampleCnt, bool needsStencil,
137 GrSurfaceDescFlags descFlags,
Robert Phillips10d17212019-04-24 14:09:10 -0400138 GrMipMapped mipMapped) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500139 SkASSERT(GrSurfaceProxy::LazyState::kNot == this->lazyInstantiationState());
Greg Danield2d8e922018-02-12 12:07:39 -0500140 SkASSERT(!fTarget);
Brian Salomonbb5711a2017-05-17 13:49:59 -0400141 GrSurfaceDesc desc;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400142 desc.fFlags = descFlags;
Brian Salomond17b4a62017-05-23 16:53:47 -0400143 if (fNeedsClear) {
144 desc.fFlags |= kPerformInitialClear_GrSurfaceFlag;
145 }
Robert Phillips16d8ec62017-07-27 16:16:25 -0400146 desc.fWidth = fWidth;
147 desc.fHeight = fHeight;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400148 desc.fIsProtected = fIsProtected;
Robert Phillips16d8ec62017-07-27 16:16:25 -0400149 desc.fConfig = fConfig;
150 desc.fSampleCnt = sampleCnt;
Robert Phillipseaa86252016-11-08 13:49:39 +0000151
Robert Phillips10d17212019-04-24 14:09:10 -0400152 // The explicit resource allocator requires that any resources it pulls out of the
153 // cache have no pending IO.
154 GrResourceProvider::Flags resourceProviderFlags = GrResourceProvider::Flags::kNoPendingIO;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400155
Robert Phillips5af44de2017-07-18 14:49:38 -0400156 sk_sp<GrSurface> surface;
Greg Danielf6f7b672018-02-15 13:06:26 -0500157 if (GrMipMapped::kYes == mipMapped) {
158 SkASSERT(SkBackingFit::kExact == fFit);
159
160 // SkMipMap doesn't include the base level in the level count so we have to add 1
161 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
162 // We should have caught the case where mipCount == 1 when making the proxy and instead
163 // created a non-mipmapped proxy.
164 SkASSERT(mipCount > 1);
165 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
166
167 // We don't want to upload any texel data
168 for (int i = 0; i < mipCount; i++) {
169 texels[i].fPixels = nullptr;
170 texels[i].fRowBytes = 0;
171 }
172
Brian Osman2b23c4b2018-06-01 12:25:08 -0400173 surface = resourceProvider->createTexture(desc, fBudgeted, texels.get(), mipCount);
Greg Danielf6f7b672018-02-15 13:06:26 -0500174 if (surface) {
175 SkASSERT(surface->asTexture());
176 SkASSERT(GrMipMapped::kYes == surface->asTexture()->texturePriv().mipMapped());
177 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000178 } else {
Greg Danielf6f7b672018-02-15 13:06:26 -0500179 if (SkBackingFit::kApprox == fFit) {
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400180 surface = resourceProvider->createApproxTexture(desc, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500181 } else {
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400182 surface = resourceProvider->createTexture(desc, fBudgeted, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500183 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000184 }
Robert Phillips65048132017-08-10 08:44:49 -0400185 if (!surface) {
186 return nullptr;
187 }
188
Robert Phillipse5f73282019-06-18 17:15:04 -0400189 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(),
190 needsStencil)) {
Robert Phillips65048132017-08-10 08:44:49 -0400191 return nullptr;
Robert Phillipseaa86252016-11-08 13:49:39 +0000192 }
193
Robert Phillips5af44de2017-07-18 14:49:38 -0400194 return surface;
195}
196
Brian Salomon7d94bb52018-10-12 14:37:19 -0400197bool GrSurfaceProxy::canSkipResourceAllocator() const {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400198 if (this->ignoredByResourceAllocator()) {
199 // Usually an atlas or onFlush proxy
200 return true;
201 }
202
Brian Salomon7d94bb52018-10-12 14:37:19 -0400203 auto peek = this->peekSurface();
204 if (!peek) {
205 return false;
206 }
207 // If this resource is already allocated and not recyclable then the resource allocator does
208 // not need to do anything with it.
209 return !peek->resourcePriv().getScratchKey().isValid();
210}
211
Robert Phillips5af44de2017-07-18 14:49:38 -0400212void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
213 SkASSERT(!fTarget && surface);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400214
Greg Daniel849dce12018-04-24 14:32:53 -0400215 SkDEBUGCODE(this->validateSurface(surface.get());)
Robert Phillipsabf7b762018-03-21 12:13:37 -0400216
Robert Phillipse5f73282019-06-18 17:15:04 -0400217 fTarget = std::move(surface);
robertphillips1125a032016-11-16 11:17:17 -0800218
Robert Phillipseaa86252016-11-08 13:49:39 +0000219#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500220 if (this->asRenderTargetProxy()) {
221 SkASSERT(fTarget->asRenderTarget());
222 if (this->asRenderTargetProxy()->needsStencil()) {
223 SkASSERT(fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment());
224 }
225 }
226
Robert Phillipseaa86252016-11-08 13:49:39 +0000227 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500228 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +0000229 }
230#endif
Robert Phillips5af44de2017-07-18 14:49:38 -0400231}
Robert Phillipseaa86252016-11-08 13:49:39 +0000232
Robert Phillips5af44de2017-07-18 14:49:38 -0400233bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400234 bool needsStencil, GrSurfaceDescFlags descFlags,
Robert Phillips10d17212019-04-24 14:09:10 -0400235 GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500236 SkASSERT(LazyState::kNot == this->lazyInstantiationState());
Robert Phillips5af44de2017-07-18 14:49:38 -0400237 if (fTarget) {
Brian Salomon57904202018-12-17 14:45:00 -0500238 if (uniqueKey && uniqueKey->isValid()) {
239 SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400240 }
Robert Phillipse5f73282019-06-18 17:15:04 -0400241 return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget.get(),
242 needsStencil);
Robert Phillips5af44de2017-07-18 14:49:38 -0400243 }
244
Robert Phillips65048132017-08-10 08:44:49 -0400245 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, needsStencil,
Robert Phillips10d17212019-04-24 14:09:10 -0400246 descFlags, mipMapped);
Robert Phillips5af44de2017-07-18 14:49:38 -0400247 if (!surface) {
248 return false;
249 }
250
Brian Osman28c434b2017-09-27 13:11:16 -0400251 // If there was an invalidation message pending for this key, we might have just processed it,
252 // causing the key (stored on this proxy) to become invalid.
253 if (uniqueKey && uniqueKey->isValid()) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400254 resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
255 }
256
Robert Phillips5af44de2017-07-18 14:49:38 -0400257 this->assign(std::move(surface));
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400258
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400259 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +0000260}
261
Brian Salomon967df202018-12-07 11:15:53 -0500262void GrSurfaceProxy::deinstantiate() {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400263 SkASSERT(this->isInstantiated());
Robert Phillipse5f73282019-06-18 17:15:04 -0400264 fTarget = nullptr;
Robert Phillips4bc70112018-03-01 10:24:02 -0500265}
266
Robert Phillips57aa3672017-07-21 11:38:13 -0400267void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500268 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillips57aa3672017-07-21 11:38:13 -0400269 const GrRenderTargetProxy* rtp = this->asRenderTargetProxy();
Brian Salomonbdecacf2018-02-02 20:32:49 -0500270 int sampleCount = 1;
Robert Phillips57aa3672017-07-21 11:38:13 -0400271 if (rtp) {
Chris Dalton6ce447a2019-06-23 18:07:38 -0600272 sampleCount = rtp->numSamples();
Robert Phillips57aa3672017-07-21 11:38:13 -0400273 }
274
275 const GrTextureProxy* tp = this->asTextureProxy();
Greg Daniele252f082017-10-23 16:05:23 -0400276 GrMipMapped mipMapped = GrMipMapped::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400277 if (tp) {
Greg Daniele252f082017-10-23 16:05:23 -0400278 mipMapped = tp->mipMapped();
Robert Phillips57aa3672017-07-21 11:38:13 -0400279 }
280
Robert Phillipsa108c922017-10-10 10:42:19 -0400281 int width = this->worstCaseWidth();
282 int height = this->worstCaseHeight();
Robert Phillips57aa3672017-07-21 11:38:13 -0400283
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400284 GrTexturePriv::ComputeScratchKey(this->config(), width, height, SkToBool(rtp), sampleCount,
Greg Daniele252f082017-10-23 16:05:23 -0400285 mipMapped, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400286}
287
Robert Phillipsf2361d22016-10-25 14:20:06 -0400288void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400289#ifdef SK_DEBUG
Robert Phillipsf2361d22016-10-25 14:20:06 -0400290 if (fLastOpList) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400291 SkASSERT(fLastOpList->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +0000292 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400293#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -0400294
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400295 // Un-reffed
296 fLastOpList = opList;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400297}
Robert Phillips37430132016-11-09 06:50:43 -0500298
Brian Osman45580d32016-11-23 09:37:01 -0500299GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
300 return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
301}
302
303GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
304 return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
305}
306
Robert Phillipsa108c922017-10-10 10:42:19 -0400307int GrSurfaceProxy::worstCaseWidth() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500308 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400309 if (fTarget) {
310 return fTarget->width();
311 }
312
313 if (SkBackingFit::kExact == fFit) {
314 return fWidth;
315 }
316 return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fWidth));
317}
318
319int GrSurfaceProxy::worstCaseHeight() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500320 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400321 if (fTarget) {
322 return fTarget->height();
323 }
324
325 if (SkBackingFit::kExact == fFit) {
326 return fHeight;
327 }
328 return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fHeight));
329}
330
Brian Osman45580d32016-11-23 09:37:01 -0500331#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500332void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500333 if (fTarget) {
334 SkASSERT(fTarget->getContext() == context);
335 }
Brian Osman45580d32016-11-23 09:37:01 -0500336}
337#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500338
Robert Phillipsd44146b2019-02-15 14:44:28 -0500339sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500340 GrSurfaceProxy* src,
Greg Daniel65c7f662017-10-30 13:39:09 -0400341 GrMipMapped mipMapped,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500342 SkIRect srcRect,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500343 SkBackingFit fit,
Greg Daniel46cfbc62019-06-07 11:43:30 -0400344 SkBudgeted budgeted,
345 RectsMustMatch rectsMustMatch) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500346 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Greg Daniel46cfbc62019-06-07 11:43:30 -0400347 GrSurfaceDesc dstDesc;
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400348 dstDesc.fIsProtected = src->isProtected() ? GrProtected::kYes : GrProtected::kNo;
Greg Daniel46cfbc62019-06-07 11:43:30 -0400349 dstDesc.fConfig = src->config();
350
351 SkIPoint dstPoint;
352 if (rectsMustMatch == RectsMustMatch::kYes) {
353 dstDesc.fWidth = src->width();
354 dstDesc.fHeight = src->height();
355 dstPoint = {srcRect.fLeft, srcRect.fTop};
356 } else {
357 dstDesc.fWidth = srcRect.width();
358 dstDesc.fHeight = srcRect.height();
359 dstPoint = {0, 0};
360 }
361
Robert Phillipse2f7d182016-12-15 09:23:05 -0500362 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
363 return nullptr;
364 }
Brian Salomond6287472019-06-24 15:50:07 -0400365 auto colorType = GrPixelConfigToColorType(src->config());
Greg Daniel46cfbc62019-06-07 11:43:30 -0400366 if (src->backendFormat().textureType() != GrTextureType::kExternal) {
367 sk_sp<GrSurfaceContext> dstContext(context->priv().makeDeferredSurfaceContext(
368 src->backendFormat().makeTexture2D(), dstDesc, src->origin(), mipMapped, fit,
Brian Salomond6287472019-06-24 15:50:07 -0400369 budgeted, colorType, kUnknown_SkAlphaType));
Greg Daniel46cfbc62019-06-07 11:43:30 -0400370 if (!dstContext) {
371 return nullptr;
372 }
373 if (dstContext->copy(src, srcRect, dstPoint)) {
374 return dstContext->asTextureProxyRef();
375 }
Greg Danielc5167c02019-06-05 17:36:53 +0000376 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400377 if (src->asTextureProxy()) {
378 GrBackendFormat format = src->backendFormat().makeTexture2D();
379 if (!format.isValid()) {
380 return nullptr;
381 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400382
Greg Daniel46cfbc62019-06-07 11:43:30 -0400383 sk_sp<GrRenderTargetContext> dstContext = context->priv().makeDeferredRenderTargetContext(
Brian Salomond6287472019-06-24 15:50:07 -0400384 format, fit, dstDesc.fWidth, dstDesc.fHeight, dstDesc.fConfig, colorType, nullptr,
385 1, mipMapped, src->origin(), nullptr, budgeted);
Greg Daniel46cfbc62019-06-07 11:43:30 -0400386
387 if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
388 return dstContext->asTextureProxyRef();
389 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400390 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400391 // Can't use backend copies or draws.
392 return nullptr;
Robert Phillips63c67462017-02-15 14:19:01 -0500393}
394
Robert Phillipsd44146b2019-02-15 14:44:28 -0500395sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500396 GrMipMapped mipMapped, SkBackingFit fit,
397 SkBudgeted budgeted) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500398 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500399 return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
400 budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500401}
402
Robert Phillipsb5204762019-06-19 14:12:13 -0400403#if GR_TEST_UTILS
404int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
405 if (fTarget) {
406 return fTarget->testingOnly_getRefCnt();
407 }
408
409 return -1; // no backing GrSurface
410}
411
412GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
413 return fSurfaceFlags;
414}
415#endif
416
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400417void GrSurfaceProxyPriv::exactify() {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500418 SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400419 if (this->isExact()) {
420 return;
421 }
422
423 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
424
425 if (fProxy->fTarget) {
426 // The kApprox but already instantiated case. Setting the proxy's width & height to
427 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400428 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400429 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
430 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400431 fProxy->fWidth = fProxy->fTarget->width();
432 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400433 return;
434 }
435
436 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
437 // It could mess things up if prior decisions were based on the approximate size.
438 fProxy->fFit = SkBackingFit::kExact;
439 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400440 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400441 // the special image goes away. If it hasn't been computed yet it might as well compute the
442 // exact amount.
443}
444
Greg Danielbddcc952018-01-24 13:22:24 -0500445bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500446 SkASSERT(GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700447
Robert Phillips0790f8a2018-09-18 13:11:03 -0400448 sk_sp<GrSurface> surface;
449 if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
450 // First try to reattach to a cached version if the proxy is uniquely keyed
451 surface = resourceProvider->findByUniqueKey<GrSurface>(
452 fProxy->asTextureProxy()->getUniqueKey());
453 }
454
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400455 bool syncKey = true;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400456 if (!surface) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400457 auto result = fProxy->fLazyInstantiateCallback(resourceProvider);
458 surface = std::move(result.fSurface);
459 syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400460 }
Greg Daniel457469c2018-02-08 15:05:44 -0500461 if (GrSurfaceProxy::LazyInstantiationType::kSingleUse == fProxy->fLazyInstantiationType) {
Greg Daniel457469c2018-02-08 15:05:44 -0500462 fProxy->fLazyInstantiateCallback = nullptr;
463 }
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
Robert Phillipsc1b60662018-06-26 10:20:08 -0400470 if (fProxy->fWidth <= 0 || fProxy->fHeight <= 0) {
471 // 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.
474 SkASSERT(fProxy->fWidth <= 0 && fProxy->fHeight <= 0);
475 fProxy->fWidth = surface->width();
476 fProxy->fHeight = surface->height();
477 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700478
Chris Daltonf91b7552019-04-29 16:21:18 -0600479 SkASSERT(fProxy->fWidth <= surface->width());
480 SkASSERT(fProxy->fHeight <= surface->height());
481
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500482 bool needsStencil = fProxy->asRenderTargetProxy()
483 ? fProxy->asRenderTargetProxy()->needsStencil()
484 : false;
485
Robert Phillips01a91282018-07-26 08:03:04 -0400486 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(), needsStencil)) {
487 return false;
488 }
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500489
Greg Daniel303e83e2018-09-10 14:10:19 -0400490 if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400491 texProxy->setTargetKeySync(syncKey);
492 if (syncKey) {
493 const GrUniqueKey& key = texProxy->getUniqueKey();
494 if (key.isValid()) {
495 if (!surface->asTexture()->getUniqueKey().isValid()) {
496 // If 'surface' is newly created, attach the unique key
497 resourceProvider->assignUniqueKeyToResource(key, surface.get());
498 } else {
499 // otherwise we had better have reattached to a cached version
500 SkASSERT(surface->asTexture()->getUniqueKey() == key);
501 }
Robert Phillips0790f8a2018-09-18 13:11:03 -0400502 } else {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400503 SkASSERT(!surface->getUniqueKey().isValid());
Robert Phillips0790f8a2018-09-18 13:11:03 -0400504 }
Greg Daniel303e83e2018-09-10 14:10:19 -0400505 }
506 }
507
Robert Phillipse8fabb22018-02-04 14:33:21 -0500508 this->assign(std::move(surface));
Greg Danielbddcc952018-01-24 13:22:24 -0500509 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700510}
511
Greg Daniel849dce12018-04-24 14:32:53 -0400512#ifdef SK_DEBUG
513void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
514 SkASSERT(surface->config() == fConfig);
515
Greg Daniel849dce12018-04-24 14:32:53 -0400516 this->onValidateSurface(surface);
517}
518#endif