blob: e5f9c2d40a1618fb34cd45247df5ed6a3dfa579a [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
Robert Phillipsb7bfbc22020-07-01 12:55:01 -040011#include "include/gpu/GrRecordingContext.h"
Brian Salomon947efe22019-07-16 15:36:11 -040012#include "src/core/SkMathPriv.h"
Mike Reed13711eb2020-07-14 17:16:32 -040013#include "src/core/SkMipmap.h"
Greg Danielc0d69152020-10-08 14:59:00 -040014#include "src/gpu/GrAttachment.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/GrGpuResourcePriv.h"
Greg Danielf41b2bd2019-08-22 16:19:24 -040018#include "src/gpu/GrOpsTask.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050019#include "src/gpu/GrProxyProvider.h"
20#include "src/gpu/GrRecordingContextPriv.h"
Robert Phillips1a82a4e2021-07-01 10:27:44 -040021#include "src/gpu/GrResourceProvider.h"
Brian Salomonf7f54332020-07-28 09:23:35 -040022#include "src/gpu/GrSurface.h"
Brian Salomoneebe7352020-12-09 16:37:04 -050023#include "src/gpu/GrSurfaceDrawContext.h"
Brian Salomon4cfae3b2020-07-23 10:33:24 -040024#include "src/gpu/GrTexture.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050025#include "src/gpu/GrTextureRenderTargetProxy.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040026
Greg Daniel65fa8ca2018-01-10 17:06:31 -050027#ifdef SK_DEBUG
Robert Phillips4e105e22020-07-16 09:18:50 -040028#include "include/gpu/GrDirectContext.h"
Adlai Hollera0693042020-10-14 11:23:11 -040029#include "src/gpu/GrDirectContextPriv.h"
Brian Salomon201cdbb2019-08-14 17:00:30 -040030#include "src/gpu/GrRenderTarget.h"
Robert Phillipsc7c2baf2018-03-08 09:51:04 -050031
Brian Salomona56a7462020-02-07 14:17:25 -050032static bool is_valid_lazy(const SkISize& dimensions, SkBackingFit fit) {
Brian Salomon1d19da02019-09-11 17:39:30 -040033 // A "fully" lazy proxy's width and height are not known until instantiation time.
34 // So fully lazy proxies are created with width and height < 0. Regular lazy proxies must be
35 // created with positive widths and heights. The width and height are set to 0 only after a
36 // failed instantiation. The former must be "approximate" fit while the latter can be either.
Brian Salomona56a7462020-02-07 14:17:25 -050037 return ((dimensions.fWidth < 0 && dimensions.fHeight < 0 && SkBackingFit::kApprox == fit) ||
38 (dimensions.fWidth > 0 && dimensions.fHeight > 0));
Greg Daniel65fa8ca2018-01-10 17:06:31 -050039}
40
Brian Salomona56a7462020-02-07 14:17:25 -050041static bool is_valid_non_lazy(SkISize dimensions) {
42 return dimensions.fWidth > 0 && dimensions.fHeight > 0;
Greg Daniel65fa8ca2018-01-10 17:06:31 -050043}
44#endif
45
Brian Salomonbeb7f522019-08-30 16:19:42 -040046// Deferred version
47GrSurfaceProxy::GrSurfaceProxy(const GrBackendFormat& format,
Brian Salomona56a7462020-02-07 14:17:25 -050048 SkISize dimensions,
Brian Salomonbeb7f522019-08-30 16:19:42 -040049 SkBackingFit fit,
50 SkBudgeted budgeted,
51 GrProtected isProtected,
52 GrInternalSurfaceFlags surfaceFlags,
53 UseAllocator useAllocator)
Greg Daniele3204862018-04-16 11:24:10 -040054 : fSurfaceFlags(surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -050055 , fFormat(format)
Brian Salomona56a7462020-02-07 14:17:25 -050056 , fDimensions(dimensions)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050057 , fFit(fit)
58 , fBudgeted(budgeted)
Brian Salomonbeb7f522019-08-30 16:19:42 -040059 , fUseAllocator(useAllocator)
Adlai Hollerba52c912021-02-26 13:16:39 -050060 , fIsProtected(isProtected) {
Greg Daniel4065d452018-11-16 15:43:41 -050061 SkASSERT(fFormat.isValid());
Brian Salomona56a7462020-02-07 14:17:25 -050062 SkASSERT(is_valid_non_lazy(dimensions));
Brian Salomonbeb7f522019-08-30 16:19:42 -040063}
Jim Van Verth1676cb92019-01-15 13:24:45 -050064
Brian Salomonbeb7f522019-08-30 16:19:42 -040065// Lazy-callback version
66GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback,
67 const GrBackendFormat& format,
Brian Salomona56a7462020-02-07 14:17:25 -050068 SkISize dimensions,
Brian Salomonbeb7f522019-08-30 16:19:42 -040069 SkBackingFit fit,
70 SkBudgeted budgeted,
71 GrProtected isProtected,
72 GrInternalSurfaceFlags surfaceFlags,
73 UseAllocator useAllocator)
74 : fSurfaceFlags(surfaceFlags)
75 , fFormat(format)
Brian Salomona56a7462020-02-07 14:17:25 -050076 , fDimensions(dimensions)
Brian Salomonbeb7f522019-08-30 16:19:42 -040077 , fFit(fit)
78 , fBudgeted(budgeted)
79 , fUseAllocator(useAllocator)
80 , fLazyInstantiateCallback(std::move(callback))
Adlai Hollerba52c912021-02-26 13:16:39 -050081 , fIsProtected(isProtected) {
Brian Salomonbeb7f522019-08-30 16:19:42 -040082 SkASSERT(fFormat.isValid());
83 SkASSERT(fLazyInstantiateCallback);
Brian Salomona56a7462020-02-07 14:17:25 -050084 SkASSERT(is_valid_lazy(dimensions, fit));
Chris Dalton706a6ff2017-11-29 22:01:06 -070085}
86
87// Wrapped version
Brian Salomonbeb7f522019-08-30 16:19:42 -040088GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface,
Brian Salomonbeb7f522019-08-30 16:19:42 -040089 SkBackingFit fit,
90 UseAllocator useAllocator)
Robert Phillipsb5204762019-06-19 14:12:13 -040091 : fTarget(std::move(surface))
Brian Salomonf7f54332020-07-28 09:23:35 -040092 , fSurfaceFlags(fTarget->flags())
Greg Daniel4065d452018-11-16 15:43:41 -050093 , fFormat(fTarget->backendFormat())
Brian Salomon9f2b86c2019-10-22 10:37:46 -040094 , fDimensions(fTarget->dimensions())
Brian Salomonbb5711a2017-05-17 13:49:59 -040095 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -050096 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
97 ? SkBudgeted::kYes
98 : SkBudgeted::kNo)
Brian Salomonbeb7f522019-08-30 16:19:42 -040099 , fUseAllocator(useAllocator)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400100 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Adlai Hollerba52c912021-02-26 13:16:39 -0500101 , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo) {
Greg Daniel4065d452018-11-16 15:43:41 -0500102 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400103}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400104
Robert Phillipsf2361d22016-10-25 14:20:06 -0400105GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400106}
107
Robert Phillipsba5c4392018-07-25 12:37:14 -0400108sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400109 int sampleCnt,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400110 GrRenderable renderable,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400111 GrMipmapped mipMapped) const {
112 SkASSERT(mipMapped == GrMipmapped::kNo || fFit == SkBackingFit::kExact);
Brian Salomonbeb7f522019-08-30 16:19:42 -0400113 SkASSERT(!this->isLazy());
Greg Danield2d8e922018-02-12 12:07:39 -0500114 SkASSERT(!fTarget);
Robert Phillipseaa86252016-11-08 13:49:39 +0000115
Robert Phillips5af44de2017-07-18 14:49:38 -0400116 sk_sp<GrSurface> surface;
Brian Salomona90382f2019-09-17 09:01:56 -0400117 if (SkBackingFit::kApprox == fFit) {
Brian Salomona56a7462020-02-07 14:17:25 -0500118 surface = resourceProvider->createApproxTexture(fDimensions, fFormat, renderable, sampleCnt,
Brian Salomona90382f2019-09-17 09:01:56 -0400119 fIsProtected);
Robert Phillipseaa86252016-11-08 13:49:39 +0000120 } else {
Brian Salomona56a7462020-02-07 14:17:25 -0500121 surface = resourceProvider->createTexture(fDimensions, fFormat, renderable, sampleCnt,
122 mipMapped, fBudgeted, fIsProtected);
Robert Phillipseaa86252016-11-08 13:49:39 +0000123 }
Robert Phillips65048132017-08-10 08:44:49 -0400124 if (!surface) {
125 return nullptr;
126 }
127
Robert Phillips5af44de2017-07-18 14:49:38 -0400128 return surface;
129}
130
Brian Salomon7d94bb52018-10-12 14:37:19 -0400131bool GrSurfaceProxy::canSkipResourceAllocator() const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400132 if (fUseAllocator == UseAllocator::kNo) {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400133 // Usually an atlas or onFlush proxy
134 return true;
135 }
136
Brian Salomon7d94bb52018-10-12 14:37:19 -0400137 auto peek = this->peekSurface();
138 if (!peek) {
139 return false;
140 }
141 // If this resource is already allocated and not recyclable then the resource allocator does
142 // not need to do anything with it.
143 return !peek->resourcePriv().getScratchKey().isValid();
144}
145
Robert Phillips5af44de2017-07-18 14:49:38 -0400146void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
147 SkASSERT(!fTarget && surface);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400148
Greg Daniel849dce12018-04-24 14:32:53 -0400149 SkDEBUGCODE(this->validateSurface(surface.get());)
Robert Phillipsabf7b762018-03-21 12:13:37 -0400150
Robert Phillipse5f73282019-06-18 17:15:04 -0400151 fTarget = std::move(surface);
robertphillips1125a032016-11-16 11:17:17 -0800152
Robert Phillipseaa86252016-11-08 13:49:39 +0000153#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500154 if (this->asRenderTargetProxy()) {
155 SkASSERT(fTarget->asRenderTarget());
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500156 }
157
Adlai Holleree2837b2021-04-09 16:52:48 -0400158 // In order to give DDL users some flexibility in the destination of there DDLs,
159 // a DDL's target proxy can be more conservative (and thus require less memory)
160 // than the actual GrSurface used to fulfill it.
161 if (!this->isDDLTarget() && kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Adlai Hollerba52c912021-02-26 13:16:39 -0500162 // TODO(11373): Can this check be exact?
Robert Phillips784b7bf2016-12-09 13:35:02 -0500163 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +0000164 }
165#endif
Robert Phillips5af44de2017-07-18 14:49:38 -0400166}
Robert Phillipseaa86252016-11-08 13:49:39 +0000167
Robert Phillips5af44de2017-07-18 14:49:38 -0400168bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400169 GrRenderable renderable, GrMipmapped mipMapped,
Chris Dalton0b68dda2019-11-07 21:08:03 -0700170 const GrUniqueKey* uniqueKey) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400171 SkASSERT(!this->isLazy());
Robert Phillips5af44de2017-07-18 14:49:38 -0400172 if (fTarget) {
Brian Salomon57904202018-12-17 14:45:00 -0500173 if (uniqueKey && uniqueKey->isValid()) {
174 SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400175 }
Chris Dalton0b68dda2019-11-07 21:08:03 -0700176 return true;
Robert Phillips5af44de2017-07-18 14:49:38 -0400177 }
178
Chris Dalton0b68dda2019-11-07 21:08:03 -0700179 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, renderable,
180 mipMapped);
Robert Phillips5af44de2017-07-18 14:49:38 -0400181 if (!surface) {
182 return false;
183 }
184
Brian Osman28c434b2017-09-27 13:11:16 -0400185 // If there was an invalidation message pending for this key, we might have just processed it,
186 // causing the key (stored on this proxy) to become invalid.
187 if (uniqueKey && uniqueKey->isValid()) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400188 resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
189 }
190
Robert Phillips5af44de2017-07-18 14:49:38 -0400191 this->assign(std::move(surface));
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400192
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400193 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +0000194}
195
Brian Salomon967df202018-12-07 11:15:53 -0500196void GrSurfaceProxy::deinstantiate() {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400197 SkASSERT(this->isInstantiated());
Robert Phillipse5f73282019-06-18 17:15:04 -0400198 fTarget = nullptr;
Robert Phillips4bc70112018-03-01 10:24:02 -0500199}
200
Greg Danield51fa2f2020-01-22 16:53:38 -0500201void GrSurfaceProxy::computeScratchKey(const GrCaps& caps, GrScratchKey* key) const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400202 SkASSERT(!this->isFullyLazy());
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400203 GrRenderable renderable = GrRenderable::kNo;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500204 int sampleCount = 1;
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400205 if (const auto* rtp = this->asRenderTargetProxy()) {
206 renderable = GrRenderable::kYes;
Chris Dalton6ce447a2019-06-23 18:07:38 -0600207 sampleCount = rtp->numSamples();
Robert Phillips57aa3672017-07-21 11:38:13 -0400208 }
209
210 const GrTextureProxy* tp = this->asTextureProxy();
Brian Salomon7e67dca2020-07-21 09:27:25 -0400211 GrMipmapped mipMapped = GrMipmapped::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400212 if (tp) {
Brian Salomon8c82a872020-07-21 12:09:58 -0400213 mipMapped = tp->mipmapped();
Robert Phillips57aa3672017-07-21 11:38:13 -0400214 }
215
Brian Salomon4cfae3b2020-07-23 10:33:24 -0400216 GrTexture::ComputeScratchKey(caps, this->backendFormat(), this->backingStoreDimensions(),
217 renderable, sampleCount, mipMapped, fIsProtected, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400218}
219
Robert Phillipse9462dd2019-10-23 12:41:29 -0400220SkISize GrSurfaceProxy::backingStoreDimensions() const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400221 SkASSERT(!this->isFullyLazy());
Robert Phillipsa108c922017-10-10 10:42:19 -0400222 if (fTarget) {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400223 return fTarget->dimensions();
Robert Phillipsa108c922017-10-10 10:42:19 -0400224 }
225
226 if (SkBackingFit::kExact == fFit) {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400227 return fDimensions;
Robert Phillipsa108c922017-10-10 10:42:19 -0400228 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400229 return GrResourceProvider::MakeApprox(fDimensions);
Robert Phillipsa108c922017-10-10 10:42:19 -0400230}
231
Brian Salomon5c60b752019-12-13 15:03:43 -0500232bool GrSurfaceProxy::isFunctionallyExact() const {
233 SkASSERT(!this->isFullyLazy());
234 return fFit == SkBackingFit::kExact ||
235 fDimensions == GrResourceProvider::MakeApprox(fDimensions);
236}
237
Greg Daniel82c6b102020-01-21 10:33:22 -0500238bool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const {
239 return caps->isFormatCompressed(this->backendFormat());
240}
241
Brian Osman45580d32016-11-23 09:37:01 -0500242#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500243void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500244 if (fTarget) {
Adlai Hollerb81eeba2020-06-09 15:20:25 -0400245 SkASSERT(fTarget->getContext()->priv().matches(context));
Brian Osman45580d32016-11-23 09:37:01 -0500246 }
Brian Osman45580d32016-11-23 09:37:01 -0500247}
248#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500249
Brian Salomonc5243782020-04-02 12:50:34 -0400250sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Brian Salomon982127b2021-01-21 10:43:35 -0500251 sk_sp<GrSurfaceProxy> src,
Brian Salomonc5243782020-04-02 12:50:34 -0400252 GrSurfaceOrigin origin,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400253 GrMipmapped mipMapped,
Brian Salomonc5243782020-04-02 12:50:34 -0400254 SkIRect srcRect,
255 SkBackingFit fit,
256 SkBudgeted budgeted,
Brian Salomond63638b2021-03-05 14:00:07 -0500257 RectsMustMatch rectsMustMatch,
258 sk_sp<GrRenderTask>* outTask) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400259 SkASSERT(!src->isFullyLazy());
Brian Salomon947efe22019-07-16 15:36:11 -0400260 int width;
261 int height;
Greg Daniel46cfbc62019-06-07 11:43:30 -0400262
263 SkIPoint dstPoint;
264 if (rectsMustMatch == RectsMustMatch::kYes) {
Brian Salomon947efe22019-07-16 15:36:11 -0400265 width = src->width();
266 height = src->height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400267 dstPoint = {srcRect.fLeft, srcRect.fTop};
268 } else {
Brian Salomon947efe22019-07-16 15:36:11 -0400269 width = srcRect.width();
270 height = srcRect.height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400271 dstPoint = {0, 0};
272 }
273
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400274 if (!srcRect.intersect(SkIRect::MakeSize(src->dimensions()))) {
Greg Daniel40903af2020-01-30 14:55:05 -0500275 return {};
Robert Phillipse2f7d182016-12-15 09:23:05 -0500276 }
Greg Danielbfa19c42019-12-19 16:41:40 -0500277 auto format = src->backendFormat().makeTexture2D();
278 SkASSERT(format.isValid());
Greg Danielbfa19c42019-12-19 16:41:40 -0500279
Greg Daniel46cfbc62019-06-07 11:43:30 -0400280 if (src->backendFormat().textureType() != GrTextureType::kExternal) {
Brian Salomon14f99fc2020-12-07 12:19:47 -0500281 GrImageInfo info(GrColorType::kUnknown, kUnknown_SkAlphaType, nullptr, {width, height});
282 auto dstContext = GrSurfaceContext::Make(context,
283 info,
284 format,
285 fit,
286 origin,
287 GrRenderable::kNo,
288 1,
289 mipMapped,
290 src->isProtected(),
291 budgeted);
Brian Salomond63638b2021-03-05 14:00:07 -0500292 sk_sp<GrRenderTask> copyTask;
293 if (dstContext && (copyTask = dstContext->copy(src, srcRect, dstPoint))) {
294 if (outTask) {
295 *outTask = std::move(copyTask);
296 }
Brian Salomonc5243782020-04-02 12:50:34 -0400297 return dstContext->asSurfaceProxyRef();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400298 }
Greg Danielc5167c02019-06-05 17:36:53 +0000299 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400300 if (src->asTextureProxy()) {
Brian Salomon590f5672020-12-16 11:44:47 -0500301 auto dstContext = GrSurfaceFillContext::Make(context,
302 kUnknown_SkAlphaType,
Brian Salomoneebe7352020-12-09 16:37:04 -0500303 nullptr,
Brian Salomon0263bff2020-12-16 08:41:39 -0500304 {width, height},
Brian Salomon590f5672020-12-16 11:44:47 -0500305 fit,
Brian Salomoneebe7352020-12-09 16:37:04 -0500306 format,
Brian Salomon590f5672020-12-16 11:44:47 -0500307 1,
Brian Salomoneebe7352020-12-09 16:37:04 -0500308 mipMapped,
309 src->isProtected(),
310 GrSwizzle::RGBA(),
311 GrSwizzle::RGBA(),
Brian Salomon0263bff2020-12-16 08:41:39 -0500312 origin,
Brian Salomon590f5672020-12-16 11:44:47 -0500313 budgeted);
Brian Salomon982127b2021-01-21 10:43:35 -0500314 GrSurfaceProxyView view(std::move(src), origin, GrSwizzle::RGBA());
Greg Daniel573312e2020-02-07 17:22:35 -0500315 if (dstContext && dstContext->blitTexture(std::move(view), srcRect, dstPoint)) {
Brian Salomond63638b2021-03-05 14:00:07 -0500316 if (outTask) {
317 *outTask = sk_ref_sp(dstContext->getOpsTask());
318 }
Brian Salomonc5243782020-04-02 12:50:34 -0400319 return dstContext->asSurfaceProxyRef();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400320 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400321 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400322 // Can't use backend copies or draws.
Brian Salomonc5243782020-04-02 12:50:34 -0400323 return nullptr;
Robert Phillips63c67462017-02-15 14:19:01 -0500324}
325
Brian Salomonc5243782020-04-02 12:50:34 -0400326sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Brian Salomon982127b2021-01-21 10:43:35 -0500327 sk_sp<GrSurfaceProxy> src,
Brian Salomonc5243782020-04-02 12:50:34 -0400328 GrSurfaceOrigin origin,
Brian Salomon7e67dca2020-07-21 09:27:25 -0400329 GrMipmapped mipMapped,
Brian Salomonc5243782020-04-02 12:50:34 -0400330 SkBackingFit fit,
Brian Salomond63638b2021-03-05 14:00:07 -0500331 SkBudgeted budgeted,
332 sk_sp<GrRenderTask>* outTask) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400333 SkASSERT(!src->isFullyLazy());
Brian Salomon982127b2021-01-21 10:43:35 -0500334 auto rect = SkIRect::MakeSize(src->dimensions());
Brian Salomond63638b2021-03-05 14:00:07 -0500335 return Copy(context,
336 std::move(src),
337 origin,
338 mipMapped,
339 rect,
340 fit,
341 budgeted,
342 RectsMustMatch::kNo,
343 outTask);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500344}
345
Robert Phillipsb5204762019-06-19 14:12:13 -0400346#if GR_TEST_UTILS
347int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
348 if (fTarget) {
349 return fTarget->testingOnly_getRefCnt();
350 }
351
352 return -1; // no backing GrSurface
353}
354
355GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
356 return fSurfaceFlags;
357}
Robert Phillips047d5bb2021-01-08 13:39:19 -0500358
359SkString GrSurfaceProxy::dump() const {
360 SkString tmp;
361
362 tmp.appendf("proxyID: %d - surfaceID: %d",
363 this->uniqueID().asUInt(),
364 this->peekSurface() ? this->peekSurface()->uniqueID().asUInt()
365 : -1);
366 return tmp;
367}
368
Robert Phillipsb5204762019-06-19 14:12:13 -0400369#endif
370
Robert Phillipse8976842019-08-09 08:27:26 -0400371void GrSurfaceProxyPriv::exactify(bool allocatedCaseOnly) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400372 SkASSERT(!fProxy->isFullyLazy());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400373 if (this->isExact()) {
374 return;
375 }
376
377 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
378
379 if (fProxy->fTarget) {
380 // The kApprox but already instantiated case. Setting the proxy's width & height to
381 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400382 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400383 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
384 // used for additional draws.
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400385 fProxy->fDimensions = fProxy->fTarget->dimensions();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400386 return;
387 }
388
Robert Phillipse8976842019-08-09 08:27:26 -0400389#ifndef SK_CRIPPLE_TEXTURE_REUSE
390 // In the post-implicit-allocation world we can't convert this proxy to be exact fit
391 // at this point. With explicit allocation switching this to exact will result in a
392 // different allocation at flush time. With implicit allocation, allocation would occur
393 // at draw time (rather than flush time) so this pathway was encountered less often (if
394 // at all).
395 if (allocatedCaseOnly) {
396 return;
397 }
398#endif
399
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400400 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
401 // It could mess things up if prior decisions were based on the approximate size.
402 fProxy->fFit = SkBackingFit::kExact;
403 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400404 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400405 // the special image goes away. If it hasn't been computed yet it might as well compute the
406 // exact amount.
407}
408
Greg Danielbddcc952018-01-24 13:22:24 -0500409bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400410 SkASSERT(fProxy->isLazy());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700411
Robert Phillips0790f8a2018-09-18 13:11:03 -0400412 sk_sp<GrSurface> surface;
Adlai Hollercc119d92021-03-16 15:17:25 -0400413 if (const auto& uniqueKey = fProxy->getUniqueKey(); uniqueKey.isValid()) {
Robert Phillips0790f8a2018-09-18 13:11:03 -0400414 // First try to reattach to a cached version if the proxy is uniquely keyed
Adlai Hollercc119d92021-03-16 15:17:25 -0400415 surface = resourceProvider->findByUniqueKey<GrSurface>(uniqueKey);
Robert Phillips0790f8a2018-09-18 13:11:03 -0400416 }
417
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400418 bool syncKey = true;
Brian Salomonbeb7f522019-08-30 16:19:42 -0400419 bool releaseCallback = false;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400420 if (!surface) {
Brian Salomon63410e92020-03-23 18:32:50 -0400421 auto result = fProxy->fLazyInstantiateCallback(resourceProvider, fProxy->callbackDesc());
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400422 surface = std::move(result.fSurface);
423 syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
Brian Salomonbeb7f522019-08-30 16:19:42 -0400424 releaseCallback = surface && result.fReleaseCallback;
Greg Daniel457469c2018-02-08 15:05:44 -0500425 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500426 if (!surface) {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400427 fProxy->fDimensions.setEmpty();
Greg Danielbddcc952018-01-24 13:22:24 -0500428 return false;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700429 }
430
Brian Salomon1d19da02019-09-11 17:39:30 -0400431 if (fProxy->isFullyLazy()) {
Robert Phillipsc1b60662018-06-26 10:20:08 -0400432 // This was a fully lazy proxy. We need to fill in the width & height. For partially
433 // lazy proxies we must preserve the original width & height since that indicates
434 // the content area.
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400435 fProxy->fDimensions = surface->dimensions();
Robert Phillipsc1b60662018-06-26 10:20:08 -0400436 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700437
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400438 SkASSERT(fProxy->width() <= surface->width());
439 SkASSERT(fProxy->height() <= surface->height());
Chris Daltonf91b7552019-04-29 16:21:18 -0600440
Greg Daniel303e83e2018-09-10 14:10:19 -0400441 if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400442 texProxy->setTargetKeySync(syncKey);
443 if (syncKey) {
444 const GrUniqueKey& key = texProxy->getUniqueKey();
445 if (key.isValid()) {
446 if (!surface->asTexture()->getUniqueKey().isValid()) {
447 // If 'surface' is newly created, attach the unique key
448 resourceProvider->assignUniqueKeyToResource(key, surface.get());
449 } else {
450 // otherwise we had better have reattached to a cached version
451 SkASSERT(surface->asTexture()->getUniqueKey() == key);
452 }
Robert Phillips0790f8a2018-09-18 13:11:03 -0400453 } else {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400454 SkASSERT(!surface->getUniqueKey().isValid());
Robert Phillips0790f8a2018-09-18 13:11:03 -0400455 }
Greg Daniel303e83e2018-09-10 14:10:19 -0400456 }
457 }
458
Robert Phillipse8fabb22018-02-04 14:33:21 -0500459 this->assign(std::move(surface));
Brian Salomonbeb7f522019-08-30 16:19:42 -0400460 if (releaseCallback) {
461 fProxy->fLazyInstantiateCallback = nullptr;
462 }
463
Greg Danielbddcc952018-01-24 13:22:24 -0500464 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700465}
466
Greg Daniel849dce12018-04-24 14:32:53 -0400467#ifdef SK_DEBUG
468void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
Robert Phillips8e54a6e2020-08-17 14:31:02 -0400469 SkASSERTF(surface->backendFormat() == fFormat, "%s != %s",
470 surface->backendFormat().toStr().c_str(), fFormat.toStr().c_str());
Greg Daniel849dce12018-04-24 14:32:53 -0400471
Greg Daniel849dce12018-04-24 14:32:53 -0400472 this->onValidateSurface(surface);
473}
474#endif