• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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"
9 #include "GrSurfaceProxyPriv.h"
10 
11 #include "GrCaps.h"
12 #include "GrContext.h"
13 #include "GrContextPriv.h"
14 #include "GrGpuResourcePriv.h"
15 #include "GrOpList.h"
16 #include "GrResourceProvider.h"
17 #include "GrSurfaceContext.h"
18 #include "GrTexturePriv.h"
19 #include "GrTextureRenderTargetProxy.h"
20 
21 #include "SkMathPriv.h"
22 
GrSurfaceProxy(sk_sp<GrSurface> surface,SkBackingFit fit)23 GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit)
24         : 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!
33         , fNeedsClear(false)
34         , fGpuMemorySize(kInvalidGpuMemorySize)
35         , fLastOpList(nullptr) {}
36 
~GrSurfaceProxy()37 GrSurfaceProxy::~GrSurfaceProxy() {
38     // 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);
41 }
42 
createSurfaceImpl(GrResourceProvider * resourceProvider,int sampleCnt,GrSurfaceFlags flags,bool isMipMapped,SkDestinationSurfaceColorMode mipColorMode) const43 sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(
44                                                 GrResourceProvider* resourceProvider, int sampleCnt,
45                                                 GrSurfaceFlags flags, bool isMipMapped,
46                                                 SkDestinationSurfaceColorMode mipColorMode) const {
47     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;
55     if (fNeedsClear) {
56         desc.fFlags |= kPerformInitialClear_GrSurfaceFlag;
57     }
58 
59     sk_sp<GrSurface> surface;
60     if (SkBackingFit::kApprox == fFit) {
61         surface.reset(resourceProvider->createApproxTexture(desc, fFlags).release());
62     } else {
63         surface.reset(resourceProvider->createTexture(desc, fBudgeted, fFlags).release());
64     }
65     if (surface) {
66         surface->asTexture()->texturePriv().setMipColorMode(mipColorMode);
67     }
68 
69     return surface;
70 }
71 
assign(sk_sp<GrSurface> surface)72 void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
73     SkASSERT(!fTarget && surface);
74     fTarget = surface.release();
75     this->INHERITED::transferRefs();
76 
77 #ifdef SK_DEBUG
78     if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
79         SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
80     }
81 #endif
82 }
83 
instantiateImpl(GrResourceProvider * resourceProvider,int sampleCnt,GrSurfaceFlags flags,bool isMipMapped,SkDestinationSurfaceColorMode mipColorMode)84 bool 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));
98     return true;
99 }
100 
setLastOpList(GrOpList * opList)101 void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
102 #ifdef SK_DEBUG
103     if (fLastOpList) {
104         SkASSERT(fLastOpList->isClosed());
105     }
106 #endif
107 
108     // Un-reffed
109     fLastOpList = opList;
110 }
111 
getLastRenderTargetOpList()112 GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
113     return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
114 }
115 
getLastTextureOpList()116 GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
117     return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
118 }
119 
MakeWrapped(sk_sp<GrSurface> surf)120 sk_sp<GrSurfaceProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrSurface> surf) {
121     if (!surf) {
122         return nullptr;
123     }
124 
125     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 
MakeWrapped(sk_sp<GrTexture> tex)139 sk_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 
MakeDeferred(GrResourceProvider * resourceProvider,const GrSurfaceDesc & desc,SkBackingFit fit,SkBudgeted budgeted,uint32_t flags)151 sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
152                                                    const GrSurfaceDesc& desc,
153                                                    SkBackingFit fit,
154                                                    SkBudgeted budgeted,
155                                                    uint32_t flags) {
156     SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
157 
158     const GrCaps* caps = resourceProvider->caps();
159 
160     // TODO: move this logic into GrResourceProvider!
161     // TODO: share this testing code with check_texture_creation_params
162     if (!caps->isConfigTexturable(desc.fConfig)) {
163         return nullptr;
164     }
165 
166     bool willBeRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
167     if (willBeRT && !caps->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
168         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) {
178         maxSize = caps->maxRenderTargetSize();
179     } else {
180         maxSize = caps->maxTextureSize();
181     }
182 
183     if (desc.fWidth > maxSize || desc.fHeight > maxSize || desc.fWidth <= 0 || desc.fHeight <= 0) {
184         return nullptr;
185     }
186 
187     GrSurfaceDesc copyDesc = desc;
188     copyDesc.fSampleCnt = caps->getSampleCount(desc.fSampleCnt, desc.fConfig);
189 
190     if (willBeRT) {
191         // We know anything we instantiate later from this deferred path will be
192         // both texturable and renderable
193         return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, copyDesc, fit,
194                                                                     budgeted, flags));
195     }
196 
197     return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
198 }
199 
MakeDeferred(GrResourceProvider * resourceProvider,const GrSurfaceDesc & desc,SkBudgeted budgeted,const void * srcData,size_t rowBytes)200 sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
201                                                    const GrSurfaceDesc& desc,
202                                                    SkBudgeted budgeted,
203                                                    const void* srcData,
204                                                    size_t rowBytes) {
205     if (srcData) {
206         GrMipLevel mipLevel = { srcData, rowBytes };
207 
208         return resourceProvider->createTextureProxy(desc, budgeted, mipLevel);
209     }
210 
211     return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, SkBackingFit::kExact, budgeted);
212 }
213 
MakeDeferredMipMap(GrResourceProvider * resourceProvider,const GrSurfaceDesc & desc,SkBudgeted budgeted,const GrMipLevel texels[],int mipLevelCount,SkDestinationSurfaceColorMode mipColorMode)214 sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferredMipMap(
215                                                     GrResourceProvider* resourceProvider,
216                                                     const GrSurfaceDesc& desc,
217                                                     SkBudgeted budgeted,
218                                                     const GrMipLevel texels[],
219                                                     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 
233     for (int i = 0; i < mipLevelCount; ++i) {
234         if (!texels[i].fPixels) {
235             return nullptr;
236         }
237     }
238 
239     sk_sp<GrTexture> tex(resourceProvider->createTexture(desc, budgeted,
240                                                          texels, mipLevelCount, mipColorMode));
241     if (!tex) {
242         return nullptr;
243     }
244 
245     return GrSurfaceProxy::MakeWrapped(std::move(tex));
246 }
247 
MakeWrappedBackend(GrContext * context,GrBackendTexture & backendTex,GrSurfaceOrigin origin)248 sk_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));
253     return GrSurfaceProxy::MakeWrapped(std::move(tex));
254 }
255 
256 #ifdef SK_DEBUG
validate(GrContext * context) const257 void GrSurfaceProxy::validate(GrContext* context) const {
258     if (fTarget) {
259         SkASSERT(fTarget->getContext() == context);
260     }
261 
262     INHERITED::validate();
263 }
264 #endif
265 
Copy(GrContext * context,GrSurfaceProxy * src,SkIRect srcRect,SkBudgeted budgeted)266 sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context,
267                                            GrSurfaceProxy* src,
268                                            SkIRect srcRect,
269                                            SkBudgeted budgeted) {
270     if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
271         return nullptr;
272     }
273 
274     GrSurfaceDesc dstDesc;
275     dstDesc.fConfig = src->config();
276     dstDesc.fWidth = srcRect.width();
277     dstDesc.fHeight = srcRect.height();
278     dstDesc.fOrigin = src->origin();
279 
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 
292     return dstContext->asTextureProxyRef();
293 }
294 
Copy(GrContext * context,GrSurfaceProxy * src,SkBudgeted budgeted)295 sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context, GrSurfaceProxy* src,
296                                            SkBudgeted budgeted) {
297     return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
298 }
299 
TestCopy(GrContext * context,const GrSurfaceDesc & dstDesc,GrSurfaceProxy * srcProxy)300 sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
301                                                  GrSurfaceProxy* srcProxy) {
302 
303     sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
304                                                                             dstDesc,
305                                                                             SkBackingFit::kExact,
306                                                                             SkBudgeted::kYes));
307     if (!dstContext) {
308         return nullptr;
309     }
310 
311     if (!dstContext->copy(srcProxy)) {
312         return nullptr;
313     }
314 
315     return dstContext;
316 }
317 
exactify()318 void 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.
331         fProxy->fWidth = fProxy->fTarget->width();
332         fProxy->fHeight = fProxy->fTarget->height();
333         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
340     // already been computed we want to leave it alone so that amount will be removed when
341     // the special image goes away. If it hasn't been computed yet it might as well compute the
342     // exact amount.
343 }
344 
345