Line data Source code
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 :
23 0 : GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit)
24 0 : : INHERITED(std::move(surface))
25 0 : , fDesc(fTarget->desc())
26 : , fFit(fit)
27 0 : , fBudgeted(fTarget->resourcePriv().isBudgeted())
28 : , fFlags(0)
29 0 : , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID!
30 : , fGpuMemorySize(kInvalidGpuMemorySize)
31 0 : , fLastOpList(nullptr) {
32 0 : }
33 :
34 0 : GrSurfaceProxy::~GrSurfaceProxy() {
35 0 : if (fLastOpList) {
36 0 : fLastOpList->clearTarget();
37 : }
38 0 : SkSafeUnref(fLastOpList);
39 0 : }
40 :
41 0 : GrSurface* GrSurfaceProxy::instantiate(GrResourceProvider* resourceProvider) {
42 0 : if (fTarget) {
43 0 : return fTarget;
44 : }
45 :
46 0 : if (SkBackingFit::kApprox == fFit) {
47 0 : fTarget = resourceProvider->createApproxTexture(fDesc, fFlags);
48 : } else {
49 0 : fTarget = resourceProvider->createTexture(fDesc, fBudgeted, fFlags).release();
50 : }
51 0 : if (!fTarget) {
52 0 : return nullptr;
53 : }
54 :
55 0 : fTarget->asTexture()->texturePriv().setMipColorMode(fMipColorMode);
56 0 : this->INHERITED::transferRefs();
57 :
58 : #ifdef SK_DEBUG
59 0 : if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
60 0 : SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
61 : }
62 : #endif
63 :
64 0 : return fTarget;
65 : }
66 :
67 0 : int GrSurfaceProxy::worstCaseWidth(const GrCaps& caps) const {
68 0 : if (fTarget) {
69 0 : return fTarget->width();
70 : }
71 :
72 0 : if (SkBackingFit::kExact == fFit) {
73 0 : return fDesc.fWidth;
74 : }
75 :
76 0 : if (caps.reuseScratchTextures() || fDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
77 0 : return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fDesc.fWidth));
78 : }
79 :
80 0 : return fDesc.fWidth;
81 : }
82 :
83 0 : int GrSurfaceProxy::worstCaseHeight(const GrCaps& caps) const {
84 0 : if (fTarget) {
85 0 : return fTarget->height();
86 : }
87 :
88 0 : if (SkBackingFit::kExact == fFit) {
89 0 : return fDesc.fHeight;
90 : }
91 :
92 0 : if (caps.reuseScratchTextures() || fDesc.fFlags & kRenderTarget_GrSurfaceFlag) {
93 0 : return SkTMax(GrResourceProvider::kMinScratchTextureSize, GrNextPow2(fDesc.fHeight));
94 : }
95 :
96 0 : return fDesc.fHeight;
97 : }
98 :
99 0 : void GrSurfaceProxy::setLastOpList(GrOpList* opList) {
100 0 : if (fLastOpList) {
101 : // The non-MDB world never closes so we can't check this condition
102 : #ifdef ENABLE_MDB
103 : SkASSERT(fLastOpList->isClosed());
104 : #endif
105 0 : fLastOpList->clearTarget();
106 : }
107 :
108 0 : SkRefCnt_SafeAssign(fLastOpList, opList);
109 0 : }
110 :
111 0 : GrRenderTargetOpList* GrSurfaceProxy::getLastRenderTargetOpList() {
112 0 : return fLastOpList ? fLastOpList->asRenderTargetOpList() : nullptr;
113 : }
114 :
115 0 : GrTextureOpList* GrSurfaceProxy::getLastTextureOpList() {
116 0 : return fLastOpList ? fLastOpList->asTextureOpList() : nullptr;
117 : }
118 :
119 0 : sk_sp<GrSurfaceProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrSurface> surf) {
120 0 : if (!surf) {
121 0 : return nullptr;
122 : }
123 :
124 0 : if (surf->asTexture()) {
125 0 : if (surf->asRenderTarget()) {
126 0 : return sk_sp<GrSurfaceProxy>(new GrTextureRenderTargetProxy(std::move(surf)));
127 : } else {
128 0 : return sk_sp<GrSurfaceProxy>(new GrTextureProxy(std::move(surf)));
129 : }
130 : } else {
131 0 : SkASSERT(surf->asRenderTarget());
132 :
133 : // Not texturable
134 0 : return sk_sp<GrSurfaceProxy>(new GrRenderTargetProxy(std::move(surf)));
135 : }
136 : }
137 :
138 0 : sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrapped(sk_sp<GrTexture> tex) {
139 0 : if (!tex) {
140 0 : return nullptr;
141 : }
142 :
143 0 : if (tex->asRenderTarget()) {
144 0 : return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(std::move(tex)));
145 : } else {
146 0 : return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(tex)));
147 : }
148 : }
149 :
150 : #include "GrResourceProvider.h"
151 :
152 0 : sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
153 : const GrSurfaceDesc& desc,
154 : SkBackingFit fit,
155 : SkBudgeted budgeted,
156 : uint32_t flags) {
157 0 : SkASSERT(0 == flags || GrResourceProvider::kNoPendingIO_Flag == flags);
158 :
159 0 : const GrCaps* caps = resourceProvider->caps();
160 :
161 : // TODO: move this logic into GrResourceProvider!
162 : // TODO: share this testing code with check_texture_creation_params
163 0 : if (GrPixelConfigIsCompressed(desc.fConfig)) {
164 0 : if (SkBackingFit::kApprox == fit || kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
165 : // We don't allow scratch compressed textures and, apparently can't Y-flip compressed
166 : // textures
167 0 : return nullptr;
168 : }
169 :
170 0 : if (!caps->npotTextureTileSupport() && (!SkIsPow2(desc.fWidth) || !SkIsPow2(desc.fHeight))) {
171 0 : return nullptr;
172 : }
173 : }
174 :
175 0 : if (!caps->isConfigTexturable(desc.fConfig)) {
176 0 : return nullptr;
177 : }
178 :
179 0 : bool willBeRT = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
180 0 : if (willBeRT && !caps->isConfigRenderable(desc.fConfig, desc.fSampleCnt > 0)) {
181 0 : return nullptr;
182 : }
183 :
184 : // We currently do not support multisampled textures
185 0 : if (!willBeRT && desc.fSampleCnt > 0) {
186 0 : return nullptr;
187 : }
188 :
189 : int maxSize;
190 0 : if (willBeRT) {
191 0 : maxSize = caps->maxRenderTargetSize();
192 : } else {
193 0 : maxSize = caps->maxTextureSize();
194 : }
195 :
196 0 : if (desc.fWidth > maxSize || desc.fHeight > maxSize) {
197 0 : return nullptr;
198 : }
199 :
200 0 : GrSurfaceDesc copyDesc = desc;
201 0 : copyDesc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount());
202 :
203 : #ifdef SK_DISABLE_DEFERRED_PROXIES
204 : sk_sp<GrTexture> tex;
205 :
206 : if (SkBackingFit::kApprox == fit) {
207 : tex.reset(resourceProvider->createApproxTexture(copyDesc, flags));
208 : } else {
209 : tex = resourceProvider->createTexture(copyDesc, budgeted, flags);
210 : }
211 :
212 : if (!tex) {
213 : return nullptr;
214 : }
215 :
216 : return GrSurfaceProxy::MakeWrapped(std::move(tex));
217 : #else
218 0 : if (willBeRT) {
219 : // We know anything we instantiate later from this deferred path will be
220 : // both texturable and renderable
221 : return sk_sp<GrTextureProxy>(new GrTextureRenderTargetProxy(*caps, copyDesc, fit,
222 0 : budgeted, flags));
223 : }
224 :
225 0 : return sk_sp<GrTextureProxy>(new GrTextureProxy(copyDesc, fit, budgeted, nullptr, 0, flags));
226 : #endif
227 : }
228 :
229 0 : sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferred(GrResourceProvider* resourceProvider,
230 : const GrSurfaceDesc& desc,
231 : SkBudgeted budgeted,
232 : const void* srcData,
233 : size_t rowBytes) {
234 0 : if (srcData) {
235 : GrMipLevel tempTexels;
236 0 : GrMipLevel* texels = nullptr;
237 0 : int levelCount = 0;
238 0 : if (srcData) {
239 0 : tempTexels.fPixels = srcData;
240 0 : tempTexels.fRowBytes = rowBytes;
241 0 : texels = &tempTexels;
242 0 : levelCount = 1;
243 : }
244 0 : return resourceProvider->createMipMappedTexture(desc, budgeted, texels, levelCount);
245 : }
246 :
247 0 : return GrSurfaceProxy::MakeDeferred(resourceProvider, desc, SkBackingFit::kExact, budgeted);
248 : }
249 :
250 0 : sk_sp<GrSurfaceProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
251 : GrBackendTextureDesc& desc) {
252 0 : sk_sp<GrTexture> tex(context->resourceProvider()->wrapBackendTexture(desc));
253 0 : return GrSurfaceProxy::MakeWrapped(std::move(tex));
254 : }
255 :
256 : #ifdef SK_DEBUG
257 0 : void GrSurfaceProxy::validate(GrContext* context) const {
258 0 : if (fTarget) {
259 0 : SkASSERT(fTarget->getContext() == context);
260 : }
261 :
262 0 : INHERITED::validate();
263 0 : }
264 : #endif
265 :
266 0 : sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context,
267 : GrSurfaceProxy* src,
268 : SkIRect srcRect,
269 : SkBudgeted budgeted) {
270 0 : if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
271 0 : return nullptr;
272 : }
273 :
274 0 : GrSurfaceDesc dstDesc = src->desc();
275 0 : dstDesc.fWidth = srcRect.width();
276 0 : dstDesc.fHeight = srcRect.height();
277 :
278 0 : sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
279 : dstDesc,
280 : SkBackingFit::kExact,
281 0 : budgeted));
282 0 : if (!dstContext) {
283 0 : return nullptr;
284 : }
285 :
286 0 : if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) {
287 0 : return nullptr;
288 : }
289 :
290 0 : return dstContext->asTextureProxyRef();
291 : }
292 :
293 0 : sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context, GrSurfaceProxy* src,
294 : SkBudgeted budgeted) {
295 0 : return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
296 : }
297 :
298 0 : sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
299 : GrSurfaceProxy* srcProxy) {
300 :
301 0 : sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
302 : dstDesc,
303 : SkBackingFit::kExact,
304 0 : SkBudgeted::kYes));
305 0 : if (!dstContext) {
306 0 : return nullptr;
307 : }
308 :
309 0 : if (!dstContext->copy(srcProxy)) {
310 0 : return nullptr;
311 : }
312 :
313 0 : return dstContext;
314 : }
315 :
316 0 : void GrSurfaceProxyPriv::exactify() {
317 0 : if (this->isExact()) {
318 0 : return;
319 : }
320 :
321 0 : SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
322 :
323 0 : if (fProxy->fTarget) {
324 : // The kApprox but already instantiated case. Setting the proxy's width & height to
325 : // the instantiated width & height could have side-effects going forward, since we're
326 : // obliterating the area of interest information. This call (exactify) only used
327 : // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
328 : // used for additional draws.
329 0 : fProxy->fDesc.fWidth = fProxy->fTarget->width();
330 0 : fProxy->fDesc.fHeight = fProxy->fTarget->height();
331 0 : return;
332 : }
333 :
334 : // The kApprox uninstantiated case. Making this proxy be exact should be okay.
335 : // It could mess things up if prior decisions were based on the approximate size.
336 0 : fProxy->fFit = SkBackingFit::kExact;
337 : // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
338 : // already been computed we want to leave it alone so that amount will be removed when
339 : // the special image goes away. If it hasn't been computed yet it might as well compute the
340 : // exact amount.
341 : }
342 :
|