blob: ec718c0f8792c9956626ca103cbbd1ecb0f5131e [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
8#include "GrSurfaceProxy.h"
Robert Phillipsb726d582017-03-09 16:36:32 -05009#include "GrSurfaceProxyPriv.h"
robertphillips76948d42016-05-04 12:47:41 -070010
Robert Phillips784b7bf2016-12-09 13:35:02 -050011#include "GrCaps.h"
Robert Phillipse2f7d182016-12-15 09:23:05 -050012#include "GrContext.h"
13#include "GrContextPriv.h"
Robert Phillipsc7635fa2016-10-28 13:25:24 -040014#include "GrGpuResourcePriv.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040015#include "GrOpList.h"
Robert Phillips1afd4cd2018-01-08 13:40:32 -050016#include "GrProxyProvider.h"
Robert Phillipsd44146b2019-02-15 14:44:28 -050017#include "GrRecordingContext.h"
18#include "GrRecordingContextPriv.h"
Robert Phillipse2f7d182016-12-15 09:23:05 -050019#include "GrSurfaceContext.h"
Robert Phillipsfe0253f2018-03-16 16:47:25 -040020#include "GrSurfacePriv.h"
Robert Phillipsa4c41b32017-03-15 13:02:45 -040021#include "GrTexturePriv.h"
Robert Phillips37430132016-11-09 06:50:43 -050022#include "GrTextureRenderTargetProxy.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040023
Robert Phillips93f16332016-11-23 19:37:13 -050024#include "SkMathPriv.h"
Greg Daniele1da1d92017-10-06 15:59:27 -040025#include "SkMipMap.h"
Robert Phillips93f16332016-11-23 19:37:13 -050026
Greg Daniel65fa8ca2018-01-10 17:06:31 -050027#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -050028#include "GrRenderTarget.h"
29#include "GrRenderTargetPriv.h"
30
Greg Daniel65fa8ca2018-01-10 17:06:31 -050031static bool is_valid_fully_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
32 return desc.fWidth <= 0 &&
33 desc.fHeight <= 0 &&
34 desc.fConfig != kUnknown_GrPixelConfig &&
Brian Salomonbdecacf2018-02-02 20:32:49 -050035 desc.fSampleCnt == 1 &&
Greg Daniel65fa8ca2018-01-10 17:06:31 -050036 SkBackingFit::kApprox == fit;
37}
38
39static bool is_valid_partially_lazy(const GrSurfaceDesc& desc) {
40 return ((desc.fWidth > 0 && desc.fHeight > 0) ||
41 (desc.fWidth <= 0 && desc.fHeight <= 0)) &&
42 desc.fConfig != kUnknown_GrPixelConfig;
43}
44
45static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
46 return desc.fWidth > 0 &&
47 desc.fHeight > 0 &&
48 desc.fConfig != kUnknown_GrPixelConfig;
49}
50#endif
51
Chris Dalton706a6ff2017-11-29 22:01:06 -070052// Lazy-callback version
Greg Daniel457469c2018-02-08 15:05:44 -050053GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, LazyInstantiationType lazyType,
Greg Daniel4065d452018-11-16 15:43:41 -050054 const GrBackendFormat& format, const GrSurfaceDesc& desc,
55 GrSurfaceOrigin origin, SkBackingFit fit,
Robert Phillipsfe0253f2018-03-16 16:47:25 -040056 SkBudgeted budgeted, GrInternalSurfaceFlags surfaceFlags)
Greg Daniele3204862018-04-16 11:24:10 -040057 : fSurfaceFlags(surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -050058 , fFormat(format)
Greg Daniele3204862018-04-16 11:24:10 -040059 , fConfig(desc.fConfig)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050060 , fWidth(desc.fWidth)
61 , fHeight(desc.fHeight)
Brian Salomon2a4f9832018-03-03 22:43:43 -050062 , fOrigin(origin)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050063 , fFit(fit)
64 , fBudgeted(budgeted)
Chris Dalton706a6ff2017-11-29 22:01:06 -070065 , fLazyInstantiateCallback(std::move(callback))
Greg Daniel457469c2018-02-08 15:05:44 -050066 , fLazyInstantiationType(lazyType)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050067 , fNeedsClear(SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag))
Chris Dalton706a6ff2017-11-29 22:01:06 -070068 , fGpuMemorySize(kInvalidGpuMemorySize)
69 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -050070 SkASSERT(fFormat.isValid());
Chris Dalton706a6ff2017-11-29 22:01:06 -070071 // NOTE: the default fUniqueID ctor pulls a value from the same pool as the GrGpuResources.
Greg Daniel65fa8ca2018-01-10 17:06:31 -050072 if (fLazyInstantiateCallback) {
73 SkASSERT(is_valid_fully_lazy(desc, fit) || is_valid_partially_lazy(desc));
74 } else {
75 SkASSERT(is_valid_non_lazy(desc));
76 }
Jim Van Verth1676cb92019-01-15 13:24:45 -050077
78 if (GrPixelConfigIsCompressed(desc.fConfig)) {
79 SkASSERT(!SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag));
80 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
81 }
Chris Dalton706a6ff2017-11-29 22:01:06 -070082}
83
84// Wrapped version
Robert Phillips066f0202017-07-25 10:16:35 -040085GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin, SkBackingFit fit)
Brian Salomonbb5711a2017-05-17 13:49:59 -040086 : INHERITED(std::move(surface))
Greg Daniele3204862018-04-16 11:24:10 -040087 , fSurfaceFlags(fTarget->surfacePriv().flags())
Greg Daniel4065d452018-11-16 15:43:41 -050088 , fFormat(fTarget->backendFormat())
Brian Salomonbb5711a2017-05-17 13:49:59 -040089 , fConfig(fTarget->config())
90 , fWidth(fTarget->width())
91 , fHeight(fTarget->height())
Robert Phillips066f0202017-07-25 10:16:35 -040092 , fOrigin(origin)
Brian Salomonbb5711a2017-05-17 13:49:59 -040093 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -050094 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
95 ? SkBudgeted::kYes
96 : SkBudgeted::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -040097 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Brian Salomond17b4a62017-05-23 16:53:47 -040098 , fNeedsClear(false)
Brian Salomonbb5711a2017-05-17 13:49:59 -040099 , fGpuMemorySize(kInvalidGpuMemorySize)
Robert Phillips019ff272017-07-24 14:47:57 -0400100 , fLastOpList(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -0500101 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400102}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400103
Robert Phillipsf2361d22016-10-25 14:20:06 -0400104GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400105 // For this to be deleted the opList that held a ref on it (if there was one) must have been
106 // deleted. Which would have cleared out this back pointer.
107 SkASSERT(!fLastOpList);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400108}
109
Robert Phillipseafd48a2017-11-16 07:52:08 -0500110bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
111 GrSurface* surface, bool needsStencil) {
Robert Phillips65048132017-08-10 08:44:49 -0400112 if (needsStencil) {
113 GrRenderTarget* rt = surface->asRenderTarget();
114 if (!rt) {
115 SkASSERT(0);
116 return false;
117 }
118
119 if (!resourceProvider->attachStencilAttachment(rt)) {
120 return false;
121 }
122 }
123
124 return true;
125}
126
Robert Phillipsba5c4392018-07-25 12:37:14 -0400127sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
128 int sampleCnt, bool needsStencil,
129 GrSurfaceDescFlags descFlags,
130 GrMipMapped mipMapped) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500131 SkASSERT(GrSurfaceProxy::LazyState::kNot == this->lazyInstantiationState());
Greg Danield2d8e922018-02-12 12:07:39 -0500132 SkASSERT(!fTarget);
Brian Salomonbb5711a2017-05-17 13:49:59 -0400133 GrSurfaceDesc desc;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400134 desc.fFlags = descFlags;
Brian Salomond17b4a62017-05-23 16:53:47 -0400135 if (fNeedsClear) {
136 desc.fFlags |= kPerformInitialClear_GrSurfaceFlag;
137 }
Robert Phillips16d8ec62017-07-27 16:16:25 -0400138 desc.fWidth = fWidth;
139 desc.fHeight = fHeight;
140 desc.fConfig = fConfig;
141 desc.fSampleCnt = sampleCnt;
Robert Phillipseaa86252016-11-08 13:49:39 +0000142
Chris Daltond004e0b2018-09-27 09:28:03 -0600143 GrResourceProvider::Flags resourceProviderFlags = GrResourceProvider::Flags::kNone;
144 if ((fSurfaceFlags & GrInternalSurfaceFlags::kNoPendingIO) ||
Robert Phillipsba5c4392018-07-25 12:37:14 -0400145 resourceProvider->explicitlyAllocateGPUResources()) {
146 // The explicit resource allocator requires that any resources it pulls out of the
147 // cache have no pending IO.
Chris Daltond004e0b2018-09-27 09:28:03 -0600148 resourceProviderFlags = GrResourceProvider::Flags::kNoPendingIO;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400149 }
150
Robert Phillips5af44de2017-07-18 14:49:38 -0400151 sk_sp<GrSurface> surface;
Greg Danielf6f7b672018-02-15 13:06:26 -0500152 if (GrMipMapped::kYes == mipMapped) {
153 SkASSERT(SkBackingFit::kExact == fFit);
154
155 // SkMipMap doesn't include the base level in the level count so we have to add 1
156 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
157 // We should have caught the case where mipCount == 1 when making the proxy and instead
158 // created a non-mipmapped proxy.
159 SkASSERT(mipCount > 1);
160 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
161
162 // We don't want to upload any texel data
163 for (int i = 0; i < mipCount; i++) {
164 texels[i].fPixels = nullptr;
165 texels[i].fRowBytes = 0;
166 }
167
Brian Osman2b23c4b2018-06-01 12:25:08 -0400168 surface = resourceProvider->createTexture(desc, fBudgeted, texels.get(), mipCount);
Greg Danielf6f7b672018-02-15 13:06:26 -0500169 if (surface) {
170 SkASSERT(surface->asTexture());
171 SkASSERT(GrMipMapped::kYes == surface->asTexture()->texturePriv().mipMapped());
172 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000173 } else {
Greg Danielf6f7b672018-02-15 13:06:26 -0500174 if (SkBackingFit::kApprox == fFit) {
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400175 surface = resourceProvider->createApproxTexture(desc, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500176 } else {
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400177 surface = resourceProvider->createTexture(desc, fBudgeted, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500178 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000179 }
Robert Phillips65048132017-08-10 08:44:49 -0400180 if (!surface) {
181 return nullptr;
182 }
183
Robert Phillipseafd48a2017-11-16 07:52:08 -0500184 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(), needsStencil)) {
Robert Phillips65048132017-08-10 08:44:49 -0400185 return nullptr;
Robert Phillipseaa86252016-11-08 13:49:39 +0000186 }
187
Robert Phillips5af44de2017-07-18 14:49:38 -0400188 return surface;
189}
190
Brian Salomon7d94bb52018-10-12 14:37:19 -0400191bool GrSurfaceProxy::canSkipResourceAllocator() const {
192 auto peek = this->peekSurface();
193 if (!peek) {
194 return false;
195 }
196 // If this resource is already allocated and not recyclable then the resource allocator does
197 // not need to do anything with it.
198 return !peek->resourcePriv().getScratchKey().isValid();
199}
200
Robert Phillips5af44de2017-07-18 14:49:38 -0400201void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
202 SkASSERT(!fTarget && surface);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400203
Greg Daniel849dce12018-04-24 14:32:53 -0400204 SkDEBUGCODE(this->validateSurface(surface.get());)
Robert Phillipsabf7b762018-03-21 12:13:37 -0400205
Robert Phillips5af44de2017-07-18 14:49:38 -0400206 fTarget = surface.release();
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500207
robertphillips1125a032016-11-16 11:17:17 -0800208 this->INHERITED::transferRefs();
209
Robert Phillipseaa86252016-11-08 13:49:39 +0000210#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500211 if (this->asRenderTargetProxy()) {
212 SkASSERT(fTarget->asRenderTarget());
213 if (this->asRenderTargetProxy()->needsStencil()) {
214 SkASSERT(fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment());
215 }
216 }
217
Robert Phillipseaa86252016-11-08 13:49:39 +0000218 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500219 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +0000220 }
221#endif
Robert Phillips5af44de2017-07-18 14:49:38 -0400222}
Robert Phillipseaa86252016-11-08 13:49:39 +0000223
Robert Phillips5af44de2017-07-18 14:49:38 -0400224bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400225 bool needsStencil, GrSurfaceDescFlags descFlags,
226 GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500227 SkASSERT(LazyState::kNot == this->lazyInstantiationState());
Robert Phillips5af44de2017-07-18 14:49:38 -0400228 if (fTarget) {
Brian Salomon57904202018-12-17 14:45:00 -0500229 if (uniqueKey && uniqueKey->isValid()) {
230 SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400231 }
Robert Phillipseafd48a2017-11-16 07:52:08 -0500232 return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget, needsStencil);
Robert Phillips5af44de2017-07-18 14:49:38 -0400233 }
234
Robert Phillips65048132017-08-10 08:44:49 -0400235 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, needsStencil,
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400236 descFlags, mipMapped);
Robert Phillips5af44de2017-07-18 14:49:38 -0400237 if (!surface) {
238 return false;
239 }
240
Brian Osman28c434b2017-09-27 13:11:16 -0400241 // If there was an invalidation message pending for this key, we might have just processed it,
242 // causing the key (stored on this proxy) to become invalid.
243 if (uniqueKey && uniqueKey->isValid()) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400244 resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
245 }
246
Robert Phillips5af44de2017-07-18 14:49:38 -0400247 this->assign(std::move(surface));
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400248
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400249 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +0000250}
251
Brian Salomon967df202018-12-07 11:15:53 -0500252void GrSurfaceProxy::deinstantiate() {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400253 SkASSERT(this->isInstantiated());
Robert Phillips4bc70112018-03-01 10:24:02 -0500254
255 this->release();
256}
257
Robert Phillips57aa3672017-07-21 11:38:13 -0400258void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500259 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillips57aa3672017-07-21 11:38:13 -0400260 const GrRenderTargetProxy* rtp = this->asRenderTargetProxy();
Brian Salomonbdecacf2018-02-02 20:32:49 -0500261 int sampleCount = 1;
Robert Phillips57aa3672017-07-21 11:38:13 -0400262 if (rtp) {
263 sampleCount = rtp->numStencilSamples();
264 }
265
266 const GrTextureProxy* tp = this->asTextureProxy();
Greg Daniele252f082017-10-23 16:05:23 -0400267 GrMipMapped mipMapped = GrMipMapped::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400268 if (tp) {
Greg Daniele252f082017-10-23 16:05:23 -0400269 mipMapped = tp->mipMapped();
Robert Phillips57aa3672017-07-21 11:38:13 -0400270 }
271
Robert Phillipsa108c922017-10-10 10:42:19 -0400272 int width = this->worstCaseWidth();
273 int height = this->worstCaseHeight();
Robert Phillips57aa3672017-07-21 11:38:13 -0400274
Robert Phillipsb0e93a22017-08-29 08:26:54 -0400275 GrTexturePriv::ComputeScratchKey(this->config(), width, height, SkToBool(rtp), sampleCount,
Greg Daniele252f082017-10-23 16:05:23 -0400276 mipMapped, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400277}
278
Robert Phillipsf2361d22016-10-25 14:20:06 -0400279void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400280#ifdef SK_DEBUG
Robert Phillipsf2361d22016-10-25 14:20:06 -0400281 if (fLastOpList) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400282 SkASSERT(fLastOpList->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +0000283 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400284#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -0400285
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400286 // Un-reffed
287 fLastOpList = opList;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400288}
Robert Phillips37430132016-11-09 06:50:43 -0500289
Brian Osman45580d32016-11-23 09:37:01 -0500290GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
291 return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
292}
293
294GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
295 return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
296}
297
Robert Phillipsa108c922017-10-10 10:42:19 -0400298int GrSurfaceProxy::worstCaseWidth() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500299 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400300 if (fTarget) {
301 return fTarget->width();
302 }
303
304 if (SkBackingFit::kExact == fFit) {
305 return fWidth;
306 }
307 return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fWidth));
308}
309
310int GrSurfaceProxy::worstCaseHeight() 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->height();
314 }
315
316 if (SkBackingFit::kExact == fFit) {
317 return fHeight;
318 }
319 return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fHeight));
320}
321
Brian Osman45580d32016-11-23 09:37:01 -0500322#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500323void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500324 if (fTarget) {
325 SkASSERT(fTarget->getContext() == context);
326 }
327
328 INHERITED::validate();
329}
330#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500331
Robert Phillipsd44146b2019-02-15 14:44:28 -0500332sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500333 GrSurfaceProxy* src,
Greg Daniel65c7f662017-10-30 13:39:09 -0400334 GrMipMapped mipMapped,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500335 SkIRect srcRect,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500336 SkBackingFit fit,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500337 SkBudgeted budgeted) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500338 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Robert Phillipse2f7d182016-12-15 09:23:05 -0500339 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
340 return nullptr;
341 }
342
Brian Salomon63e79732017-05-15 21:23:13 -0400343 GrSurfaceDesc dstDesc;
Robert Phillipse2f7d182016-12-15 09:23:05 -0500344 dstDesc.fWidth = srcRect.width();
345 dstDesc.fHeight = srcRect.height();
Robert Phillips16d8ec62017-07-27 16:16:25 -0400346 dstDesc.fConfig = src->config();
Robert Phillipse2f7d182016-12-15 09:23:05 -0500347
Greg Daniel4065d452018-11-16 15:43:41 -0500348 GrBackendFormat format = src->backendFormat().makeTexture2D();
349 if (!format.isValid()) {
350 return nullptr;
351 }
352
Robert Phillips9da87e02019-02-04 13:26:26 -0500353 sk_sp<GrSurfaceContext> dstContext(context->priv().makeDeferredSurfaceContext(
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500354 format, dstDesc, src->origin(), mipMapped, fit, budgeted));
Robert Phillipse2f7d182016-12-15 09:23:05 -0500355 if (!dstContext) {
356 return nullptr;
357 }
358
359 if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) {
360 return nullptr;
361 }
362
Robert Phillips63c67462017-02-15 14:19:01 -0500363 return dstContext->asTextureProxyRef();
364}
365
Robert Phillipsd44146b2019-02-15 14:44:28 -0500366sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500367 GrMipMapped mipMapped, SkBackingFit fit,
368 SkBudgeted budgeted) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500369 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500370 return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
371 budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500372}
373
Robert Phillipsd44146b2019-02-15 14:44:28 -0500374sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrRecordingContext* context,
375 const GrSurfaceDesc& dstDesc,
Brian Salomon2a4f9832018-03-03 22:43:43 -0500376 GrSurfaceOrigin origin, GrSurfaceProxy* srcProxy) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500377 SkASSERT(LazyState::kFully != srcProxy->lazyInstantiationState());
Greg Daniel4065d452018-11-16 15:43:41 -0500378
379 GrBackendFormat format = srcProxy->backendFormat().makeTexture2D();
380 if (!format.isValid()) {
381 return nullptr;
382 }
383
Robert Phillips9da87e02019-02-04 13:26:26 -0500384 sk_sp<GrSurfaceContext> dstContext(context->priv().makeDeferredSurfaceContext(
Greg Daniel4065d452018-11-16 15:43:41 -0500385 format, dstDesc, origin, GrMipMapped::kNo, SkBackingFit::kExact, SkBudgeted::kYes));
Robert Phillipse2f7d182016-12-15 09:23:05 -0500386 if (!dstContext) {
387 return nullptr;
388 }
389
Robert Phillipsd46697a2017-01-25 12:10:37 -0500390 if (!dstContext->copy(srcProxy)) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500391 return nullptr;
392 }
393
Robert Phillipsd46697a2017-01-25 12:10:37 -0500394 return dstContext;
Robert Phillipse2f7d182016-12-15 09:23:05 -0500395}
Robert Phillipsb726d582017-03-09 16:36:32 -0500396
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400397void GrSurfaceProxyPriv::exactify() {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500398 SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400399 if (this->isExact()) {
400 return;
401 }
402
403 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
404
405 if (fProxy->fTarget) {
406 // The kApprox but already instantiated case. Setting the proxy's width & height to
407 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400408 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400409 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
410 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400411 fProxy->fWidth = fProxy->fTarget->width();
412 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400413 return;
414 }
415
416 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
417 // It could mess things up if prior decisions were based on the approximate size.
418 fProxy->fFit = SkBackingFit::kExact;
419 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400420 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400421 // the special image goes away. If it hasn't been computed yet it might as well compute the
422 // exact amount.
423}
424
Greg Danielbddcc952018-01-24 13:22:24 -0500425bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500426 SkASSERT(GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700427
Robert Phillips0790f8a2018-09-18 13:11:03 -0400428 sk_sp<GrSurface> surface;
429 if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
430 // First try to reattach to a cached version if the proxy is uniquely keyed
431 surface = resourceProvider->findByUniqueKey<GrSurface>(
432 fProxy->asTextureProxy()->getUniqueKey());
433 }
434
435 if (!surface) {
436 surface = fProxy->fLazyInstantiateCallback(resourceProvider);
437 }
Greg Daniel457469c2018-02-08 15:05:44 -0500438 if (GrSurfaceProxy::LazyInstantiationType::kSingleUse == fProxy->fLazyInstantiationType) {
Greg Daniel457469c2018-02-08 15:05:44 -0500439 fProxy->fLazyInstantiateCallback = nullptr;
440 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500441 if (!surface) {
Chris Dalton706a6ff2017-11-29 22:01:06 -0700442 fProxy->fWidth = 0;
443 fProxy->fHeight = 0;
Greg Danielbddcc952018-01-24 13:22:24 -0500444 return false;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700445 }
446
Robert Phillipsc1b60662018-06-26 10:20:08 -0400447 if (fProxy->fWidth <= 0 || fProxy->fHeight <= 0) {
448 // This was a fully lazy proxy. We need to fill in the width & height. For partially
449 // lazy proxies we must preserve the original width & height since that indicates
450 // the content area.
451 SkASSERT(fProxy->fWidth <= 0 && fProxy->fHeight <= 0);
452 fProxy->fWidth = surface->width();
453 fProxy->fHeight = surface->height();
454 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700455
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500456 bool needsStencil = fProxy->asRenderTargetProxy()
457 ? fProxy->asRenderTargetProxy()->needsStencil()
458 : false;
459
Robert Phillips01a91282018-07-26 08:03:04 -0400460 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(), needsStencil)) {
461 return false;
462 }
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500463
Greg Daniel303e83e2018-09-10 14:10:19 -0400464 if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
465 const GrUniqueKey& key = texProxy->getUniqueKey();
466 if (key.isValid()) {
Robert Phillips0790f8a2018-09-18 13:11:03 -0400467 if (!surface->asTexture()->getUniqueKey().isValid()) {
468 // If 'surface' is newly created, attach the unique key
469 resourceProvider->assignUniqueKeyToResource(key, surface.get());
470 } else {
471 // otherwise we had better have reattached to a cached version
472 SkASSERT(surface->asTexture()->getUniqueKey() == key);
473 }
Greg Daniel303e83e2018-09-10 14:10:19 -0400474 }
475 }
476
Robert Phillipse8fabb22018-02-04 14:33:21 -0500477 this->assign(std::move(surface));
Greg Danielbddcc952018-01-24 13:22:24 -0500478 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700479}
480
Greg Daniel849dce12018-04-24 14:32:53 -0400481#ifdef SK_DEBUG
482void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
483 SkASSERT(surface->config() == fConfig);
484
485 // Assert the flags are the same except for kNoPendingIO which is not passed onto the GrSurface.
486 GrInternalSurfaceFlags proxyFlags = fSurfaceFlags & ~GrInternalSurfaceFlags::kNoPendingIO;
487 GrInternalSurfaceFlags surfaceFlags = surface->surfacePriv().flags();
488 SkASSERT((proxyFlags & GrInternalSurfaceFlags::kSurfaceMask) ==
489 (surfaceFlags & GrInternalSurfaceFlags::kSurfaceMask));
490 this->onValidateSurface(surface);
491}
492#endif