blob: be13c0de2833081a9e0315d21ba7d6bc9bcddd0d [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 &&
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,
Brian Salomonf2c2ba92019-07-17 09:59:59 -040055 GrRenderable renderable, GrSurfaceOrigin origin,
56 const GrSwizzle& textureSwizzle, SkBackingFit fit,
Brian Salomone8a766b2019-07-19 14:24:36 -040057 SkBudgeted budgeted, GrProtected isProtected,
58 GrInternalSurfaceFlags surfaceFlags)
Greg Daniele3204862018-04-16 11:24:10 -040059 : fSurfaceFlags(surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -050060 , fFormat(format)
Greg Daniele3204862018-04-16 11:24:10 -040061 , fConfig(desc.fConfig)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050062 , fWidth(desc.fWidth)
63 , fHeight(desc.fHeight)
Brian Salomon2a4f9832018-03-03 22:43:43 -050064 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040065 , fTextureSwizzle(textureSwizzle)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050066 , fFit(fit)
67 , fBudgeted(budgeted)
Chris Dalton706a6ff2017-11-29 22:01:06 -070068 , fLazyInstantiateCallback(std::move(callback))
Greg Daniel457469c2018-02-08 15:05:44 -050069 , fLazyInstantiationType(lazyType)
Brian Salomone8a766b2019-07-19 14:24:36 -040070 , fIsProtected(isProtected)
Chris Dalton706a6ff2017-11-29 22:01:06 -070071 , fGpuMemorySize(kInvalidGpuMemorySize)
Chris Dalton6b498102019-08-01 14:14:52 -060072 , fLastRenderTask(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -050073 SkASSERT(fFormat.isValid());
Chris Dalton706a6ff2017-11-29 22:01:06 -070074 // NOTE: the default fUniqueID ctor pulls a value from the same pool as the GrGpuResources.
Greg Daniel65fa8ca2018-01-10 17:06:31 -050075 if (fLazyInstantiateCallback) {
76 SkASSERT(is_valid_fully_lazy(desc, fit) || is_valid_partially_lazy(desc));
77 } else {
78 SkASSERT(is_valid_non_lazy(desc));
79 }
Jim Van Verth1676cb92019-01-15 13:24:45 -050080
81 if (GrPixelConfigIsCompressed(desc.fConfig)) {
Brian Salomonf2c2ba92019-07-17 09:59:59 -040082 SkASSERT(renderable == GrRenderable::kNo);
Jim Van Verth1676cb92019-01-15 13:24:45 -050083 fSurfaceFlags |= GrInternalSurfaceFlags::kReadOnly;
84 }
Chris Dalton706a6ff2017-11-29 22:01:06 -070085}
86
87// Wrapped version
Greg Daniel2c19e7f2019-06-18 13:29:21 -040088GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin,
89 const GrSwizzle& textureSwizzle, SkBackingFit fit)
Robert Phillipsb5204762019-06-19 14:12:13 -040090 : fTarget(std::move(surface))
Greg Daniele3204862018-04-16 11:24:10 -040091 , fSurfaceFlags(fTarget->surfacePriv().flags())
Greg Daniel4065d452018-11-16 15:43:41 -050092 , fFormat(fTarget->backendFormat())
Brian Salomonbb5711a2017-05-17 13:49:59 -040093 , fConfig(fTarget->config())
94 , fWidth(fTarget->width())
95 , fHeight(fTarget->height())
Robert Phillips066f0202017-07-25 10:16:35 -040096 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040097 , fTextureSwizzle(textureSwizzle)
Brian Salomonbb5711a2017-05-17 13:49:59 -040098 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -050099 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
100 ? SkBudgeted::kYes
101 : SkBudgeted::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400102 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400103 , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400104 , fGpuMemorySize(kInvalidGpuMemorySize)
Chris Dalton6b498102019-08-01 14:14:52 -0600105 , fLastRenderTask(nullptr) {
Greg Daniel4065d452018-11-16 15:43:41 -0500106 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400107}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400108
Robert Phillipsf2361d22016-10-25 14:20:06 -0400109GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400110 // For this to be deleted the opList that held a ref on it (if there was one) must have been
111 // deleted. Which would have cleared out this back pointer.
Chris Dalton6b498102019-08-01 14:14:52 -0600112 SkASSERT(!fLastRenderTask);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400113}
114
Robert Phillipseafd48a2017-11-16 07:52:08 -0500115bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
Chris Daltoneffee202019-07-01 22:28:03 -0600116 GrSurface* surface, int minStencilSampleCount) {
117 if (minStencilSampleCount) {
Robert Phillips65048132017-08-10 08:44:49 -0400118 GrRenderTarget* rt = surface->asRenderTarget();
119 if (!rt) {
120 SkASSERT(0);
121 return false;
122 }
123
Chris Daltoneffee202019-07-01 22:28:03 -0600124 if (!resourceProvider->attachStencilAttachment(rt, minStencilSampleCount)) {
Robert Phillips65048132017-08-10 08:44:49 -0400125 return false;
126 }
127 }
128
129 return true;
130}
131
Robert Phillipsba5c4392018-07-25 12:37:14 -0400132sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400133 int sampleCnt,
134 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;
Robert Phillipseaa86252016-11-08 13:49:39 +0000143
Robert Phillips10d17212019-04-24 14:09:10 -0400144 // The explicit resource allocator requires that any resources it pulls out of the
145 // cache have no pending IO.
146 GrResourceProvider::Flags resourceProviderFlags = GrResourceProvider::Flags::kNoPendingIO;
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400147
Robert Phillips5af44de2017-07-18 14:49:38 -0400148 sk_sp<GrSurface> surface;
Greg Danielf6f7b672018-02-15 13:06:26 -0500149 if (GrMipMapped::kYes == mipMapped) {
150 SkASSERT(SkBackingFit::kExact == fFit);
151
152 // SkMipMap doesn't include the base level in the level count so we have to add 1
153 int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
154 // We should have caught the case where mipCount == 1 when making the proxy and instead
155 // created a non-mipmapped proxy.
156 SkASSERT(mipCount > 1);
157 std::unique_ptr<GrMipLevel[]> texels(new GrMipLevel[mipCount]);
158
159 // We don't want to upload any texel data
160 for (int i = 0; i < mipCount; i++) {
161 texels[i].fPixels = nullptr;
162 texels[i].fRowBytes = 0;
163 }
Brian Salomon4eb38b72019-08-05 12:58:39 -0400164 surface = resourceProvider->createTexture(desc, fFormat, renderable, sampleCnt, fBudgeted,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400165 fIsProtected, texels.get(), mipCount);
Chris Dalton95d8ceb2019-07-30 11:17:59 -0600166#ifdef SK_DEBUG
Greg Danielf6f7b672018-02-15 13:06:26 -0500167 if (surface) {
Chris Dalton95d8ceb2019-07-30 11:17:59 -0600168 const GrTextureProxy* thisTexProxy = this->asTextureProxy();
169 SkASSERT(thisTexProxy);
170
171 GrTexture* texture = surface->asTexture();
172 SkASSERT(texture);
173
174 SkASSERT(GrMipMapped::kYes == texture->texturePriv().mipMapped());
175 SkASSERT(thisTexProxy->fInitialMipMapsStatus == texture->texturePriv().mipMapsStatus());
Greg Danielf6f7b672018-02-15 13:06:26 -0500176 }
Chris Dalton95d8ceb2019-07-30 11:17:59 -0600177#endif
Robert Phillipseaa86252016-11-08 13:49:39 +0000178 } else {
Greg Danielf6f7b672018-02-15 13:06:26 -0500179 if (SkBackingFit::kApprox == fFit) {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400180 surface = resourceProvider->createApproxTexture(desc, fFormat, renderable, sampleCnt,
Brian Salomon27b4d8d2019-07-22 14:23:45 -0400181 fIsProtected, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500182 } else {
Brian Salomon4eb38b72019-08-05 12:58:39 -0400183 surface =
184 resourceProvider->createTexture(desc, fFormat, renderable, sampleCnt, fBudgeted,
185 fIsProtected, resourceProviderFlags);
Greg Danielf6f7b672018-02-15 13:06:26 -0500186 }
Robert Phillipseaa86252016-11-08 13:49:39 +0000187 }
Robert Phillips65048132017-08-10 08:44:49 -0400188 if (!surface) {
189 return nullptr;
190 }
191
Robert Phillipse5f73282019-06-18 17:15:04 -0400192 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(),
Chris Daltoneffee202019-07-01 22:28:03 -0600193 minStencilSampleCount)) {
Robert Phillips65048132017-08-10 08:44:49 -0400194 return nullptr;
Robert Phillipseaa86252016-11-08 13:49:39 +0000195 }
196
Robert Phillips5af44de2017-07-18 14:49:38 -0400197 return surface;
198}
199
Brian Salomon7d94bb52018-10-12 14:37:19 -0400200bool GrSurfaceProxy::canSkipResourceAllocator() const {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400201 if (this->ignoredByResourceAllocator()) {
202 // Usually an atlas or onFlush proxy
203 return true;
204 }
205
Brian Salomon7d94bb52018-10-12 14:37:19 -0400206 auto peek = this->peekSurface();
207 if (!peek) {
208 return false;
209 }
210 // If this resource is already allocated and not recyclable then the resource allocator does
211 // not need to do anything with it.
212 return !peek->resourcePriv().getScratchKey().isValid();
213}
214
Robert Phillips5af44de2017-07-18 14:49:38 -0400215void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
216 SkASSERT(!fTarget && surface);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400217
Greg Daniel849dce12018-04-24 14:32:53 -0400218 SkDEBUGCODE(this->validateSurface(surface.get());)
Robert Phillipsabf7b762018-03-21 12:13:37 -0400219
Robert Phillipse5f73282019-06-18 17:15:04 -0400220 fTarget = std::move(surface);
robertphillips1125a032016-11-16 11:17:17 -0800221
Robert Phillipseaa86252016-11-08 13:49:39 +0000222#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500223 if (this->asRenderTargetProxy()) {
224 SkASSERT(fTarget->asRenderTarget());
Chris Daltoneffee202019-07-01 22:28:03 -0600225 if (int minStencilSampleCount = this->asRenderTargetProxy()->numStencilSamples()) {
226 auto* stencil = fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment();
227 SkASSERT(stencil);
228 SkASSERT(stencil->numSamples() >= minStencilSampleCount);
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500229 }
230 }
231
Robert Phillipseaa86252016-11-08 13:49:39 +0000232 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500233 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +0000234 }
235#endif
Robert Phillips5af44de2017-07-18 14:49:38 -0400236}
Robert Phillipseaa86252016-11-08 13:49:39 +0000237
Robert Phillips5af44de2017-07-18 14:49:38 -0400238bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400239 int minStencilSampleCount, GrRenderable renderable,
Robert Phillips10d17212019-04-24 14:09:10 -0400240 GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500241 SkASSERT(LazyState::kNot == this->lazyInstantiationState());
Robert Phillips5af44de2017-07-18 14:49:38 -0400242 if (fTarget) {
Brian Salomon57904202018-12-17 14:45:00 -0500243 if (uniqueKey && uniqueKey->isValid()) {
244 SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400245 }
Robert Phillipse5f73282019-06-18 17:15:04 -0400246 return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget.get(),
Chris Daltoneffee202019-07-01 22:28:03 -0600247 minStencilSampleCount);
Robert Phillips5af44de2017-07-18 14:49:38 -0400248 }
249
Chris Daltoneffee202019-07-01 22:28:03 -0600250 sk_sp<GrSurface> surface = this->createSurfaceImpl(
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400251 resourceProvider, sampleCnt, minStencilSampleCount, renderable, mipMapped);
Robert Phillips5af44de2017-07-18 14:49:38 -0400252 if (!surface) {
253 return false;
254 }
255
Brian Osman28c434b2017-09-27 13:11:16 -0400256 // If there was an invalidation message pending for this key, we might have just processed it,
257 // causing the key (stored on this proxy) to become invalid.
258 if (uniqueKey && uniqueKey->isValid()) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400259 resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
260 }
261
Robert Phillips5af44de2017-07-18 14:49:38 -0400262 this->assign(std::move(surface));
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400263
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400264 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +0000265}
266
Brian Salomon967df202018-12-07 11:15:53 -0500267void GrSurfaceProxy::deinstantiate() {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400268 SkASSERT(this->isInstantiated());
Robert Phillipse5f73282019-06-18 17:15:04 -0400269 fTarget = nullptr;
Robert Phillips4bc70112018-03-01 10:24:02 -0500270}
271
Robert Phillips57aa3672017-07-21 11:38:13 -0400272void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500273 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400274 GrRenderable renderable = GrRenderable::kNo;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500275 int sampleCount = 1;
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400276 if (const auto* rtp = this->asRenderTargetProxy()) {
277 renderable = GrRenderable::kYes;
Chris Dalton6ce447a2019-06-23 18:07:38 -0600278 sampleCount = rtp->numSamples();
Robert Phillips57aa3672017-07-21 11:38:13 -0400279 }
280
281 const GrTextureProxy* tp = this->asTextureProxy();
Greg Daniele252f082017-10-23 16:05:23 -0400282 GrMipMapped mipMapped = GrMipMapped::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400283 if (tp) {
Greg Daniele252f082017-10-23 16:05:23 -0400284 mipMapped = tp->mipMapped();
Robert Phillips57aa3672017-07-21 11:38:13 -0400285 }
286
Robert Phillipsa108c922017-10-10 10:42:19 -0400287 int width = this->worstCaseWidth();
288 int height = this->worstCaseHeight();
Robert Phillips57aa3672017-07-21 11:38:13 -0400289
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400290 GrTexturePriv::ComputeScratchKey(this->config(), width, height, renderable, sampleCount,
Greg Daniele252f082017-10-23 16:05:23 -0400291 mipMapped, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400292}
293
Chris Dalton6b498102019-08-01 14:14:52 -0600294void GrSurfaceProxy::setLastRenderTask(GrRenderTask* renderTask) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400295#ifdef SK_DEBUG
Chris Dalton6b498102019-08-01 14:14:52 -0600296 if (fLastRenderTask) {
297 SkASSERT(fLastRenderTask->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +0000298 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400299#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -0400300
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400301 // Un-reffed
Chris Dalton6b498102019-08-01 14:14:52 -0600302 fLastRenderTask = renderTask;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400303}
Robert Phillips37430132016-11-09 06:50:43 -0500304
Brian Osman45580d32016-11-23 09:37:01 -0500305GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
Chris Dalton6b498102019-08-01 14:14:52 -0600306 return fLastRenderTask ? fLastRenderTask->asRenderTargetOpList() : nullptr;
Brian Osman45580d32016-11-23 09:37:01 -0500307}
308
309GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
Chris Dalton6b498102019-08-01 14:14:52 -0600310 return fLastRenderTask ? fLastRenderTask->asTextureOpList() : nullptr;
Brian Osman45580d32016-11-23 09:37:01 -0500311}
312
Robert Phillipsa108c922017-10-10 10:42:19 -0400313int GrSurfaceProxy::worstCaseWidth() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500314 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400315 if (fTarget) {
316 return fTarget->width();
317 }
318
319 if (SkBackingFit::kExact == fFit) {
320 return fWidth;
321 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400322 return GrResourceProvider::MakeApprox(fWidth);
Robert Phillipsa108c922017-10-10 10:42:19 -0400323}
324
325int GrSurfaceProxy::worstCaseHeight() const {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500326 SkASSERT(LazyState::kFully != this->lazyInstantiationState());
Robert Phillipsa108c922017-10-10 10:42:19 -0400327 if (fTarget) {
328 return fTarget->height();
329 }
330
331 if (SkBackingFit::kExact == fFit) {
332 return fHeight;
333 }
Robert Phillipsf9fcf7f2019-07-11 09:03:27 -0400334 return GrResourceProvider::MakeApprox(fHeight);
Robert Phillipsa108c922017-10-10 10:42:19 -0400335}
336
Brian Osman45580d32016-11-23 09:37:01 -0500337#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500338void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500339 if (fTarget) {
340 SkASSERT(fTarget->getContext() == context);
341 }
Brian Osman45580d32016-11-23 09:37:01 -0500342}
343#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500344
Robert Phillipsd44146b2019-02-15 14:44:28 -0500345sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500346 GrSurfaceProxy* src,
Greg Daniel65c7f662017-10-30 13:39:09 -0400347 GrMipMapped mipMapped,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500348 SkIRect srcRect,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500349 SkBackingFit fit,
Greg Daniel46cfbc62019-06-07 11:43:30 -0400350 SkBudgeted budgeted,
351 RectsMustMatch rectsMustMatch) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500352 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Brian Salomon947efe22019-07-16 15:36:11 -0400353 GrProtected isProtected = src->isProtected() ? GrProtected::kYes : GrProtected::kNo;
354 int width;
355 int height;
Greg Daniel46cfbc62019-06-07 11:43:30 -0400356
357 SkIPoint dstPoint;
358 if (rectsMustMatch == RectsMustMatch::kYes) {
Brian Salomon947efe22019-07-16 15:36:11 -0400359 width = src->width();
360 height = src->height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400361 dstPoint = {srcRect.fLeft, srcRect.fTop};
362 } else {
Brian Salomon947efe22019-07-16 15:36:11 -0400363 width = srcRect.width();
364 height = srcRect.height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400365 dstPoint = {0, 0};
366 }
367
Robert Phillipse2f7d182016-12-15 09:23:05 -0500368 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
369 return nullptr;
370 }
Brian Salomond6287472019-06-24 15:50:07 -0400371 auto colorType = GrPixelConfigToColorType(src->config());
Greg Daniel46cfbc62019-06-07 11:43:30 -0400372 if (src->backendFormat().textureType() != GrTextureType::kExternal) {
Brian Salomon947efe22019-07-16 15:36:11 -0400373 sk_sp<GrTextureContext> dstContext(context->priv().makeDeferredTextureContext(
374 fit, width, height, colorType, kUnknown_SkAlphaType, nullptr, mipMapped,
375 src->origin(), budgeted, isProtected));
Greg Daniel46cfbc62019-06-07 11:43:30 -0400376 if (!dstContext) {
377 return nullptr;
378 }
379 if (dstContext->copy(src, srcRect, dstPoint)) {
380 return dstContext->asTextureProxyRef();
381 }
Greg Danielc5167c02019-06-05 17:36:53 +0000382 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400383 if (src->asTextureProxy()) {
Greg Daniel46cfbc62019-06-07 11:43:30 -0400384 sk_sp<GrRenderTargetContext> dstContext = context->priv().makeDeferredRenderTargetContext(
Brian Salomon947efe22019-07-16 15:36:11 -0400385 fit, width, height, colorType, nullptr, 1, mipMapped, src->origin(), nullptr,
386 budgeted);
Greg Daniel46cfbc62019-06-07 11:43:30 -0400387
388 if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
389 return dstContext->asTextureProxyRef();
390 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400391 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400392 // Can't use backend copies or draws.
393 return nullptr;
Robert Phillips63c67462017-02-15 14:19:01 -0500394}
395
Robert Phillipsd44146b2019-02-15 14:44:28 -0500396sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500397 GrMipMapped mipMapped, SkBackingFit fit,
398 SkBudgeted budgeted) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500399 SkASSERT(LazyState::kFully != src->lazyInstantiationState());
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500400 return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), fit,
401 budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500402}
403
Robert Phillipsb5204762019-06-19 14:12:13 -0400404#if GR_TEST_UTILS
405int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
406 if (fTarget) {
407 return fTarget->testingOnly_getRefCnt();
408 }
409
410 return -1; // no backing GrSurface
411}
412
413GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
414 return fSurfaceFlags;
415}
416#endif
417
Robert Phillipse8976842019-08-09 08:27:26 -0400418void GrSurfaceProxyPriv::exactify(bool allocatedCaseOnly) {
Greg Daniel65fa8ca2018-01-10 17:06:31 -0500419 SkASSERT(GrSurfaceProxy::LazyState::kFully != fProxy->lazyInstantiationState());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400420 if (this->isExact()) {
421 return;
422 }
423
424 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
425
426 if (fProxy->fTarget) {
427 // The kApprox but already instantiated case. Setting the proxy's width & height to
428 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400429 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400430 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
431 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400432 fProxy->fWidth = fProxy->fTarget->width();
433 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400434 return;
435 }
436
Robert Phillipse8976842019-08-09 08:27:26 -0400437#ifndef SK_CRIPPLE_TEXTURE_REUSE
438 // In the post-implicit-allocation world we can't convert this proxy to be exact fit
439 // at this point. With explicit allocation switching this to exact will result in a
440 // different allocation at flush time. With implicit allocation, allocation would occur
441 // at draw time (rather than flush time) so this pathway was encountered less often (if
442 // at all).
443 if (allocatedCaseOnly) {
444 return;
445 }
446#endif
447
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400448 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
449 // It could mess things up if prior decisions were based on the approximate size.
450 fProxy->fFit = SkBackingFit::kExact;
451 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400452 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400453 // the special image goes away. If it hasn't been computed yet it might as well compute the
454 // exact amount.
455}
456
Greg Danielbddcc952018-01-24 13:22:24 -0500457bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Greg Daniel0a375db2018-02-01 12:21:39 -0500458 SkASSERT(GrSurfaceProxy::LazyState::kNot != fProxy->lazyInstantiationState());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700459
Robert Phillips0790f8a2018-09-18 13:11:03 -0400460 sk_sp<GrSurface> surface;
461 if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
462 // First try to reattach to a cached version if the proxy is uniquely keyed
463 surface = resourceProvider->findByUniqueKey<GrSurface>(
464 fProxy->asTextureProxy()->getUniqueKey());
465 }
466
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400467 bool syncKey = true;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400468 if (!surface) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400469 auto result = fProxy->fLazyInstantiateCallback(resourceProvider);
470 surface = std::move(result.fSurface);
471 syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400472 }
Greg Daniel457469c2018-02-08 15:05:44 -0500473 if (GrSurfaceProxy::LazyInstantiationType::kSingleUse == fProxy->fLazyInstantiationType) {
Greg Daniel457469c2018-02-08 15:05:44 -0500474 fProxy->fLazyInstantiateCallback = nullptr;
475 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500476 if (!surface) {
Chris Dalton706a6ff2017-11-29 22:01:06 -0700477 fProxy->fWidth = 0;
478 fProxy->fHeight = 0;
Greg Danielbddcc952018-01-24 13:22:24 -0500479 return false;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700480 }
481
Robert Phillipsc1b60662018-06-26 10:20:08 -0400482 if (fProxy->fWidth <= 0 || fProxy->fHeight <= 0) {
483 // This was a fully lazy proxy. We need to fill in the width & height. For partially
484 // lazy proxies we must preserve the original width & height since that indicates
485 // the content area.
486 SkASSERT(fProxy->fWidth <= 0 && fProxy->fHeight <= 0);
487 fProxy->fWidth = surface->width();
488 fProxy->fHeight = surface->height();
489 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700490
Chris Daltonf91b7552019-04-29 16:21:18 -0600491 SkASSERT(fProxy->fWidth <= surface->width());
492 SkASSERT(fProxy->fHeight <= surface->height());
493
Chris Daltoneffee202019-07-01 22:28:03 -0600494 int minStencilSampleCount = (fProxy->asRenderTargetProxy())
495 ? fProxy->asRenderTargetProxy()->numSamples()
496 : 0;
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500497
Chris Daltoneffee202019-07-01 22:28:03 -0600498 if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(
499 resourceProvider, surface.get(), minStencilSampleCount)) {
Robert Phillips01a91282018-07-26 08:03:04 -0400500 return false;
501 }
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500502
Greg Daniel303e83e2018-09-10 14:10:19 -0400503 if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400504 texProxy->setTargetKeySync(syncKey);
505 if (syncKey) {
506 const GrUniqueKey& key = texProxy->getUniqueKey();
507 if (key.isValid()) {
508 if (!surface->asTexture()->getUniqueKey().isValid()) {
509 // If 'surface' is newly created, attach the unique key
510 resourceProvider->assignUniqueKeyToResource(key, surface.get());
511 } else {
512 // otherwise we had better have reattached to a cached version
513 SkASSERT(surface->asTexture()->getUniqueKey() == key);
514 }
Robert Phillips0790f8a2018-09-18 13:11:03 -0400515 } else {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400516 SkASSERT(!surface->getUniqueKey().isValid());
Robert Phillips0790f8a2018-09-18 13:11:03 -0400517 }
Greg Daniel303e83e2018-09-10 14:10:19 -0400518 }
519 }
520
Robert Phillipse8fabb22018-02-04 14:33:21 -0500521 this->assign(std::move(surface));
Greg Danielbddcc952018-01-24 13:22:24 -0500522 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700523}
524
Greg Daniel849dce12018-04-24 14:32:53 -0400525#ifdef SK_DEBUG
526void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
527 SkASSERT(surface->config() == fConfig);
528
Greg Daniel849dce12018-04-24 14:32:53 -0400529 this->onValidateSurface(surface);
530}
531#endif