blob: b07366265c21d4437df8163a02159559fedc5e23 [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
Robert Phillips5af44de2017-07-18 14:49:38 -040043sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(
44 GrResourceProvider* resourceProvider, int sampleCnt,
45 GrSurfaceFlags flags, bool isMipMapped,
46 SkDestinationSurfaceColorMode mipColorMode) const {
Brian Salomonbb5711a2017-05-17 13:49:59 -040047 GrSurfaceDesc desc;
48 desc.fConfig = fConfig;
49 desc.fWidth = fWidth;
50 desc.fHeight = fHeight;
51 desc.fOrigin = fOrigin;
52 desc.fSampleCnt = sampleCnt;
53 desc.fIsMipMapped = isMipMapped;
54 desc.fFlags = flags;
Brian Salomond17b4a62017-05-23 16:53:47 -040055 if (fNeedsClear) {
56 desc.fFlags |= kPerformInitialClear_GrSurfaceFlag;
57 }
Robert Phillipseaa86252016-11-08 13:49:39 +000058
Robert Phillips5af44de2017-07-18 14:49:38 -040059 sk_sp<GrSurface> surface;
Robert Phillipseaa86252016-11-08 13:49:39 +000060 if (SkBackingFit::kApprox == fFit) {
Robert Phillips5af44de2017-07-18 14:49:38 -040061 surface.reset(resourceProvider->createApproxTexture(desc, fFlags).release());
Robert Phillipseaa86252016-11-08 13:49:39 +000062 } else {
Robert Phillips5af44de2017-07-18 14:49:38 -040063 surface.reset(resourceProvider->createTexture(desc, fBudgeted, fFlags).release());
Robert Phillipseaa86252016-11-08 13:49:39 +000064 }
Robert Phillips5af44de2017-07-18 14:49:38 -040065 if (surface) {
66 surface->asTexture()->texturePriv().setMipColorMode(mipColorMode);
Robert Phillipseaa86252016-11-08 13:49:39 +000067 }
68
Robert Phillips5af44de2017-07-18 14:49:38 -040069 return surface;
70}
71
72void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
73 SkASSERT(!fTarget && surface);
74 fTarget = surface.release();
robertphillips1125a032016-11-16 11:17:17 -080075 this->INHERITED::transferRefs();
76
Robert Phillipseaa86252016-11-08 13:49:39 +000077#ifdef SK_DEBUG
78 if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
Robert Phillips784b7bf2016-12-09 13:35:02 -050079 SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
Robert Phillipseaa86252016-11-08 13:49:39 +000080 }
81#endif
Robert Phillips5af44de2017-07-18 14:49:38 -040082}
Robert Phillipseaa86252016-11-08 13:49:39 +000083
Robert Phillips5af44de2017-07-18 14:49:38 -040084bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
85 GrSurfaceFlags flags, bool isMipMapped,
86 SkDestinationSurfaceColorMode mipColorMode) {
87 if (fTarget) {
88 return true;
89 }
90
91 sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, flags,
92 isMipMapped, mipColorMode);
93 if (!surface) {
94 return false;
95 }
96
97 this->assign(std::move(surface));
Robert Phillipseee4d6e2017-06-05 09:26:07 -040098 return true;
Robert Phillipseaa86252016-11-08 13:49:39 +000099}
100
Robert Phillipsf2361d22016-10-25 14:20:06 -0400101void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400102#ifdef SK_DEBUG
Robert Phillipsf2361d22016-10-25 14:20:06 -0400103 if (fLastOpList) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400104 SkASSERT(fLastOpList->isClosed());
Robert Phillips4a395042017-04-24 16:27:17 +0000105 }
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400106#endif
Robert Phillipsf2361d22016-10-25 14:20:06 -0400107
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400108 // Un-reffed
109 fLastOpList = opList;
Robert Phillipsf2361d22016-10-25 14:20:06 -0400110}
Robert Phillips37430132016-11-09 06:50:43 -0500111
Brian Osman45580d32016-11-23 09:37:01 -0500112GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
113 return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
114}
115
116GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
117 return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
118}
119
Robert Phillips37430132016-11-09 06:50:43 -0500120sk_sp<GrSurfaceProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrSurface> surf) {
Robert Phillipsbc7a4fb2017-01-23 15:30:35 -0500121 if (!surf) {
122 return nullptr;
123 }
124
Robert Phillips37430132016-11-09 06:50:43 -0500125 if (surf->asTexture()) {
126 if (surf->asRenderTarget()) {
127 return sk_sp<GrSurfaceProxy>(new GrTextureRenderTargetProxy(std::move(surf)));
128 } else {
129 return sk_sp<GrSurfaceProxy>(new GrTextureProxy(std::move(surf)));
130 }
131 } else {
132 SkASSERT(surf->asRenderTarget());
133
134 // Not texturable
135 return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(surf)));
136 }
137}
138
Robert Phillips63c67462017-02-15 14:19:01 -0500139sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrTexture> tex) {
140 if (!tex) {
141 return nullptr;
142 }
143
144 if (tex->asRenderTarget()) {
145 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex)));
146 } else {
147 return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex)));
148 }
149}
150
Brian Osman32342f02017-03-04 08:12:46 -0500151sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
Robert Phillips37430132016-11-09 06:50:43 -0500152 const GrSurfaceDesc& desc,
153 SkBackingFit fit,
Robert Phillipsc787e492017-02-28 11:26:32 -0500154 SkBudgeted budgeted,
155 uint32_t flags) {
156 SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
157
Robert Phillips26c90e02017-03-14 14:39:29 -0400158 const GrCaps* caps = resourceProvider->caps();
159
160 // TODO: move this logic into GrResourceProvider!
Robert Phillips8f741bb2017-01-31 17:25:29 -0500161 // TODO: share this testing code with check_texture_creation_params
Robert Phillips26c90e02017-03-14 14:39:29 -0400162 if (!caps->isConfigTexturable(desc.fConfig)) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500163 return nullptr;
164 }
165
166 bool willBeRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
Robert Phillips26c90e02017-03-14 14:39:29 -0400167 if (willBeRT && !caps->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500168 return nullptr;
169 }
170
171 // We currently do not support multisampled textures
172 if (!willBeRT && desc.fSampleCnt > 0) {
173 return nullptr;
174 }
175
176 int maxSize;
177 if (willBeRT) {
Robert Phillips26c90e02017-03-14 14:39:29 -0400178 maxSize = caps->maxRenderTargetSize();
Robert Phillips8f741bb2017-01-31 17:25:29 -0500179 } else {
Robert Phillips26c90e02017-03-14 14:39:29 -0400180 maxSize = caps->maxTextureSize();
Robert Phillips8f741bb2017-01-31 17:25:29 -0500181 }
182
Robert Phillips78de2122017-04-26 07:44:26 -0400183 if (desc.fWidth > maxSize || desc.fHeight > maxSize || desc.fWidth <= 0 || desc.fHeight <= 0) {
Robert Phillips8f741bb2017-01-31 17:25:29 -0500184 return nullptr;
185 }
186
Robert Phillips6520a692017-02-01 09:20:00 -0500187 GrSurfaceDesc copyDesc = desc;
Robert Phillips26c90e02017-03-14 14:39:29 -0400188 copyDesc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
Robert Phillips6520a692017-02-01 09:20:00 -0500189
Robert Phillips8f741bb2017-01-31 17:25:29 -0500190 if (willBeRT) {
Robert Phillips37430132016-11-09 06:50:43 -0500191 // We know anything we instantiate later from this deferred path will be
192 // both texturable and renderable
Robert Phillips26c90e02017-03-14 14:39:29 -0400193 return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, copyDesc, fit,
Robert Phillipsc787e492017-02-28 11:26:32 -0500194 budgeted, flags));
Robert Phillips37430132016-11-09 06:50:43 -0500195 }
196
Robert Phillips2f493142017-03-02 18:18:38 -0500197 return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
Robert Phillips37430132016-11-09 06:50:43 -0500198}
199
Robert Phillips26c90e02017-03-14 14:39:29 -0400200sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
Robert Phillips37430132016-11-09 06:50:43 -0500201 const GrSurfaceDesc& desc,
202 SkBudgeted budgeted,
203 const void* srcData,
204 size_t rowBytes) {
205 if (srcData) {
Robert Phillips45fdae12017-04-17 12:57:27 -0400206 GrMipLevel mipLevel = { srcData, rowBytes };
207
208 return resourceProvider->createTextureProxy(desc, budgeted, mipLevel);
Robert Phillips37430132016-11-09 06:50:43 -0500209 }
210
Robert Phillips26c90e02017-03-14 14:39:29 -0400211 return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, SkBackingFit::kExact, budgeted);
Robert Phillips37430132016-11-09 06:50:43 -0500212}
213
Robert Phillips8e8c7552017-07-10 12:06:05 -0400214sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferredMipMap(
215 GrResourceProvider* resourceProvider,
216 const GrSurfaceDesc& desc,
217 SkBudgeted budgeted,
Robert Phillips590533f2017-07-11 14:22:35 -0400218 const GrMipLevel texels[],
Robert Phillips8e8c7552017-07-10 12:06:05 -0400219 int mipLevelCount,
220 SkDestinationSurfaceColorMode mipColorMode) {
221 if (!mipLevelCount) {
222 if (texels) {
223 return nullptr;
224 }
225 return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, budgeted, nullptr, 0);
226 } else if (1 == mipLevelCount) {
227 if (!texels) {
228 return nullptr;
229 }
230 return resourceProvider->createTextureProxy(desc, budgeted, texels[0]);
231 }
232
Robert Phillips8e8c7552017-07-10 12:06:05 -0400233 for (int i = 0; i < mipLevelCount; ++i) {
234 if (!texels[i].fPixels) {
235 return nullptr;
236 }
Robert Phillips8e8c7552017-07-10 12:06:05 -0400237 }
238
239 sk_sp<GrTexture> tex(resourceProvider->createTexture(desc, budgeted,
Robert Phillips590533f2017-07-11 14:22:35 -0400240 texels, mipLevelCount, mipColorMode));
Robert Phillips8e8c7552017-07-10 12:06:05 -0400241 if (!tex) {
242 return nullptr;
243 }
244
245 return GrSurfaceProxy::MakeWrapped(std::move(tex));
246}
247
Greg Daniel7ef28f32017-04-20 16:41:55 +0000248sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
249 GrBackendTexture& backendTex,
250 GrSurfaceOrigin origin) {
251 sk_sp<GrTexture> tex(context->resourceProvider()->wrapBackendTexture(
252 backendTex, origin, kNone_GrBackendTextureFlag, 0));
Robert Phillips26caf892017-01-27 10:58:31 -0500253 return GrSurfaceProxy::MakeWrapped(std::move(tex));
254}
255
Brian Osman45580d32016-11-23 09:37:01 -0500256#ifdef SK_DEBUG
257void GrSurfaceProxy::validate(GrContext* context) const {
258 if (fTarget) {
259 SkASSERT(fTarget->getContext() == context);
260 }
261
262 INHERITED::validate();
263}
264#endif
Robert Phillipse2f7d182016-12-15 09:23:05 -0500265
Robert Phillips63c67462017-02-15 14:19:01 -0500266sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context,
Robert Phillipse2f7d182016-12-15 09:23:05 -0500267 GrSurfaceProxy* src,
268 SkIRect srcRect,
269 SkBudgeted budgeted) {
270 if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
271 return nullptr;
272 }
273
Brian Salomon63e79732017-05-15 21:23:13 -0400274 GrSurfaceDesc dstDesc;
275 dstDesc.fConfig = src->config();
Robert Phillipse2f7d182016-12-15 09:23:05 -0500276 dstDesc.fWidth = srcRect.width();
277 dstDesc.fHeight = srcRect.height();
Brian Salomon63e79732017-05-15 21:23:13 -0400278 dstDesc.fOrigin = src->origin();
Robert Phillipse2f7d182016-12-15 09:23:05 -0500279
280 sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
281 dstDesc,
282 SkBackingFit::kExact,
283 budgeted));
284 if (!dstContext) {
285 return nullptr;
286 }
287
288 if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) {
289 return nullptr;
290 }
291
Robert Phillips63c67462017-02-15 14:19:01 -0500292 return dstContext->asTextureProxyRef();
293}
294
295sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context, GrSurfaceProxy* src,
296 SkBudgeted budgeted) {
297 return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
Robert Phillipse2f7d182016-12-15 09:23:05 -0500298}
299
Robert Phillipsd46697a2017-01-25 12:10:37 -0500300sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
301 GrSurfaceProxy* srcProxy) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500302
303 sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
304 dstDesc,
305 SkBackingFit::kExact,
Robert Phillipsd46697a2017-01-25 12:10:37 -0500306 SkBudgeted::kYes));
Robert Phillipse2f7d182016-12-15 09:23:05 -0500307 if (!dstContext) {
308 return nullptr;
309 }
310
Robert Phillipsd46697a2017-01-25 12:10:37 -0500311 if (!dstContext->copy(srcProxy)) {
Robert Phillipse2f7d182016-12-15 09:23:05 -0500312 return nullptr;
313 }
314
Robert Phillipsd46697a2017-01-25 12:10:37 -0500315 return dstContext;
Robert Phillipse2f7d182016-12-15 09:23:05 -0500316}
Robert Phillipsb726d582017-03-09 16:36:32 -0500317
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400318void GrSurfaceProxyPriv::exactify() {
319 if (this->isExact()) {
320 return;
321 }
322
323 SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
324
325 if (fProxy->fTarget) {
326 // The kApprox but already instantiated case. Setting the proxy's width & height to
327 // the instantiated width & height could have side-effects going forward, since we're
328 // obliterating the area of interest information. This call (exactify) only used
329 // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
330 // used for additional draws.
Brian Salomonbb5711a2017-05-17 13:49:59 -0400331 fProxy->fWidth = fProxy->fTarget->width();
332 fProxy->fHeight = fProxy->fTarget->height();
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400333 return;
334 }
335
336 // The kApprox uninstantiated case. Making this proxy be exact should be okay.
337 // It could mess things up if prior decisions were based on the approximate size.
338 fProxy->fFit = SkBackingFit::kExact;
339 // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
Robert Phillips6cdc22c2017-05-11 16:29:14 -0400340 // already been computed we want to leave it alone so that amount will be removed when
Robert Phillips0ae6faa2017-03-21 16:22:00 -0400341 // the special image goes away. If it hasn't been computed yet it might as well compute the
342 // exact amount.
343}
344