blob: 76523ce03a6b4711bd3b658a0a0abfc0234d6008 [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)
24 : INHERITED(std::move(surface))
25 , fDesc(fTarget->desc())
26 , fFit(fit)
27 , fBudgeted(fTarget->resourcePriv().isBudgeted())
Robert Phillipsc787e492017-02-28 11:26:32 -050028 , fFlags(0)
Robert Phillips294870f2016-11-11 12:38:40 -050029 , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
Robert Phillips8bc06d02016-11-01 17:28:40 -040030 , fGpuMemorySize(kInvalidGpuMemorySize)
Robert Phillipsc7635fa2016-10-28 13:25:24 -040031 , fLastOpList(nullptr) {
32}
33
Robert Phillipsf2361d22016-10-25 14:20:06 -040034GrSurfaceProxy::~GrSurfaceProxy() {
Robert Phillips4a395042017-04-24 16:27:17 +000035 if (fLastOpList) {
36 fLastOpList->clearTarget();
37 }
38 SkSafeUnref(fLastOpList);
Robert Phillipsf2361d22016-10-25 14:20:06 -040039}
40
Brian Osman32342f02017-03-04 08:12:46 -050041GrSurface* GrSurfaceProxy::instantiate(GrResourceProvider* resourceProvider) {
Robert Phillipseaa86252016-11-08 13:49:39 +000042 if (fTarget) {
43 return fTarget;
44 }
45
46 if (SkBackingFit::kApprox == fFit) {
Brian Osman32342f02017-03-04 08:12:46 -050047 fTarget = resourceProvider->createApproxTexture(fDesc, fFlags);
Robert Phillipseaa86252016-11-08 13:49:39 +000048 } else {
Robert Phillipse78b7252017-04-06 07:59:41 -040049 fTarget = resourceProvider->createTexture(fDesc, fBudgeted, fFlags).release();
Robert Phillipseaa86252016-11-08 13:49:39 +000050 }
51 if (!fTarget) {
52 return nullptr;
53 }
54
Robert Phillipsa4c41b32017-03-15 13:02:45 -040055 fTarget->asTexture()->texturePriv().setMipColorMode(fMipColorMode);
robertphillips1125a032016-11-16 11:17:17 -080056 this->INHERITED::transferRefs();
57
Robert Phillipseaa86252016-11-08 13:49:39 +000058#ifdef SK_DEBUG
59 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -050060 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +000061 }
62#endif
63
64 return fTarget;
65}
66
Robert Phillips784b7bf2016-12-09 13:35:02 -050067int GrSurfaceProxy::worstCaseWidth(const GrCaps& caps) const {
Robert Phillips93f16332016-11-23 19:37:13 -050068 if (fTarget) {
69 return fTarget->width();
70 }
71
72 if (SkBackingFit::kExact == fFit) {
73 return fDesc.fWidth;
74 }
75
Robert Phillips784b7bf2016-12-09 13:35:02 -050076 if (caps.reuseScratchTextures() || fDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
Brian Osman32342f02017-03-04 08:12:46 -050077 return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fDesc.fWidth));
Robert Phillips784b7bf2016-12-09 13:35:02 -050078 }
79
80 return fDesc.fWidth;
Robert Phillips93f16332016-11-23 19:37:13 -050081}
82
Robert Phillips784b7bf2016-12-09 13:35:02 -050083int GrSurfaceProxy::worstCaseHeight(const GrCaps& caps) const {
Robert Phillips93f16332016-11-23 19:37:13 -050084 if (fTarget) {
85 return fTarget->height();
86 }
87
88 if (SkBackingFit::kExact == fFit) {
89 return fDesc.fHeight;
90 }
91
Robert Phillips784b7bf2016-12-09 13:35:02 -050092 if (caps.reuseScratchTextures() || fDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
Brian Osman32342f02017-03-04 08:12:46 -050093 return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fDesc.fHeight));
Robert Phillips784b7bf2016-12-09 13:35:02 -050094 }
95
96 return fDesc.fHeight;
Robert Phillips93f16332016-11-23 19:37:13 -050097}
98
Robert Phillipsf2361d22016-10-25 14:20:06 -040099void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
100 if (fLastOpList) {
Robert Phillips4a395042017-04-24 16:27:17 +0000101 // The non-MDB world never closes so we can't check this condition
102#ifdef ENABLE_MDB
Robert Phillipsf2361d22016-10-25 14:20:06 -0400103 SkASSERT(fLastOpList->isClosed());
Robert Phillipsdf2bf212017-04-24 08:39:40 -0400104#endif
Robert Phillips4a395042017-04-24 16:27:17 +0000105 fLastOpList->clearTarget();
106 }
Robert Phillipsf2361d22016-10-25 14:20:06 -0400107
Robert Phillips4a395042017-04-24 16:27:17 +0000108 SkRefCnt_SafeAssign(fLastOpList, opList);
Robert Phillipsf2361d22016-10-25 14:20:06 -0400109}
Robert Phillips37430132016-11-09 06:50:43 -0500110
Brian Osman45580d32016-11-23 09:37:01 -0500111GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
112 return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
113}
114
115GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
116 return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
117}
118
Robert Phillips37430132016-11-09 06:50:43 -0500119sk_sp<GrSurfaceProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrSurface> surf) {
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -0500120 if (!surf) {
121 return nullptr;
122 }
123
Robert Phillips37430132016-11-09 06:50:43 -0500124 if (surf->asTexture()) {
125 if (surf->asRenderTarget()) {
126 return sk_sp<GrSurfaceProxy>(new GrTextureRenderTargetProxy(std::move(surf)));
127 } else {
128 return sk_sp<GrSurfaceProxy>(new GrTextureProxy(std::move(surf)));
129 }
130 } else {
131 SkASSERT(surf->asRenderTarget());
132
133 // Not texturable
134 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(surf)));
135 }
136}
137
Robert Phillips63c67462017-02-15 14:19:01 -0500138sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrTexture> tex) {
139 if (!tex) {
140 return nullptr;
141 }
142
143 if (tex->asRenderTarget()) {
144 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex)));
145 } else {
146 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex)));
147 }
148}
149
Brian Osman32342f02017-03-04 08:12:46 -0500150sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
Robert Phillips37430132016-11-09 06:50:43 -0500151 const GrSurfaceDesc& desc,
152 SkBackingFit fit,
Robert Phillipsc787e492017-02-28 11:26:32 -0500153 SkBudgeted budgeted,
154 uint32_t flags) {
155 SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
156
Robert Phillips26c90e02017-03-14 14:39:29 -0400157 const GrCaps* caps = resourceProvider->caps();
158
159 // TODO: move this logic into GrResourceProvider!
Robert Phillips8f741bb2017-01-31 17:25:29 -0500160 // TODO: share this testing code with check_texture_creation_params
Robert Phillips6520a692017-02-01 09:20:00 -0500161 if (GrPixelConfigIsCompressed(desc.fConfig)) {
162 if (SkBackingFit::kApprox == fit || kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
163 // We don't allow scratch compressed textures and, apparently can't Y-flip compressed
164 // textures
165 return nullptr;
166 }
167
Robert Phillips26c90e02017-03-14 14:39:29 -0400168 if (!caps->npotTextureTileSupport() && (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
Robert Phillips6520a692017-02-01 09:20:00 -0500169 return nullptr;
170 }
Robert Phillips08c5ec72017-01-30 12:26:47 -0500171 }
172
Robert Phillips26c90e02017-03-14 14:39:29 -0400173 if (!caps->isConfigTexturable(desc.fConfig)) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500174 return nullptr;
175 }
176
177 bool willBeRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
Robert Phillips26c90e02017-03-14 14:39:29 -0400178 if (willBeRT && !caps->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500179 return nullptr;
180 }
181
182 // We currently do not support multisampled textures
183 if (!willBeRT && desc.fSampleCnt > 0) {
184 return nullptr;
185 }
186
187 int maxSize;
188 if (willBeRT) {
Robert Phillips26c90e02017-03-14 14:39:29 -0400189 maxSize = caps->maxRenderTargetSize();
Robert Phillips8f741bb2017-01-31 17:25:29 -0500190 } else {
Robert Phillips26c90e02017-03-14 14:39:29 -0400191 maxSize = caps->maxTextureSize();
Robert Phillips8f741bb2017-01-31 17:25:29 -0500192 }
193
Robert Phillips78de2122017-04-26 07:44:26 -0400194 if (desc.fWidth > maxSize || desc.fHeight > maxSize || desc.fWidth <= 0 || desc.fHeight <= 0) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500195 return nullptr;
196 }
197
Robert Phillips6520a692017-02-01 09:20:00 -0500198 GrSurfaceDesc copyDesc = desc;
Robert Phillips26c90e02017-03-14 14:39:29 -0400199 copyDesc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
Robert Phillips6520a692017-02-01 09:20:00 -0500200
Robert Phillipscd901042017-04-27 12:04:15 -0400201#ifdef SK_DISABLE_DEFERRED_PROXIES
202 sk_sp<GrTexture> tex;
203
204 if (SkBackingFit::kApprox == fit) {
205 tex.reset(resourceProvider->createApproxTexture(copyDesc, flags));
206 } else {
207 tex = resourceProvider->createTexture(copyDesc, budgeted, flags);
208 }
209
210 if (!tex) {
211 return nullptr;
212 }
213
214 return GrSurfaceProxy::MakeWrapped(std::move(tex));
215#else
Robert Phillips8f741bb2017-01-31 17:25:29 -0500216 if (willBeRT) {
Robert Phillips37430132016-11-09 06:50:43 -0500217 // We know anything we instantiate later from this deferred path will be
218 // both texturable and renderable
Robert Phillips26c90e02017-03-14 14:39:29 -0400219 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, copyDesc, fit,
Robert Phillipsc787e492017-02-28 11:26:32 -0500220 budgeted, flags));
Robert Phillips37430132016-11-09 06:50:43 -0500221 }
222
Robert Phillips2f493142017-03-02 18:18:38 -0500223 return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
Robert Phillipscd901042017-04-27 12:04:15 -0400224#endif
Robert Phillips37430132016-11-09 06:50:43 -0500225}
226
Robert Phillips26c90e02017-03-14 14:39:29 -0400227sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
Robert Phillips37430132016-11-09 06:50:43 -0500228 const GrSurfaceDesc& desc,
229 SkBudgeted budgeted,
230 const void* srcData,
231 size_t rowBytes) {
232 if (srcData) {
Robert Phillips45fdae12017-04-17 12:57:27 -0400233 GrMipLevel mipLevel = { srcData, rowBytes };
234
235 return resourceProvider->createTextureProxy(desc, budgeted, mipLevel);
Robert Phillips37430132016-11-09 06:50:43 -0500236 }
237
Robert Phillips26c90e02017-03-14 14:39:29 -0400238 return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, SkBackingFit::kExact, budgeted);
Robert Phillips37430132016-11-09 06:50:43 -0500239}
240
Greg Daniel7ef28f32017-04-20 16:41:55 +0000241sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
242 GrBackendTexture& backendTex,
243 GrSurfaceOrigin origin) {
244 sk_sp<GrTexture> tex(context->resourceProvider()->wrapBackendTexture(
245 backendTex, origin, kNone_GrBackendTextureFlag, 0));
Robert Phillips26caf892017-01-27 10:58:31 -0500246 return GrSurfaceProxy::MakeWrapped(std::move(tex));
247}
248
Brian Osman45580d32016-11-23 09:37:01 -0500249#ifdef SK_DEBUG
250void GrSurfaceProxy::validate(GrContext* context) const {
251 if (fTarget) {
252 SkASSERT(fTarget->getContext() == context);
253 }
254
255 INHERITED::validate();
256}
257#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500258
Robert Phillips63c67462017-02-15 14:19:01 -0500259sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500260 GrSurfaceProxy* src,
261 SkIRect srcRect,
262 SkBudgeted budgeted) {
263 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
264 return nullptr;
265 }
266
267 GrSurfaceDesc dstDesc = src->desc();
268 dstDesc.fWidth = srcRect.width();
269 dstDesc.fHeight = srcRect.height();
270
271 sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
272 dstDesc,
273 SkBackingFit::kExact,
274 budgeted));
275 if (!dstContext) {
276 return nullptr;
277 }
278
279 if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) {
280 return nullptr;
281 }
282
Robert Phillips63c67462017-02-15 14:19:01 -0500283 return dstContext->asTextureProxyRef();
284}
285
286sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context, GrSurfaceProxy* src,
287 SkBudgeted budgeted) {
288 return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500289}
290
Robert Phillipsd46697a2017-01-25 12:10:37 -0500291sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
292 GrSurfaceProxy* srcProxy) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500293
294 sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
295 dstDesc,
296 SkBackingFit::kExact,
Robert Phillipsd46697a2017-01-25 12:10:37 -0500297 SkBudgeted::kYes));
Robert Phillipse2f7d182016-12-15 09:23:05 -0500298 if (!dstContext) {
299 return nullptr;
300 }
301
Robert Phillipsd46697a2017-01-25 12:10:37 -0500302 if (!dstContext->copy(srcProxy)) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500303 return nullptr;
304 }
305
Robert Phillipsd46697a2017-01-25 12:10:37 -0500306 return dstContext;
Robert Phillipse2f7d182016-12-15 09:23:05 -0500307}
Robert Phillipsb726d582017-03-09 16:36:32 -0500308
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400309void GrSurfaceProxyPriv::exactify() {
310 if (this->isExact()) {
311 return;
312 }
313
314 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
315
316 if (fProxy->fTarget) {
317 // The kApprox but already instantiated case. Setting the proxy's width & height to
318 // the instantiated width & height could have side-effects going forward, since we're
319 // obliterating the area of interest information. This call (exactify) only used
320 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
321 // used for additional draws.
322 fProxy->fDesc.fWidth = fProxy->fTarget->width();
323 fProxy->fDesc.fHeight = fProxy->fTarget->height();
324 return;
325 }
326
327 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
328 // It could mess things up if prior decisions were based on the approximate size.
329 fProxy->fFit = SkBackingFit::kExact;
330 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
331 // already been computed we want to leave it alone so that amount will be removed when
332 // the special image goes away. If it hasn't been computed yet it might as well compute the
333 // exact amount.
334}
335