blob: 0d9198fd0d13a450581575b548f783b9c2606573 [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"
Brian Osman32342f02017-03-04 08:12:46 -050016#include "GrResourceProvider.h"
Robert Phillipse2f7d182016-12-15 09:23:05 -050017#include "GrSurfaceContext.h"
Robert Phillipsa4c41b32017-03-15 13:02:45 -040018#include "GrTexturePriv.h"
Robert Phillips37430132016-11-09 06:50:43 -050019#include "GrTextureRenderTargetProxy.h"
Robert Phillipsf2361d22016-10-25 14:20:06 -040020
Robert Phillips93f16332016-11-23 19:37:13 -050021#include "SkMathPriv.h"
22
Robert Phillipsc7635fa2016-10-28 13:25:24 -040023GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit)
Brian Salomonbb5711a2017-05-17 13:49:59 -040024 : INHERITED(std::move(surface))
25 , fConfig(fTarget->config())
26 , fWidth(fTarget->width())
27 , fHeight(fTarget->height())
28 , fOrigin(fTarget->origin())
29 , fFit(fit)
30 , fBudgeted(fTarget->resourcePriv().isBudgeted())
31 , fFlags(0)
32 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Brian Salomond17b4a62017-05-23 16:53:47 -040033 , fNeedsClear(false)
Brian Salomonbb5711a2017-05-17 13:49:59 -040034 , fGpuMemorySize(kInvalidGpuMemorySize)
35 , fLastOpList(nullptr) {}
Robert Phillipsc7635fa2016-10-28 13:25:24 -040036
Robert Phillipsf2361d22016-10-25 14:20:06 -040037GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillips6cdc22c2017-05-11 16:29:14 -040038 // For this to be deleted the opList that held a ref on it (if there was one) must have been
39 // deleted. Which would have cleared out this back pointer.
40 SkASSERT(!fLastOpList);
Robert Phillipsf2361d22016-10-25 14:20:06 -040041}
42
Brian Salomonbb5711a2017-05-17 13:49:59 -040043GrSurface* GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
Brian Salomon081e0e62017-05-17 14:27:58 -040044 GrSurfaceFlags flags, bool isMipMapped,
45 SkDestinationSurfaceColorMode mipColorMode) {
Robert Phillipseaa86252016-11-08 13:49:39 +000046 if (fTarget) {
47 return fTarget;
48 }
Brian Salomonbb5711a2017-05-17 13:49:59 -040049 GrSurfaceDesc desc;
50 desc.fConfig = fConfig;
51 desc.fWidth = fWidth;
52 desc.fHeight = fHeight;
53 desc.fOrigin = fOrigin;
54 desc.fSampleCnt = sampleCnt;
55 desc.fIsMipMapped = isMipMapped;
56 desc.fFlags = flags;
Brian Salomond17b4a62017-05-23 16:53:47 -040057 if (fNeedsClear) {
58 desc.fFlags |= kPerformInitialClear_GrSurfaceFlag;
59 }
Robert Phillipseaa86252016-11-08 13:49:39 +000060
61 if (SkBackingFit::kApprox == fFit) {
Brian Salomonbb5711a2017-05-17 13:49:59 -040062 fTarget = resourceProvider->createApproxTexture(desc, fFlags);
Robert Phillipseaa86252016-11-08 13:49:39 +000063 } else {
Brian Salomonbb5711a2017-05-17 13:49:59 -040064 fTarget = resourceProvider->createTexture(desc, fBudgeted, fFlags).release();
Robert Phillipseaa86252016-11-08 13:49:39 +000065 }
66 if (!fTarget) {
67 return nullptr;
68 }
69
Brian Salomon081e0e62017-05-17 14:27:58 -040070 fTarget->asTexture()->texturePriv().setMipColorMode(mipColorMode);
robertphillips1125a032016-11-16 11:17:17 -080071 this->INHERITED::transferRefs();
72
Robert Phillipseaa86252016-11-08 13:49:39 +000073#ifdef SK_DEBUG
74 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -050075 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +000076 }
77#endif
78
79 return fTarget;
80}
81
Robert Phillipsf2361d22016-10-25 14:20:06 -040082void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -040083#ifdef SK_DEBUG
Robert Phillipsf2361d22016-10-25 14:20:06 -040084 if (fLastOpList) {
Robert Phillipsf2361d22016-10-25 14:20:06 -040085 SkASSERT(fLastOpList->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +000086 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -040087#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -040088
Robert Phillips6cdc22c2017-05-11 16:29:14 -040089 // Un-reffed
90 fLastOpList = opList;
Robert Phillipsf2361d22016-10-25 14:20:06 -040091}
Robert Phillips37430132016-11-09 06:50:43 -050092
Brian Osman45580d32016-11-23 09:37:01 -050093GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
94 return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
95}
96
97GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
98 return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
99}
100
Robert Phillips37430132016-11-09 06:50:43 -0500101sk_sp<GrSurfaceProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrSurface> surf) {
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -0500102 if (!surf) {
103 return nullptr;
104 }
105
Robert Phillips37430132016-11-09 06:50:43 -0500106 if (surf->asTexture()) {
107 if (surf->asRenderTarget()) {
108 return sk_sp<GrSurfaceProxy>(new GrTextureRenderTargetProxy(std::move(surf)));
109 } else {
110 return sk_sp<GrSurfaceProxy>(new GrTextureProxy(std::move(surf)));
111 }
112 } else {
113 SkASSERT(surf->asRenderTarget());
114
115 // Not texturable
116 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(surf)));
117 }
118}
119
Robert Phillips63c67462017-02-15 14:19:01 -0500120sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrTexture> tex) {
121 if (!tex) {
122 return nullptr;
123 }
124
125 if (tex->asRenderTarget()) {
126 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex)));
127 } else {
128 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex)));
129 }
130}
131
Brian Osman32342f02017-03-04 08:12:46 -0500132sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
Robert Phillips37430132016-11-09 06:50:43 -0500133 const GrSurfaceDesc& desc,
134 SkBackingFit fit,
Robert Phillipsc787e492017-02-28 11:26:32 -0500135 SkBudgeted budgeted,
136 uint32_t flags) {
137 SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
138
Robert Phillips26c90e02017-03-14 14:39:29 -0400139 const GrCaps* caps = resourceProvider->caps();
140
141 // TODO: move this logic into GrResourceProvider!
Robert Phillips8f741bb2017-01-31 17:25:29 -0500142 // TODO: share this testing code with check_texture_creation_params
Robert Phillips26c90e02017-03-14 14:39:29 -0400143 if (!caps->isConfigTexturable(desc.fConfig)) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500144 return nullptr;
145 }
146
147 bool willBeRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
Robert Phillips26c90e02017-03-14 14:39:29 -0400148 if (willBeRT && !caps->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500149 return nullptr;
150 }
151
152 // We currently do not support multisampled textures
153 if (!willBeRT && desc.fSampleCnt > 0) {
154 return nullptr;
155 }
156
157 int maxSize;
158 if (willBeRT) {
Robert Phillips26c90e02017-03-14 14:39:29 -0400159 maxSize = caps->maxRenderTargetSize();
Robert Phillips8f741bb2017-01-31 17:25:29 -0500160 } else {
Robert Phillips26c90e02017-03-14 14:39:29 -0400161 maxSize = caps->maxTextureSize();
Robert Phillips8f741bb2017-01-31 17:25:29 -0500162 }
163
Robert Phillips78de2122017-04-26 07:44:26 -0400164 if (desc.fWidth > maxSize || desc.fHeight > maxSize || desc.fWidth <= 0 || desc.fHeight <= 0) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500165 return nullptr;
166 }
167
Robert Phillips6520a692017-02-01 09:20:00 -0500168 GrSurfaceDesc copyDesc = desc;
Robert Phillips26c90e02017-03-14 14:39:29 -0400169 copyDesc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
Robert Phillips6520a692017-02-01 09:20:00 -0500170
Robert Phillips8f741bb2017-01-31 17:25:29 -0500171 if (willBeRT) {
Robert Phillips37430132016-11-09 06:50:43 -0500172 // We know anything we instantiate later from this deferred path will be
173 // both texturable and renderable
Robert Phillips26c90e02017-03-14 14:39:29 -0400174 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, copyDesc, fit,
Robert Phillipsc787e492017-02-28 11:26:32 -0500175 budgeted, flags));
Robert Phillips37430132016-11-09 06:50:43 -0500176 }
177
Robert Phillips2f493142017-03-02 18:18:38 -0500178 return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
Robert Phillips37430132016-11-09 06:50:43 -0500179}
180
Robert Phillips26c90e02017-03-14 14:39:29 -0400181sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
Robert Phillips37430132016-11-09 06:50:43 -0500182 const GrSurfaceDesc& desc,
183 SkBudgeted budgeted,
184 const void* srcData,
185 size_t rowBytes) {
186 if (srcData) {
Robert Phillips45fdae12017-04-17 12:57:27 -0400187 GrMipLevel mipLevel = { srcData, rowBytes };
188
189 return resourceProvider->createTextureProxy(desc, budgeted, mipLevel);
Robert Phillips37430132016-11-09 06:50:43 -0500190 }
191
Robert Phillips26c90e02017-03-14 14:39:29 -0400192 return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, SkBackingFit::kExact, budgeted);
Robert Phillips37430132016-11-09 06:50:43 -0500193}
194
Greg Daniel7ef28f32017-04-20 16:41:55 +0000195sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
196 GrBackendTexture& backendTex,
197 GrSurfaceOrigin origin) {
198 sk_sp<GrTexture> tex(context->resourceProvider()->wrapBackendTexture(
199 backendTex, origin, kNone_GrBackendTextureFlag, 0));
Robert Phillips26caf892017-01-27 10:58:31 -0500200 return GrSurfaceProxy::MakeWrapped(std::move(tex));
201}
202
Brian Osman45580d32016-11-23 09:37:01 -0500203#ifdef SK_DEBUG
204void GrSurfaceProxy::validate(GrContext* context) const {
205 if (fTarget) {
206 SkASSERT(fTarget->getContext() == context);
207 }
208
209 INHERITED::validate();
210}
211#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500212
Robert Phillips63c67462017-02-15 14:19:01 -0500213sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500214 GrSurfaceProxy* src,
215 SkIRect srcRect,
216 SkBudgeted budgeted) {
217 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
218 return nullptr;
219 }
220
Brian Salomon63e79732017-05-15 21:23:13 -0400221 GrSurfaceDesc dstDesc;
222 dstDesc.fConfig = src->config();
Robert Phillipse2f7d182016-12-15 09:23:05 -0500223 dstDesc.fWidth = srcRect.width();
224 dstDesc.fHeight = srcRect.height();
Brian Salomon63e79732017-05-15 21:23:13 -0400225 dstDesc.fOrigin = src->origin();
Robert Phillipse2f7d182016-12-15 09:23:05 -0500226
227 sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
228 dstDesc,
229 SkBackingFit::kExact,
230 budgeted));
231 if (!dstContext) {
232 return nullptr;
233 }
234
235 if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) {
236 return nullptr;
237 }
238
Robert Phillips63c67462017-02-15 14:19:01 -0500239 return dstContext->asTextureProxyRef();
240}
241
242sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context, GrSurfaceProxy* src,
243 SkBudgeted budgeted) {
244 return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500245}
246
Robert Phillipsd46697a2017-01-25 12:10:37 -0500247sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
248 GrSurfaceProxy* srcProxy) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500249
250 sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
251 dstDesc,
252 SkBackingFit::kExact,
Robert Phillipsd46697a2017-01-25 12:10:37 -0500253 SkBudgeted::kYes));
Robert Phillipse2f7d182016-12-15 09:23:05 -0500254 if (!dstContext) {
255 return nullptr;
256 }
257
Robert Phillipsd46697a2017-01-25 12:10:37 -0500258 if (!dstContext->copy(srcProxy)) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500259 return nullptr;
260 }
261
Robert Phillipsd46697a2017-01-25 12:10:37 -0500262 return dstContext;
Robert Phillipse2f7d182016-12-15 09:23:05 -0500263}
Robert Phillipsb726d582017-03-09 16:36:32 -0500264
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400265void GrSurfaceProxyPriv::exactify() {
266 if (this->isExact()) {
267 return;
268 }
269
270 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
271
272 if (fProxy->fTarget) {
273 // The kApprox but already instantiated case. Setting the proxy's width & height to
274 // the instantiated width & height could have side-effects going forward, since we're
275 // obliterating the area of interest information. This call (exactify) only used
276 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
277 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400278 fProxy->fWidth = fProxy->fTarget->width();
279 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400280 return;
281 }
282
283 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
284 // It could mess things up if prior decisions were based on the approximate size.
285 fProxy->fFit = SkBackingFit::kExact;
286 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400287 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400288 // the special image goes away. If it hasn't been computed yet it might as well compute the
289 // exact amount.
290}
291