1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2016 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxy.h"
9cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/gpu/GrRecordingContext.h"
12cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h"
13cb93a386Sopenharmony_ci#include "src/gpu/GrAttachment.h"
14cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
15cb93a386Sopenharmony_ci#include "src/gpu/GrGpuResourcePriv.h"
16cb93a386Sopenharmony_ci#include "src/gpu/GrImageInfo.h"
17cb93a386Sopenharmony_ci#include "src/gpu/GrRecordingContextPriv.h"
18cb93a386Sopenharmony_ci#include "src/gpu/GrResourceProvider.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrSurface.h"
20cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h"
21cb93a386Sopenharmony_ci#include "src/gpu/GrTextureRenderTargetProxy.h"
22cb93a386Sopenharmony_ci#include "src/gpu/SurfaceFillContext.h"
23cb93a386Sopenharmony_ci
24cb93a386Sopenharmony_ci#ifdef SK_DEBUG
25cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
26cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
27cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h"
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_cistatic bool is_valid_lazy(const SkISize& dimensions, SkBackingFit fit) {
30cb93a386Sopenharmony_ci    // A "fully" lazy proxy's width and height are not known until instantiation time.
31cb93a386Sopenharmony_ci    // So fully lazy proxies are created with width and height < 0. Regular lazy proxies must be
32cb93a386Sopenharmony_ci    // created with positive widths and heights. The width and height are set to 0 only after a
33cb93a386Sopenharmony_ci    // failed instantiation. The former must be "approximate" fit while the latter can be either.
34cb93a386Sopenharmony_ci    return ((dimensions.fWidth < 0 && dimensions.fHeight < 0 && SkBackingFit::kApprox == fit) ||
35cb93a386Sopenharmony_ci            (dimensions.fWidth > 0 && dimensions.fHeight > 0));
36cb93a386Sopenharmony_ci}
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_cistatic bool is_valid_non_lazy(SkISize dimensions) {
39cb93a386Sopenharmony_ci    return dimensions.fWidth > 0 && dimensions.fHeight > 0;
40cb93a386Sopenharmony_ci}
41cb93a386Sopenharmony_ci#endif
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_ci// Deferred version
44cb93a386Sopenharmony_ciGrSurfaceProxy::GrSurfaceProxy(const GrBackendFormat& format,
45cb93a386Sopenharmony_ci                               SkISize dimensions,
46cb93a386Sopenharmony_ci                               SkBackingFit fit,
47cb93a386Sopenharmony_ci                               SkBudgeted budgeted,
48cb93a386Sopenharmony_ci                               GrProtected isProtected,
49cb93a386Sopenharmony_ci                               GrInternalSurfaceFlags surfaceFlags,
50cb93a386Sopenharmony_ci                               UseAllocator useAllocator)
51cb93a386Sopenharmony_ci        : fSurfaceFlags(surfaceFlags)
52cb93a386Sopenharmony_ci        , fFormat(format)
53cb93a386Sopenharmony_ci        , fDimensions(dimensions)
54cb93a386Sopenharmony_ci        , fFit(fit)
55cb93a386Sopenharmony_ci        , fBudgeted(budgeted)
56cb93a386Sopenharmony_ci        , fUseAllocator(useAllocator)
57cb93a386Sopenharmony_ci        , fIsProtected(isProtected) {
58cb93a386Sopenharmony_ci    SkASSERT(fFormat.isValid());
59cb93a386Sopenharmony_ci    SkASSERT(is_valid_non_lazy(dimensions));
60cb93a386Sopenharmony_ci}
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci// Lazy-callback version
63cb93a386Sopenharmony_ciGrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback,
64cb93a386Sopenharmony_ci                               const GrBackendFormat& format,
65cb93a386Sopenharmony_ci                               SkISize dimensions,
66cb93a386Sopenharmony_ci                               SkBackingFit fit,
67cb93a386Sopenharmony_ci                               SkBudgeted budgeted,
68cb93a386Sopenharmony_ci                               GrProtected isProtected,
69cb93a386Sopenharmony_ci                               GrInternalSurfaceFlags surfaceFlags,
70cb93a386Sopenharmony_ci                               UseAllocator useAllocator)
71cb93a386Sopenharmony_ci        : fSurfaceFlags(surfaceFlags)
72cb93a386Sopenharmony_ci        , fFormat(format)
73cb93a386Sopenharmony_ci        , fDimensions(dimensions)
74cb93a386Sopenharmony_ci        , fFit(fit)
75cb93a386Sopenharmony_ci        , fBudgeted(budgeted)
76cb93a386Sopenharmony_ci        , fUseAllocator(useAllocator)
77cb93a386Sopenharmony_ci        , fLazyInstantiateCallback(std::move(callback))
78cb93a386Sopenharmony_ci        , fIsProtected(isProtected) {
79cb93a386Sopenharmony_ci    SkASSERT(fFormat.isValid());
80cb93a386Sopenharmony_ci    SkASSERT(fLazyInstantiateCallback);
81cb93a386Sopenharmony_ci    SkASSERT(is_valid_lazy(dimensions, fit));
82cb93a386Sopenharmony_ci}
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_ci// Wrapped version
85cb93a386Sopenharmony_ciGrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface,
86cb93a386Sopenharmony_ci                               SkBackingFit fit,
87cb93a386Sopenharmony_ci                               UseAllocator useAllocator)
88cb93a386Sopenharmony_ci        : fTarget(std::move(surface))
89cb93a386Sopenharmony_ci        , fSurfaceFlags(fTarget->flags())
90cb93a386Sopenharmony_ci        , fFormat(fTarget->backendFormat())
91cb93a386Sopenharmony_ci        , fDimensions(fTarget->dimensions())
92cb93a386Sopenharmony_ci        , fFit(fit)
93cb93a386Sopenharmony_ci        , fBudgeted(fTarget->resourcePriv().budgetedType() == GrBudgetedType::kBudgeted
94cb93a386Sopenharmony_ci                            ? SkBudgeted::kYes
95cb93a386Sopenharmony_ci                            : SkBudgeted::kNo)
96cb93a386Sopenharmony_ci        , fUseAllocator(useAllocator)
97cb93a386Sopenharmony_ci        , fUniqueID(fTarget->uniqueID())  // Note: converting from unique resource ID to a proxy ID!
98cb93a386Sopenharmony_ci        , fIsProtected(fTarget->isProtected() ? GrProtected::kYes : GrProtected::kNo) {
99cb93a386Sopenharmony_ci    SkASSERT(fFormat.isValid());
100cb93a386Sopenharmony_ci}
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_ciGrSurfaceProxy::~GrSurfaceProxy() {
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_cisk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
106cb93a386Sopenharmony_ci                                                   int sampleCnt,
107cb93a386Sopenharmony_ci                                                   GrRenderable renderable,
108cb93a386Sopenharmony_ci                                                   GrMipmapped mipMapped) const {
109cb93a386Sopenharmony_ci    SkASSERT(mipMapped == GrMipmapped::kNo || fFit == SkBackingFit::kExact);
110cb93a386Sopenharmony_ci    SkASSERT(!this->isLazy());
111cb93a386Sopenharmony_ci    SkASSERT(!fTarget);
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    sk_sp<GrSurface> surface;
114cb93a386Sopenharmony_ci    if (SkBackingFit::kApprox == fFit) {
115cb93a386Sopenharmony_ci        surface = resourceProvider->createApproxTexture(fDimensions,
116cb93a386Sopenharmony_ci                                                        fFormat,
117cb93a386Sopenharmony_ci                                                        fFormat.textureType(),
118cb93a386Sopenharmony_ci                                                        renderable,
119cb93a386Sopenharmony_ci                                                        sampleCnt,
120cb93a386Sopenharmony_ci                                                        fIsProtected);
121cb93a386Sopenharmony_ci    } else {
122cb93a386Sopenharmony_ci        surface = resourceProvider->createTexture(fDimensions,
123cb93a386Sopenharmony_ci                                                  fFormat,
124cb93a386Sopenharmony_ci                                                  fFormat.textureType(),
125cb93a386Sopenharmony_ci                                                  renderable,
126cb93a386Sopenharmony_ci                                                  sampleCnt,
127cb93a386Sopenharmony_ci                                                  mipMapped,
128cb93a386Sopenharmony_ci                                                  fBudgeted,
129cb93a386Sopenharmony_ci                                                  fIsProtected);
130cb93a386Sopenharmony_ci    }
131cb93a386Sopenharmony_ci    if (!surface) {
132cb93a386Sopenharmony_ci        return nullptr;
133cb93a386Sopenharmony_ci    }
134cb93a386Sopenharmony_ci
135cb93a386Sopenharmony_ci    if (fGrProxyTag.isGrTagValid()) {
136cb93a386Sopenharmony_ci        surface->setResourceTag(fGrProxyTag);
137cb93a386Sopenharmony_ci    }
138cb93a386Sopenharmony_ci    return surface;
139cb93a386Sopenharmony_ci}
140cb93a386Sopenharmony_ci
141cb93a386Sopenharmony_cibool GrSurfaceProxy::canSkipResourceAllocator() const {
142cb93a386Sopenharmony_ci    if (fUseAllocator == UseAllocator::kNo) {
143cb93a386Sopenharmony_ci        // Usually an atlas or onFlush proxy
144cb93a386Sopenharmony_ci        return true;
145cb93a386Sopenharmony_ci    }
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci    auto peek = this->peekSurface();
148cb93a386Sopenharmony_ci    if (!peek) {
149cb93a386Sopenharmony_ci        return false;
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci    // If this resource is already allocated and not recyclable then the resource allocator does
152cb93a386Sopenharmony_ci    // not need to do anything with it.
153cb93a386Sopenharmony_ci    return !peek->resourcePriv().getScratchKey().isValid();
154cb93a386Sopenharmony_ci}
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_civoid GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
157cb93a386Sopenharmony_ci    SkASSERT(!fTarget && surface);
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validateSurface(surface.get());)
160cb93a386Sopenharmony_ci
161cb93a386Sopenharmony_ci    fTarget = std::move(surface);
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci#ifdef SK_DEBUG
164cb93a386Sopenharmony_ci    if (this->asRenderTargetProxy()) {
165cb93a386Sopenharmony_ci        SkASSERT(fTarget->asRenderTarget());
166cb93a386Sopenharmony_ci    }
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci    // In order to give DDL users some flexibility in the destination of there DDLs,
169cb93a386Sopenharmony_ci    // a DDL's target proxy can be more conservative (and thus require less memory)
170cb93a386Sopenharmony_ci    // than the actual GrSurface used to fulfill it.
171cb93a386Sopenharmony_ci    if (!this->isDDLTarget() && kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
172cb93a386Sopenharmony_ci        // TODO(11373): Can this check be exact?
173cb93a386Sopenharmony_ci        SkASSERT(fTarget->gpuMemorySize() <= this->getRawGpuMemorySize_debugOnly());
174cb93a386Sopenharmony_ci    }
175cb93a386Sopenharmony_ci#endif
176cb93a386Sopenharmony_ci}
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_cibool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
179cb93a386Sopenharmony_ci                                     GrRenderable renderable, GrMipmapped mipMapped,
180cb93a386Sopenharmony_ci                                     const GrUniqueKey* uniqueKey) {
181cb93a386Sopenharmony_ci    SkASSERT(!this->isLazy());
182cb93a386Sopenharmony_ci    if (fTarget) {
183cb93a386Sopenharmony_ci        if (uniqueKey && uniqueKey->isValid()) {
184cb93a386Sopenharmony_ci            SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
185cb93a386Sopenharmony_ci        }
186cb93a386Sopenharmony_ci        return true;
187cb93a386Sopenharmony_ci    }
188cb93a386Sopenharmony_ci
189cb93a386Sopenharmony_ci    sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, renderable,
190cb93a386Sopenharmony_ci                                                       mipMapped);
191cb93a386Sopenharmony_ci    if (!surface) {
192cb93a386Sopenharmony_ci        return false;
193cb93a386Sopenharmony_ci    }
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_ci    // If there was an invalidation message pending for this key, we might have just processed it,
196cb93a386Sopenharmony_ci    // causing the key (stored on this proxy) to become invalid.
197cb93a386Sopenharmony_ci    if (uniqueKey && uniqueKey->isValid()) {
198cb93a386Sopenharmony_ci        resourceProvider->assignUniqueKeyToResource(*uniqueKey, surface.get());
199cb93a386Sopenharmony_ci    }
200cb93a386Sopenharmony_ci
201cb93a386Sopenharmony_ci    this->assign(std::move(surface));
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_ci    return true;
204cb93a386Sopenharmony_ci}
205cb93a386Sopenharmony_ci
206cb93a386Sopenharmony_civoid GrSurfaceProxy::deinstantiate() {
207cb93a386Sopenharmony_ci    SkASSERT(this->isInstantiated());
208cb93a386Sopenharmony_ci    fTarget = nullptr;
209cb93a386Sopenharmony_ci}
210cb93a386Sopenharmony_ci
211cb93a386Sopenharmony_civoid GrSurfaceProxy::computeScratchKey(const GrCaps& caps, GrScratchKey* key) const {
212cb93a386Sopenharmony_ci    SkASSERT(!this->isFullyLazy());
213cb93a386Sopenharmony_ci    GrRenderable renderable = GrRenderable::kNo;
214cb93a386Sopenharmony_ci    int sampleCount = 1;
215cb93a386Sopenharmony_ci    if (const auto* rtp = this->asRenderTargetProxy()) {
216cb93a386Sopenharmony_ci        renderable = GrRenderable::kYes;
217cb93a386Sopenharmony_ci        sampleCount = rtp->numSamples();
218cb93a386Sopenharmony_ci    }
219cb93a386Sopenharmony_ci
220cb93a386Sopenharmony_ci    const GrTextureProxy* tp = this->asTextureProxy();
221cb93a386Sopenharmony_ci    GrMipmapped mipMapped = GrMipmapped::kNo;
222cb93a386Sopenharmony_ci    if (tp) {
223cb93a386Sopenharmony_ci        mipMapped = tp->mipmapped();
224cb93a386Sopenharmony_ci    }
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ci    GrTexture::ComputeScratchKey(caps, this->backendFormat(), this->backingStoreDimensions(),
227cb93a386Sopenharmony_ci                                 renderable, sampleCount, mipMapped, fIsProtected, key);
228cb93a386Sopenharmony_ci}
229cb93a386Sopenharmony_ci
230cb93a386Sopenharmony_ciSkISize GrSurfaceProxy::backingStoreDimensions() const {
231cb93a386Sopenharmony_ci    SkASSERT(!this->isFullyLazy());
232cb93a386Sopenharmony_ci    if (fTarget) {
233cb93a386Sopenharmony_ci        return fTarget->dimensions();
234cb93a386Sopenharmony_ci    }
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_ci    if (SkBackingFit::kExact == fFit) {
237cb93a386Sopenharmony_ci        return fDimensions;
238cb93a386Sopenharmony_ci    }
239cb93a386Sopenharmony_ci    return GrResourceProvider::MakeApprox(fDimensions);
240cb93a386Sopenharmony_ci}
241cb93a386Sopenharmony_ci
242cb93a386Sopenharmony_cibool GrSurfaceProxy::isFunctionallyExact() const {
243cb93a386Sopenharmony_ci    SkASSERT(!this->isFullyLazy());
244cb93a386Sopenharmony_ci    return fFit == SkBackingFit::kExact ||
245cb93a386Sopenharmony_ci           fDimensions == GrResourceProvider::MakeApprox(fDimensions);
246cb93a386Sopenharmony_ci}
247cb93a386Sopenharmony_ci
248cb93a386Sopenharmony_cibool GrSurfaceProxy::isFormatCompressed(const GrCaps* caps) const {
249cb93a386Sopenharmony_ci    return caps->isFormatCompressed(this->backendFormat());
250cb93a386Sopenharmony_ci}
251cb93a386Sopenharmony_ci
252cb93a386Sopenharmony_ci#ifdef SK_DEBUG
253cb93a386Sopenharmony_civoid GrSurfaceProxy::validate(GrContext_Base* context) const {
254cb93a386Sopenharmony_ci    if (fTarget) {
255cb93a386Sopenharmony_ci        SkASSERT(fTarget->getContext()->priv().matches(context));
256cb93a386Sopenharmony_ci    }
257cb93a386Sopenharmony_ci}
258cb93a386Sopenharmony_ci#endif
259cb93a386Sopenharmony_ci
260cb93a386Sopenharmony_cisk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* rContext,
261cb93a386Sopenharmony_ci                                           sk_sp<GrSurfaceProxy> src,
262cb93a386Sopenharmony_ci                                           GrSurfaceOrigin origin,
263cb93a386Sopenharmony_ci                                           GrMipmapped mipMapped,
264cb93a386Sopenharmony_ci                                           SkIRect srcRect,
265cb93a386Sopenharmony_ci                                           SkBackingFit fit,
266cb93a386Sopenharmony_ci                                           SkBudgeted budgeted,
267cb93a386Sopenharmony_ci                                           RectsMustMatch rectsMustMatch,
268cb93a386Sopenharmony_ci                                           sk_sp<GrRenderTask>* outTask) {
269cb93a386Sopenharmony_ci    SkASSERT(!src->isFullyLazy());
270cb93a386Sopenharmony_ci    int width;
271cb93a386Sopenharmony_ci    int height;
272cb93a386Sopenharmony_ci
273cb93a386Sopenharmony_ci    SkIPoint dstPoint;
274cb93a386Sopenharmony_ci    if (rectsMustMatch == RectsMustMatch::kYes) {
275cb93a386Sopenharmony_ci        width = src->width();
276cb93a386Sopenharmony_ci        height = src->height();
277cb93a386Sopenharmony_ci        dstPoint = {srcRect.fLeft, srcRect.fTop};
278cb93a386Sopenharmony_ci    } else {
279cb93a386Sopenharmony_ci        width = srcRect.width();
280cb93a386Sopenharmony_ci        height = srcRect.height();
281cb93a386Sopenharmony_ci        dstPoint = {0, 0};
282cb93a386Sopenharmony_ci    }
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci    if (!srcRect.intersect(SkIRect::MakeSize(src->dimensions()))) {
285cb93a386Sopenharmony_ci        return {};
286cb93a386Sopenharmony_ci    }
287cb93a386Sopenharmony_ci    auto format = src->backendFormat().makeTexture2D();
288cb93a386Sopenharmony_ci    SkASSERT(format.isValid());
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci    if (src->backendFormat().textureType() != GrTextureType::kExternal) {
291cb93a386Sopenharmony_ci        GrImageInfo info(GrColorType::kUnknown, kUnknown_SkAlphaType, nullptr, {width, height});
292cb93a386Sopenharmony_ci        auto dstContext = rContext->priv().makeSC(info,
293cb93a386Sopenharmony_ci                                                  format,
294cb93a386Sopenharmony_ci                                                  fit,
295cb93a386Sopenharmony_ci                                                  origin,
296cb93a386Sopenharmony_ci                                                  GrRenderable::kNo,
297cb93a386Sopenharmony_ci                                                  1,
298cb93a386Sopenharmony_ci                                                  mipMapped,
299cb93a386Sopenharmony_ci                                                  src->isProtected(),
300cb93a386Sopenharmony_ci                                                  budgeted);
301cb93a386Sopenharmony_ci        sk_sp<GrRenderTask> copyTask;
302cb93a386Sopenharmony_ci        if (dstContext && (copyTask = dstContext->copy(src, srcRect, dstPoint))) {
303cb93a386Sopenharmony_ci            if (outTask) {
304cb93a386Sopenharmony_ci                *outTask = std::move(copyTask);
305cb93a386Sopenharmony_ci            }
306cb93a386Sopenharmony_ci            return dstContext->asSurfaceProxyRef();
307cb93a386Sopenharmony_ci        }
308cb93a386Sopenharmony_ci    }
309cb93a386Sopenharmony_ci    if (src->asTextureProxy()) {
310cb93a386Sopenharmony_ci        auto dstContext = rContext->priv().makeSFC(kUnknown_SkAlphaType,
311cb93a386Sopenharmony_ci                                                   nullptr,
312cb93a386Sopenharmony_ci                                                   {width, height},
313cb93a386Sopenharmony_ci                                                   fit,
314cb93a386Sopenharmony_ci                                                   format,
315cb93a386Sopenharmony_ci                                                   1,
316cb93a386Sopenharmony_ci                                                   mipMapped,
317cb93a386Sopenharmony_ci                                                   src->isProtected(),
318cb93a386Sopenharmony_ci                                                   GrSwizzle::RGBA(),
319cb93a386Sopenharmony_ci                                                   GrSwizzle::RGBA(),
320cb93a386Sopenharmony_ci                                                   origin,
321cb93a386Sopenharmony_ci                                                   budgeted);
322cb93a386Sopenharmony_ci        GrSurfaceProxyView view(std::move(src), origin, GrSwizzle::RGBA());
323cb93a386Sopenharmony_ci        if (dstContext && dstContext->blitTexture(std::move(view), srcRect, dstPoint)) {
324cb93a386Sopenharmony_ci            if (outTask) {
325cb93a386Sopenharmony_ci                *outTask = dstContext->refRenderTask();
326cb93a386Sopenharmony_ci            }
327cb93a386Sopenharmony_ci            return dstContext->asSurfaceProxyRef();
328cb93a386Sopenharmony_ci        }
329cb93a386Sopenharmony_ci    }
330cb93a386Sopenharmony_ci    // Can't use backend copies or draws.
331cb93a386Sopenharmony_ci    return nullptr;
332cb93a386Sopenharmony_ci}
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_cisk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrRecordingContext* context,
335cb93a386Sopenharmony_ci                                           sk_sp<GrSurfaceProxy> src,
336cb93a386Sopenharmony_ci                                           GrSurfaceOrigin origin,
337cb93a386Sopenharmony_ci                                           GrMipmapped mipMapped,
338cb93a386Sopenharmony_ci                                           SkBackingFit fit,
339cb93a386Sopenharmony_ci                                           SkBudgeted budgeted,
340cb93a386Sopenharmony_ci                                           sk_sp<GrRenderTask>* outTask) {
341cb93a386Sopenharmony_ci    SkASSERT(!src->isFullyLazy());
342cb93a386Sopenharmony_ci    auto rect = SkIRect::MakeSize(src->dimensions());
343cb93a386Sopenharmony_ci    return Copy(context,
344cb93a386Sopenharmony_ci                std::move(src),
345cb93a386Sopenharmony_ci                origin,
346cb93a386Sopenharmony_ci                mipMapped,
347cb93a386Sopenharmony_ci                rect,
348cb93a386Sopenharmony_ci                fit,
349cb93a386Sopenharmony_ci                budgeted,
350cb93a386Sopenharmony_ci                RectsMustMatch::kNo,
351cb93a386Sopenharmony_ci                outTask);
352cb93a386Sopenharmony_ci}
353cb93a386Sopenharmony_ci
354cb93a386Sopenharmony_ci#if GR_TEST_UTILS
355cb93a386Sopenharmony_ciint32_t GrSurfaceProxy::testingOnly_getBackingRefCnt() const {
356cb93a386Sopenharmony_ci    if (fTarget) {
357cb93a386Sopenharmony_ci        return fTarget->testingOnly_getRefCnt();
358cb93a386Sopenharmony_ci    }
359cb93a386Sopenharmony_ci
360cb93a386Sopenharmony_ci    return -1; // no backing GrSurface
361cb93a386Sopenharmony_ci}
362cb93a386Sopenharmony_ci
363cb93a386Sopenharmony_ciGrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
364cb93a386Sopenharmony_ci    return fSurfaceFlags;
365cb93a386Sopenharmony_ci}
366cb93a386Sopenharmony_ci
367cb93a386Sopenharmony_ciSkString GrSurfaceProxy::dump() const {
368cb93a386Sopenharmony_ci    SkString tmp;
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ci    tmp.appendf("proxyID: %d - surfaceID: %d",
371cb93a386Sopenharmony_ci                this->uniqueID().asUInt(),
372cb93a386Sopenharmony_ci                this->peekSurface() ? this->peekSurface()->uniqueID().asUInt()
373cb93a386Sopenharmony_ci                                    : -1);
374cb93a386Sopenharmony_ci    return tmp;
375cb93a386Sopenharmony_ci}
376cb93a386Sopenharmony_ci
377cb93a386Sopenharmony_ci#endif
378cb93a386Sopenharmony_ci
379cb93a386Sopenharmony_civoid GrSurfaceProxyPriv::exactify(bool allocatedCaseOnly) {
380cb93a386Sopenharmony_ci    SkASSERT(!fProxy->isFullyLazy());
381cb93a386Sopenharmony_ci    if (this->isExact()) {
382cb93a386Sopenharmony_ci        return;
383cb93a386Sopenharmony_ci    }
384cb93a386Sopenharmony_ci
385cb93a386Sopenharmony_ci    SkASSERT(SkBackingFit::kApprox == fProxy->fFit);
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_ci    if (fProxy->fTarget) {
388cb93a386Sopenharmony_ci        // The kApprox but already instantiated case. Setting the proxy's width & height to
389cb93a386Sopenharmony_ci        // the instantiated width & height could have side-effects going forward, since we're
390cb93a386Sopenharmony_ci        // obliterating the area of interest information. This call (exactify) only used
391cb93a386Sopenharmony_ci        // when converting an SkSpecialImage to an SkImage so the proxy shouldn't be
392cb93a386Sopenharmony_ci        // used for additional draws.
393cb93a386Sopenharmony_ci        fProxy->fDimensions = fProxy->fTarget->dimensions();
394cb93a386Sopenharmony_ci        return;
395cb93a386Sopenharmony_ci    }
396cb93a386Sopenharmony_ci
397cb93a386Sopenharmony_ci#ifndef SK_CRIPPLE_TEXTURE_REUSE
398cb93a386Sopenharmony_ci    // In the post-implicit-allocation world we can't convert this proxy to be exact fit
399cb93a386Sopenharmony_ci    // at this point. With explicit allocation switching this to exact will result in a
400cb93a386Sopenharmony_ci    // different allocation at flush time. With implicit allocation, allocation would occur
401cb93a386Sopenharmony_ci    // at draw time (rather than flush time) so this pathway was encountered less often (if
402cb93a386Sopenharmony_ci    // at all).
403cb93a386Sopenharmony_ci    if (allocatedCaseOnly) {
404cb93a386Sopenharmony_ci        return;
405cb93a386Sopenharmony_ci    }
406cb93a386Sopenharmony_ci#endif
407cb93a386Sopenharmony_ci
408cb93a386Sopenharmony_ci    // The kApprox uninstantiated case. Making this proxy be exact should be okay.
409cb93a386Sopenharmony_ci    // It could mess things up if prior decisions were based on the approximate size.
410cb93a386Sopenharmony_ci    fProxy->fFit = SkBackingFit::kExact;
411cb93a386Sopenharmony_ci    // If fGpuMemorySize is used when caching specialImages for the image filter DAG. If it has
412cb93a386Sopenharmony_ci    // already been computed we want to leave it alone so that amount will be removed when
413cb93a386Sopenharmony_ci    // the special image goes away. If it hasn't been computed yet it might as well compute the
414cb93a386Sopenharmony_ci    // exact amount.
415cb93a386Sopenharmony_ci}
416cb93a386Sopenharmony_ci
417cb93a386Sopenharmony_cibool GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
418cb93a386Sopenharmony_ci    SkASSERT(fProxy->isLazy());
419cb93a386Sopenharmony_ci
420cb93a386Sopenharmony_ci    sk_sp<GrSurface> surface;
421cb93a386Sopenharmony_ci    if (const auto& uniqueKey = fProxy->getUniqueKey(); uniqueKey.isValid()) {
422cb93a386Sopenharmony_ci        // First try to reattach to a cached version if the proxy is uniquely keyed
423cb93a386Sopenharmony_ci        surface = resourceProvider->findByUniqueKey<GrSurface>(uniqueKey);
424cb93a386Sopenharmony_ci    }
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_ci    bool syncKey = true;
427cb93a386Sopenharmony_ci    bool releaseCallback = false;
428cb93a386Sopenharmony_ci    if (!surface) {
429cb93a386Sopenharmony_ci        auto result = fProxy->fLazyInstantiateCallback(resourceProvider, fProxy->callbackDesc());
430cb93a386Sopenharmony_ci        surface = std::move(result.fSurface);
431cb93a386Sopenharmony_ci        syncKey = result.fKeyMode == GrSurfaceProxy::LazyInstantiationKeyMode::kSynced;
432cb93a386Sopenharmony_ci        releaseCallback = surface && result.fReleaseCallback;
433cb93a386Sopenharmony_ci    }
434cb93a386Sopenharmony_ci    if (!surface) {
435cb93a386Sopenharmony_ci        fProxy->fDimensions.setEmpty();
436cb93a386Sopenharmony_ci        return false;
437cb93a386Sopenharmony_ci    }
438cb93a386Sopenharmony_ci
439cb93a386Sopenharmony_ci    if (fProxy->isFullyLazy()) {
440cb93a386Sopenharmony_ci        // This was a fully lazy proxy. We need to fill in the width & height. For partially
441cb93a386Sopenharmony_ci        // lazy proxies we must preserve the original width & height since that indicates
442cb93a386Sopenharmony_ci        // the content area.
443cb93a386Sopenharmony_ci        fProxy->fDimensions = surface->dimensions();
444cb93a386Sopenharmony_ci    }
445cb93a386Sopenharmony_ci
446cb93a386Sopenharmony_ci    SkASSERT(fProxy->width() <= surface->width());
447cb93a386Sopenharmony_ci    SkASSERT(fProxy->height() <= surface->height());
448cb93a386Sopenharmony_ci
449cb93a386Sopenharmony_ci    if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
450cb93a386Sopenharmony_ci        texProxy->setTargetKeySync(syncKey);
451cb93a386Sopenharmony_ci        if (syncKey) {
452cb93a386Sopenharmony_ci            const GrUniqueKey& key = texProxy->getUniqueKey();
453cb93a386Sopenharmony_ci            if (key.isValid()) {
454cb93a386Sopenharmony_ci                if (!surface->asTexture()->getUniqueKey().isValid()) {
455cb93a386Sopenharmony_ci                    // If 'surface' is newly created, attach the unique key
456cb93a386Sopenharmony_ci                    resourceProvider->assignUniqueKeyToResource(key, surface.get());
457cb93a386Sopenharmony_ci                } else {
458cb93a386Sopenharmony_ci                    // otherwise we had better have reattached to a cached version
459cb93a386Sopenharmony_ci                    SkASSERT(surface->asTexture()->getUniqueKey() == key);
460cb93a386Sopenharmony_ci                }
461cb93a386Sopenharmony_ci            } else {
462cb93a386Sopenharmony_ci                SkASSERT(!surface->getUniqueKey().isValid());
463cb93a386Sopenharmony_ci            }
464cb93a386Sopenharmony_ci        }
465cb93a386Sopenharmony_ci    }
466cb93a386Sopenharmony_ci
467cb93a386Sopenharmony_ci    this->assign(std::move(surface));
468cb93a386Sopenharmony_ci    if (releaseCallback) {
469cb93a386Sopenharmony_ci        fProxy->fLazyInstantiateCallback = nullptr;
470cb93a386Sopenharmony_ci    }
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_ci    return true;
473cb93a386Sopenharmony_ci}
474cb93a386Sopenharmony_ci
475cb93a386Sopenharmony_ci#ifdef SK_DEBUG
476cb93a386Sopenharmony_civoid GrSurfaceProxy::validateSurface(const GrSurface* surface) {
477cb93a386Sopenharmony_ci    SkASSERTF(surface->backendFormat() == fFormat, "%s != %s",
478cb93a386Sopenharmony_ci              surface->backendFormat().toStr().c_str(), fFormat.toStr().c_str());
479cb93a386Sopenharmony_ci
480cb93a386Sopenharmony_ci    this->onValidateSurface(surface);
481cb93a386Sopenharmony_ci}
482cb93a386Sopenharmony_ci#endif
483