blob: 41566bb00c19d6085d50f2e719ca140c55f7ae38 [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 Danielf41b2bd2019-08-22 16:19:24 -040019#include "src/gpu/GrOpsTask.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/GrProxyProvider.h"
21#include "src/gpu/GrRecordingContextPriv.h"
Greg Daniele20fcad2020-01-08 11:52:34 -050022#include "src/gpu/GrRenderTargetContext.h"
Chris Daltoneffee202019-07-01 22:28:03 -060023#include "src/gpu/GrStencilAttachment.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/gpu/GrSurfacePriv.h"
25#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
Brian Salomon201cdbb2019-08-14 17:00:30 -040029#include "src/gpu/GrRenderTarget.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050030#include "src/gpu/GrRenderTargetPriv.h"
Robert Phillipsc7c2baf2018-03-08 09:51:04 -050031
Brian Salomon1d19da02019-09-11 17:39:30 -040032static bool is_valid_lazy(const GrSurfaceDesc& desc, SkBackingFit fit) {
33 // 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.
Greg Danield51fa2f2020-01-22 16:53:38 -050037 return ((desc.fWidth < 0 && desc.fHeight < 0 && SkBackingFit::kApprox == fit) ||
Brian Salomon1d19da02019-09-11 17:39:30 -040038 (desc.fWidth > 0 && desc.fHeight > 0));
Greg Daniel65fa8ca2018-01-10 17:06:31 -050039}
40
41static bool is_valid_non_lazy(const GrSurfaceDesc& desc) {
Greg Danield51fa2f2020-01-22 16:53:38 -050042 return desc.fWidth > 0 && desc.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,
48 const GrSurfaceDesc& desc,
49 GrRenderable renderable,
50 GrSurfaceOrigin origin,
51 const GrSwizzle& textureSwizzle,
52 SkBackingFit fit,
53 SkBudgeted budgeted,
54 GrProtected isProtected,
55 GrInternalSurfaceFlags surfaceFlags,
56 UseAllocator useAllocator)
Greg Daniele3204862018-04-16 11:24:10 -040057 : fSurfaceFlags(surfaceFlags)
Greg Daniel4065d452018-11-16 15:43:41 -050058 , fFormat(format)
Brian Salomon9f2b86c2019-10-22 10:37:46 -040059 , fDimensions{desc.fWidth, desc.fHeight}
Brian Salomon2a4f9832018-03-03 22:43:43 -050060 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -040061 , fTextureSwizzle(textureSwizzle)
Greg Daniel65fa8ca2018-01-10 17:06:31 -050062 , fFit(fit)
63 , fBudgeted(budgeted)
Brian Salomonbeb7f522019-08-30 16:19:42 -040064 , fUseAllocator(useAllocator)
Brian Salomone8a766b2019-07-19 14:24:36 -040065 , fIsProtected(isProtected)
Brian Salomonbeb7f522019-08-30 16:19:42 -040066 , fGpuMemorySize(kInvalidGpuMemorySize) {
Greg Daniel4065d452018-11-16 15:43:41 -050067 SkASSERT(fFormat.isValid());
Brian Salomonbeb7f522019-08-30 16:19:42 -040068 SkASSERT(is_valid_non_lazy(desc));
Brian Salomonbeb7f522019-08-30 16:19:42 -040069}
Jim Van Verth1676cb92019-01-15 13:24:45 -050070
Brian Salomonbeb7f522019-08-30 16:19:42 -040071// Lazy-callback version
72GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback,
73 const GrBackendFormat& format,
74 const GrSurfaceDesc& desc,
75 GrRenderable renderable,
76 GrSurfaceOrigin origin,
77 const GrSwizzle& textureSwizzle,
78 SkBackingFit fit,
79 SkBudgeted budgeted,
80 GrProtected isProtected,
81 GrInternalSurfaceFlags surfaceFlags,
82 UseAllocator useAllocator)
83 : fSurfaceFlags(surfaceFlags)
84 , fFormat(format)
Brian Salomon9f2b86c2019-10-22 10:37:46 -040085 , fDimensions{desc.fWidth, desc.fHeight}
Brian Salomonbeb7f522019-08-30 16:19:42 -040086 , fOrigin(origin)
87 , fTextureSwizzle(textureSwizzle)
88 , fFit(fit)
89 , fBudgeted(budgeted)
90 , fUseAllocator(useAllocator)
91 , fLazyInstantiateCallback(std::move(callback))
92 , fIsProtected(isProtected)
93 , fGpuMemorySize(kInvalidGpuMemorySize) {
94 SkASSERT(fFormat.isValid());
95 SkASSERT(fLazyInstantiateCallback);
Brian Salomon1d19da02019-09-11 17:39:30 -040096 SkASSERT(is_valid_lazy(desc, fit));
Chris Dalton706a6ff2017-11-29 22:01:06 -070097}
98
99// Wrapped version
Brian Salomonbeb7f522019-08-30 16:19:42 -0400100GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface,
101 GrSurfaceOrigin origin,
102 const GrSwizzle& textureSwizzle,
103 SkBackingFit fit,
104 UseAllocator useAllocator)
Robert Phillipsb5204762019-06-19 14:12:13 -0400105 : fTarget(std::move(surface))
Greg Daniele3204862018-04-16 11:24:10 -0400106 , fSurfaceFlags(fTarget->surfacePriv().flags())
Greg Daniel4065d452018-11-16 15:43:41 -0500107 , fFormat(fTarget->backendFormat())
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400108 , fDimensions(fTarget->dimensions())
Robert Phillips066f0202017-07-25 10:16:35 -0400109 , fOrigin(origin)
Greg Daniel2c19e7f2019-06-18 13:29:21 -0400110 , fTextureSwizzle(textureSwizzle)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400111 , fFit(fit)
Brian Salomonfa2ebea2019-01-24 15:58:58 -0500112 , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
113 ? SkBudgeted::kYes
114 : SkBudgeted::kNo)
Brian Salomonbeb7f522019-08-30 16:19:42 -0400115 , fUseAllocator(useAllocator)
Brian Salomonbb5711a2017-05-17 13:49:59 -0400116 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Emircan Uysaler23ca4e72019-06-24 10:53:09 -0400117 , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo)
Brian Salomonbeb7f522019-08-30 16:19:42 -0400118 , fGpuMemorySize(kInvalidGpuMemorySize) {
Greg Daniel4065d452018-11-16 15:43:41 -0500119 SkASSERT(fFormat.isValid());
Robert Phillips019ff272017-07-24 14:47:57 -0400120}
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400121
Robert Phillipsf2361d22016-10-25 14:20:06 -0400122GrSurfaceProxy::~GrSurfaceProxy() {
Greg Danielf41b2bd2019-08-22 16:19:24 -0400123 // For this to be deleted the opsTask that held a ref on it (if there was one) must have been
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400124 // deleted. Which would have cleared out this back pointer.
Chris Dalton6b498102019-08-01 14:14:52 -0600125 SkASSERT(!fLastRenderTask);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400126}
127
Robert Phillipsba5c4392018-07-25 12:37:14 -0400128sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
Brian Salomon4eb38b72019-08-05 12:58:39 -0400129 int sampleCnt,
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400130 GrRenderable renderable,
Robert Phillips10d17212019-04-24 14:09:10 -0400131 GrMipMapped mipMapped) const {
Brian Salomona90382f2019-09-17 09:01:56 -0400132 SkASSERT(mipMapped == GrMipMapped::kNo || fFit == SkBackingFit::kExact);
Brian Salomonbeb7f522019-08-30 16:19:42 -0400133 SkASSERT(!this->isLazy());
Greg Danield2d8e922018-02-12 12:07:39 -0500134 SkASSERT(!fTarget);
Brian Salomonbb5711a2017-05-17 13:49:59 -0400135 GrSurfaceDesc desc;
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400136 desc.fWidth = fDimensions.width();
137 desc.fHeight = fDimensions.height();
Robert Phillipseaa86252016-11-08 13:49:39 +0000138
Robert Phillips5af44de2017-07-18 14:49:38 -0400139 sk_sp<GrSurface> surface;
Brian Salomona90382f2019-09-17 09:01:56 -0400140 if (SkBackingFit::kApprox == fFit) {
141 surface = resourceProvider->createApproxTexture(desc, fFormat, renderable, sampleCnt,
142 fIsProtected);
Robert Phillipseaa86252016-11-08 13:49:39 +0000143 } else {
Brian Salomona90382f2019-09-17 09:01:56 -0400144 surface = resourceProvider->createTexture(desc, fFormat, renderable, sampleCnt, mipMapped,
145 fBudgeted, fIsProtected);
Robert Phillipseaa86252016-11-08 13:49:39 +0000146 }
Robert Phillips65048132017-08-10 08:44:49 -0400147 if (!surface) {
148 return nullptr;
149 }
150
Robert Phillips5af44de2017-07-18 14:49:38 -0400151 return surface;
152}
153
Brian Salomon7d94bb52018-10-12 14:37:19 -0400154bool GrSurfaceProxy::canSkipResourceAllocator() const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400155 if (fUseAllocator == UseAllocator::kNo) {
Robert Phillips5f78adf2019-04-22 12:41:39 -0400156 // Usually an atlas or onFlush proxy
157 return true;
158 }
159
Brian Salomon7d94bb52018-10-12 14:37:19 -0400160 auto peek = this->peekSurface();
161 if (!peek) {
162 return false;
163 }
164 // If this resource is already allocated and not recyclable then the resource allocator does
165 // not need to do anything with it.
166 return !peek->resourcePriv().getScratchKey().isValid();
167}
168
Robert Phillips5af44de2017-07-18 14:49:38 -0400169void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
170 SkASSERT(!fTarget && surface);
Robert Phillipsabf7b762018-03-21 12:13:37 -0400171
Greg Daniel849dce12018-04-24 14:32:53 -0400172 SkDEBUGCODE(this->validateSurface(surface.get());)
Robert Phillipsabf7b762018-03-21 12:13:37 -0400173
Robert Phillipse5f73282019-06-18 17:15:04 -0400174 fTarget = std::move(surface);
robertphillips1125a032016-11-16 11:17:17 -0800175
Robert Phillipseaa86252016-11-08 13:49:39 +0000176#ifdef SK_DEBUG
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500177 if (this->asRenderTargetProxy()) {
178 SkASSERT(fTarget->asRenderTarget());
Robert Phillipsc7c2baf2018-03-08 09:51:04 -0500179 }
180
Robert Phillipseaa86252016-11-08 13:49:39 +0000181 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -0500182 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +0000183 }
184#endif
Robert Phillips5af44de2017-07-18 14:49:38 -0400185}
Robert Phillipseaa86252016-11-08 13:49:39 +0000186
Robert Phillips5af44de2017-07-18 14:49:38 -0400187bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Chris Dalton0b68dda2019-11-07 21:08:03 -0700188 GrRenderable renderable, GrMipMapped mipMapped,
189 const GrUniqueKey* uniqueKey) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400190 SkASSERT(!this->isLazy());
Robert Phillips5af44de2017-07-18 14:49:38 -0400191 if (fTarget) {
Brian Salomon57904202018-12-17 14:45:00 -0500192 if (uniqueKey && uniqueKey->isValid()) {
193 SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400194 }
Chris Dalton0b68dda2019-11-07 21:08:03 -0700195 return true;
Robert Phillips5af44de2017-07-18 14:49:38 -0400196 }
197
Chris Dalton0b68dda2019-11-07 21:08:03 -0700198 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, renderable,
199 mipMapped);
Robert Phillips5af44de2017-07-18 14:49:38 -0400200 if (!surface) {
201 return false;
202 }
203
Brian Osman28c434b2017-09-27 13:11:16 -0400204 // If there was an invalidation message pending for this key, we might have just processed it,
205 // causing the key (stored on this proxy) to become invalid.
206 if (uniqueKey && uniqueKey->isValid()) {
Robert Phillipsae7d3f32017-09-21 08:26:08 -0400207 resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
208 }
209
Robert Phillips5af44de2017-07-18 14:49:38 -0400210 this->assign(std::move(surface));
Robert Phillipsfe0253f2018-03-16 16:47:25 -0400211
Robert Phillipseee4d6e2017-06-05 09:26:07 -0400212 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +0000213}
214
Brian Salomon967df202018-12-07 11:15:53 -0500215void GrSurfaceProxy::deinstantiate() {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400216 SkASSERT(this->isInstantiated());
Robert Phillipse5f73282019-06-18 17:15:04 -0400217 fTarget = nullptr;
Robert Phillips4bc70112018-03-01 10:24:02 -0500218}
219
Greg Danield51fa2f2020-01-22 16:53:38 -0500220void GrSurfaceProxy::computeScratchKey(const GrCaps& caps, GrScratchKey* key) const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400221 SkASSERT(!this->isFullyLazy());
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400222 GrRenderable renderable = GrRenderable::kNo;
Brian Salomonbdecacf2018-02-02 20:32:49 -0500223 int sampleCount = 1;
Brian Salomonf2c2ba92019-07-17 09:59:59 -0400224 if (const auto* rtp = this->asRenderTargetProxy()) {
225 renderable = GrRenderable::kYes;
Chris Dalton6ce447a2019-06-23 18:07:38 -0600226 sampleCount = rtp->numSamples();
Robert Phillips57aa3672017-07-21 11:38:13 -0400227 }
228
229 const GrTextureProxy* tp = this->asTextureProxy();
Greg Daniele252f082017-10-23 16:05:23 -0400230 GrMipMapped mipMapped = GrMipMapped::kNo;
Robert Phillips57aa3672017-07-21 11:38:13 -0400231 if (tp) {
Greg Daniele252f082017-10-23 16:05:23 -0400232 mipMapped = tp->mipMapped();
Robert Phillips57aa3672017-07-21 11:38:13 -0400233 }
234
Greg Danield51fa2f2020-01-22 16:53:38 -0500235 GrTexturePriv::ComputeScratchKey(caps, this->backendFormat(), this->backingStoreDimensions(),
236 renderable, sampleCount, mipMapped, fIsProtected, key);
Robert Phillips57aa3672017-07-21 11:38:13 -0400237}
238
Chris Dalton6b498102019-08-01 14:14:52 -0600239void GrSurfaceProxy::setLastRenderTask(GrRenderTask* renderTask) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400240#ifdef SK_DEBUG
Chris Dalton6b498102019-08-01 14:14:52 -0600241 if (fLastRenderTask) {
242 SkASSERT(fLastRenderTask->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +0000243 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400244#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -0400245
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400246 // Un-reffed
Chris Dalton6b498102019-08-01 14:14:52 -0600247 fLastRenderTask = renderTask;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400248}
Robert Phillips37430132016-11-09 06:50:43 -0500249
Greg Danielf41b2bd2019-08-22 16:19:24 -0400250GrOpsTask* GrSurfaceProxy::getLastOpsTask() {
251 return fLastRenderTask ? fLastRenderTask->asOpsTask() : nullptr;
Brian Osman45580d32016-11-23 09:37:01 -0500252}
253
Robert Phillipse9462dd2019-10-23 12:41:29 -0400254SkISize GrSurfaceProxy::backingStoreDimensions() const {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400255 SkASSERT(!this->isFullyLazy());
Robert Phillipsa108c922017-10-10 10:42:19 -0400256 if (fTarget) {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400257 return fTarget->dimensions();
Robert Phillipsa108c922017-10-10 10:42:19 -0400258 }
259
260 if (SkBackingFit::kExact == fFit) {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400261 return fDimensions;
Robert Phillipsa108c922017-10-10 10:42:19 -0400262 }
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400263 return GrResourceProvider::MakeApprox(fDimensions);
Robert Phillipsa108c922017-10-10 10:42:19 -0400264}
265
Brian Salomon5c60b752019-12-13 15:03:43 -0500266bool GrSurfaceProxy::isFunctionallyExact() const {
267 SkASSERT(!this->isFullyLazy());
268 return fFit == SkBackingFit::kExact ||
269 fDimensions == GrResourceProvider::MakeApprox(fDimensions);
270}
271
Greg Daniel82c6b102020-01-21 10:33:22 -0500272bool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const {
273 return caps->isFormatCompressed(this->backendFormat());
274}
275
Brian Osman45580d32016-11-23 09:37:01 -0500276#ifdef SK_DEBUG
Robert Phillips292a6b22019-02-14 14:49:02 -0500277void GrSurfaceProxy::validate(GrContext_Base* context) const {
Brian Osman45580d32016-11-23 09:37:01 -0500278 if (fTarget) {
279 SkASSERT(fTarget->getContext() == context);
280 }
Brian Osman45580d32016-11-23 09:37:01 -0500281}
282#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500283
Robert Phillipsd44146b2019-02-15 14:44:28 -0500284sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500285 GrSurfaceProxy* src,
Greg Daniel3155f7f2020-01-16 16:54:26 -0500286 GrColorType srcColorType,
Greg Daniel65c7f662017-10-30 13:39:09 -0400287 GrMipMapped mipMapped,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500288 SkIRect srcRect,
Brian Salomonfee3f9b2018-12-19 12:34:12 -0500289 SkBackingFit fit,
Greg Daniel46cfbc62019-06-07 11:43:30 -0400290 SkBudgeted budgeted,
291 RectsMustMatch rectsMustMatch) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400292 SkASSERT(!src->isFullyLazy());
Brian Salomon947efe22019-07-16 15:36:11 -0400293 int width;
294 int height;
Greg Daniel46cfbc62019-06-07 11:43:30 -0400295
296 SkIPoint dstPoint;
297 if (rectsMustMatch == RectsMustMatch::kYes) {
Brian Salomon947efe22019-07-16 15:36:11 -0400298 width = src->width();
299 height = src->height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400300 dstPoint = {srcRect.fLeft, srcRect.fTop};
301 } else {
Brian Salomon947efe22019-07-16 15:36:11 -0400302 width = srcRect.width();
303 height = srcRect.height();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400304 dstPoint = {0, 0};
305 }
306
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400307 if (!srcRect.intersect(SkIRect::MakeSize(src->dimensions()))) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500308 return nullptr;
309 }
Greg Danielbfa19c42019-12-19 16:41:40 -0500310 auto format = src->backendFormat().makeTexture2D();
311 SkASSERT(format.isValid());
Greg Danielbfa19c42019-12-19 16:41:40 -0500312
313 GrSurfaceOrigin origin = src->origin();
Greg Daniel46cfbc62019-06-07 11:43:30 -0400314 if (src->backendFormat().textureType() != GrTextureType::kExternal) {
Greg Danielbfa19c42019-12-19 16:41:40 -0500315 auto dstContext = GrSurfaceContext::Make(context, {width, height}, format,
Greg Danielca9dbe22020-01-02 13:44:30 -0500316 GrRenderable::kNo, 1, mipMapped,
Greg Daniel3155f7f2020-01-16 16:54:26 -0500317 src->isProtected(), origin, srcColorType,
Greg Danielca9dbe22020-01-02 13:44:30 -0500318 kUnknown_SkAlphaType, nullptr, fit, budgeted);
Greg Danielbfa19c42019-12-19 16:41:40 -0500319 if (dstContext && dstContext->copy(src, srcRect, dstPoint)) {
Greg Daniel46cfbc62019-06-07 11:43:30 -0400320 return dstContext->asTextureProxyRef();
321 }
Greg Danielc5167c02019-06-05 17:36:53 +0000322 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400323 if (src->asTextureProxy()) {
Greg Daniel3155f7f2020-01-16 16:54:26 -0500324 auto dstContext = GrRenderTargetContext::Make(context, srcColorType, nullptr, fit,
Greg Daniele20fcad2020-01-08 11:52:34 -0500325 {width, height}, format, 1,
326 mipMapped, src->isProtected(), origin,
327 budgeted, nullptr);
Brian Salomonfc118442019-11-22 19:09:27 -0500328 if (dstContext && dstContext->blitTexture(src->asTextureProxy(), srcRect, dstPoint)) {
Greg Daniel46cfbc62019-06-07 11:43:30 -0400329 return dstContext->asTextureProxyRef();
330 }
Greg Daniel4c6f9b72019-06-06 13:40:59 -0400331 }
Greg Daniel46cfbc62019-06-07 11:43:30 -0400332 // Can't use backend copies or draws.
333 return nullptr;
Robert Phillips63c67462017-02-15 14:19:01 -0500334}
335
Robert Phillipsd44146b2019-02-15 14:44:28 -0500336sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrRecordingContext* context, GrSurfaceProxy* src,
Greg Daniel3155f7f2020-01-16 16:54:26 -0500337 GrColorType srcColorType, GrMipMapped mipMapped,
338 SkBackingFit fit, SkBudgeted budgeted) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400339 SkASSERT(!src->isFullyLazy());
Greg Daniel3155f7f2020-01-16 16:54:26 -0500340 return Copy(context, src, srcColorType, mipMapped, SkIRect::MakeSize(src->dimensions()), fit,
341 budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500342}
343
Robert Phillipsb5204762019-06-19 14:12:13 -0400344#if GR_TEST_UTILS
345int32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
346 if (fTarget) {
347 return fTarget->testingOnly_getRefCnt();
348 }
349
350 return -1; // no backing GrSurface
351}
352
353GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
354 return fSurfaceFlags;
355}
356#endif
357
Robert Phillipse8976842019-08-09 08:27:26 -0400358void GrSurfaceProxyPriv::exactify(bool allocatedCaseOnly) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400359 SkASSERT(!fProxy->isFullyLazy());
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400360 if (this->isExact()) {
361 return;
362 }
363
364 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
365
366 if (fProxy->fTarget) {
367 // The kApprox but already instantiated case. Setting the proxy's width & height to
368 // the instantiated width & height could have side-effects going forward, since we're
Ben Wagner63fd7602017-10-09 15:45:33 -0400369 // obliterating the area of interest information. This call (exactify) only used
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400370 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
371 // used for additional draws.
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400372 fProxy->fDimensions = fProxy->fTarget->dimensions();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400373 return;
374 }
375
Robert Phillipse8976842019-08-09 08:27:26 -0400376#ifndef SK_CRIPPLE_TEXTURE_REUSE
377 // In the post-implicit-allocation world we can't convert this proxy to be exact fit
378 // at this point. With explicit allocation switching this to exact will result in a
379 // different allocation at flush time. With implicit allocation, allocation would occur
380 // at draw time (rather than flush time) so this pathway was encountered less often (if
381 // at all).
382 if (allocatedCaseOnly) {
383 return;
384 }
385#endif
386
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400387 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
388 // It could mess things up if prior decisions were based on the approximate size.
389 fProxy->fFit = SkBackingFit::kExact;
390 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400391 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400392 // the special image goes away. If it hasn't been computed yet it might as well compute the
393 // exact amount.
394}
395
Greg Danielbddcc952018-01-24 13:22:24 -0500396bool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
Brian Salomonbeb7f522019-08-30 16:19:42 -0400397 SkASSERT(fProxy->isLazy());
Chris Dalton706a6ff2017-11-29 22:01:06 -0700398
Robert Phillips0790f8a2018-09-18 13:11:03 -0400399 sk_sp<GrSurface> surface;
400 if (fProxy->asTextureProxy() && fProxy->asTextureProxy()->getUniqueKey().isValid()) {
401 // First try to reattach to a cached version if the proxy is uniquely keyed
402 surface = resourceProvider->findByUniqueKey<GrSurface>(
403 fProxy->asTextureProxy()->getUniqueKey());
404 }
405
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400406 bool syncKey = true;
Brian Salomonbeb7f522019-08-30 16:19:42 -0400407 bool releaseCallback = false;
Robert Phillips0790f8a2018-09-18 13:11:03 -0400408 if (!surface) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400409 auto result = fProxy->fLazyInstantiateCallback(resourceProvider);
410 surface = std::move(result.fSurface);
411 syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
Brian Salomonbeb7f522019-08-30 16:19:42 -0400412 releaseCallback = surface && result.fReleaseCallback;
Greg Daniel457469c2018-02-08 15:05:44 -0500413 }
Robert Phillipse8fabb22018-02-04 14:33:21 -0500414 if (!surface) {
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400415 fProxy->fDimensions.setEmpty();
Greg Danielbddcc952018-01-24 13:22:24 -0500416 return false;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700417 }
418
Brian Salomon1d19da02019-09-11 17:39:30 -0400419 if (fProxy->isFullyLazy()) {
Robert Phillipsc1b60662018-06-26 10:20:08 -0400420 // This was a fully lazy proxy. We need to fill in the width & height. For partially
421 // lazy proxies we must preserve the original width & height since that indicates
422 // the content area.
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400423 fProxy->fDimensions = surface->dimensions();
Robert Phillipsc1b60662018-06-26 10:20:08 -0400424 }
Chris Dalton706a6ff2017-11-29 22:01:06 -0700425
Brian Salomon9f2b86c2019-10-22 10:37:46 -0400426 SkASSERT(fProxy->width() <= surface->width());
427 SkASSERT(fProxy->height() <= surface->height());
Chris Daltonf91b7552019-04-29 16:21:18 -0600428
Greg Daniel303e83e2018-09-10 14:10:19 -0400429 if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400430 texProxy->setTargetKeySync(syncKey);
431 if (syncKey) {
432 const GrUniqueKey& key = texProxy->getUniqueKey();
433 if (key.isValid()) {
434 if (!surface->asTexture()->getUniqueKey().isValid()) {
435 // If 'surface' is newly created, attach the unique key
436 resourceProvider->assignUniqueKeyToResource(key, surface.get());
437 } else {
438 // otherwise we had better have reattached to a cached version
439 SkASSERT(surface->asTexture()->getUniqueKey() == key);
440 }
Robert Phillips0790f8a2018-09-18 13:11:03 -0400441 } else {
Brian Salomonb6a3a3b2019-04-01 12:29:34 -0400442 SkASSERT(!surface->getUniqueKey().isValid());
Robert Phillips0790f8a2018-09-18 13:11:03 -0400443 }
Greg Daniel303e83e2018-09-10 14:10:19 -0400444 }
445 }
446
Robert Phillipse8fabb22018-02-04 14:33:21 -0500447 this->assign(std::move(surface));
Brian Salomonbeb7f522019-08-30 16:19:42 -0400448 if (releaseCallback) {
449 fProxy->fLazyInstantiateCallback = nullptr;
450 }
451
Greg Danielbddcc952018-01-24 13:22:24 -0500452 return true;
Chris Dalton706a6ff2017-11-29 22:01:06 -0700453}
454
Greg Daniel849dce12018-04-24 14:32:53 -0400455#ifdef SK_DEBUG
456void GrSurfaceProxy::validateSurface(const GrSurface* surface) {
Greg Danield51fa2f2020-01-22 16:53:38 -0500457 SkASSERT(surface->backendFormat() == fFormat);
Greg Daniel849dce12018-04-24 14:32:53 -0400458
Greg Daniel849dce12018-04-24 14:32:53 -0400459 this->onValidateSurface(surface);
460}
461#endif