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/GrTextureRenderTargetProxy.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "src/gpu/GrCaps.h"
11cb93a386Sopenharmony_ci#include "src/gpu/GrRenderTarget.h"
12cb93a386Sopenharmony_ci#include "src/gpu/GrSurface.h"
13cb93a386Sopenharmony_ci#include "src/gpu/GrSurfaceProxyPriv.h"
14cb93a386Sopenharmony_ci#include "src/gpu/GrTexture.h"
15cb93a386Sopenharmony_ci#include "src/gpu/GrTextureProxyPriv.h"
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_ci#ifdef SK_DEBUG
18cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h"
19cb93a386Sopenharmony_ci#include "src/gpu/GrDirectContextPriv.h"
20cb93a386Sopenharmony_ci#endif
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ci// Deferred version
23cb93a386Sopenharmony_ci// This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and
24cb93a386Sopenharmony_ci// GrRenderTargetProxy) so its constructor must be explicitly called.
25cb93a386Sopenharmony_ciGrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
26cb93a386Sopenharmony_ci                                                       const GrBackendFormat& format,
27cb93a386Sopenharmony_ci                                                       SkISize dimensions,
28cb93a386Sopenharmony_ci                                                       int sampleCnt,
29cb93a386Sopenharmony_ci                                                       GrMipmapped mipMapped,
30cb93a386Sopenharmony_ci                                                       GrMipmapStatus mipmapStatus,
31cb93a386Sopenharmony_ci                                                       SkBackingFit fit,
32cb93a386Sopenharmony_ci                                                       SkBudgeted budgeted,
33cb93a386Sopenharmony_ci                                                       GrProtected isProtected,
34cb93a386Sopenharmony_ci                                                       GrInternalSurfaceFlags surfaceFlags,
35cb93a386Sopenharmony_ci                                                       UseAllocator useAllocator,
36cb93a386Sopenharmony_ci                                                       GrDDLProvider creatingProvider)
37cb93a386Sopenharmony_ci        : GrSurfaceProxy(format, dimensions, fit, budgeted, isProtected, surfaceFlags, useAllocator)
38cb93a386Sopenharmony_ci        // for now textures w/ data are always wrapped
39cb93a386Sopenharmony_ci        , GrRenderTargetProxy(caps, format, dimensions, sampleCnt, fit, budgeted, isProtected,
40cb93a386Sopenharmony_ci                              surfaceFlags, useAllocator)
41cb93a386Sopenharmony_ci        , GrTextureProxy(format, dimensions, mipMapped, mipmapStatus, fit, budgeted, isProtected,
42cb93a386Sopenharmony_ci                         surfaceFlags, useAllocator, creatingProvider) {
43cb93a386Sopenharmony_ci    this->initSurfaceFlags(caps);
44cb93a386Sopenharmony_ci}
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci// Lazy-callback version
47cb93a386Sopenharmony_ciGrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
48cb93a386Sopenharmony_ci                                                       LazyInstantiateCallback&& callback,
49cb93a386Sopenharmony_ci                                                       const GrBackendFormat& format,
50cb93a386Sopenharmony_ci                                                       SkISize dimensions,
51cb93a386Sopenharmony_ci                                                       int sampleCnt,
52cb93a386Sopenharmony_ci                                                       GrMipmapped mipMapped,
53cb93a386Sopenharmony_ci                                                       GrMipmapStatus mipmapStatus,
54cb93a386Sopenharmony_ci                                                       SkBackingFit fit,
55cb93a386Sopenharmony_ci                                                       SkBudgeted budgeted,
56cb93a386Sopenharmony_ci                                                       GrProtected isProtected,
57cb93a386Sopenharmony_ci                                                       GrInternalSurfaceFlags surfaceFlags,
58cb93a386Sopenharmony_ci                                                       UseAllocator useAllocator,
59cb93a386Sopenharmony_ci                                                       GrDDLProvider creatingProvider)
60cb93a386Sopenharmony_ci        : GrSurfaceProxy(std::move(callback), format, dimensions, fit, budgeted, isProtected,
61cb93a386Sopenharmony_ci                         surfaceFlags, useAllocator)
62cb93a386Sopenharmony_ci        // Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null
63cb93a386Sopenharmony_ci        // callbacks to the texture and RT proxies simply to route to the appropriate constructors.
64cb93a386Sopenharmony_ci        , GrRenderTargetProxy(LazyInstantiateCallback(), format, dimensions, sampleCnt, fit,
65cb93a386Sopenharmony_ci                              budgeted, isProtected, surfaceFlags, useAllocator,
66cb93a386Sopenharmony_ci                              WrapsVkSecondaryCB::kNo)
67cb93a386Sopenharmony_ci        , GrTextureProxy(LazyInstantiateCallback(), format, dimensions, mipMapped, mipmapStatus,
68cb93a386Sopenharmony_ci                         fit, budgeted, isProtected, surfaceFlags, useAllocator,
69cb93a386Sopenharmony_ci                         creatingProvider) {
70cb93a386Sopenharmony_ci    this->initSurfaceFlags(caps);
71cb93a386Sopenharmony_ci}
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci// Wrapped version
74cb93a386Sopenharmony_ci// This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and
75cb93a386Sopenharmony_ci// GrRenderTargetProxy) so its constructor must be explicitly called.
76cb93a386Sopenharmony_ciGrTextureRenderTargetProxy::GrTextureRenderTargetProxy(sk_sp<GrSurface> surf,
77cb93a386Sopenharmony_ci                                                       UseAllocator useAllocator,
78cb93a386Sopenharmony_ci                                                       GrDDLProvider creatingProvider)
79cb93a386Sopenharmony_ci        : GrSurfaceProxy(surf, SkBackingFit::kExact, useAllocator)
80cb93a386Sopenharmony_ci        , GrRenderTargetProxy(surf, useAllocator)
81cb93a386Sopenharmony_ci        , GrTextureProxy(surf, useAllocator, creatingProvider) {
82cb93a386Sopenharmony_ci    SkASSERT(surf->asTexture());
83cb93a386Sopenharmony_ci    SkASSERT(surf->asRenderTarget());
84cb93a386Sopenharmony_ci    SkASSERT(fSurfaceFlags == fTarget->flags());
85cb93a386Sopenharmony_ci    SkASSERT((this->numSamples() <= 1 ||
86cb93a386Sopenharmony_ci              fTarget->getContext()->priv().caps()->msaaResolvesAutomatically()) !=
87cb93a386Sopenharmony_ci             this->requiresManualMSAAResolve());
88cb93a386Sopenharmony_ci}
89cb93a386Sopenharmony_ci
90cb93a386Sopenharmony_civoid GrTextureRenderTargetProxy::initSurfaceFlags(const GrCaps& caps) {
91cb93a386Sopenharmony_ci    // FBO 0 should never be wrapped as a texture render target.
92cb93a386Sopenharmony_ci    SkASSERT(!this->glRTFBOIDIs0());
93cb93a386Sopenharmony_ci    if (this->numSamples() > 1 && !caps.msaaResolvesAutomatically())  {
94cb93a386Sopenharmony_ci        // MSAA texture-render-targets always require manual resolve if we are not using a
95cb93a386Sopenharmony_ci        // multisampled-render-to-texture extension.
96cb93a386Sopenharmony_ci        //
97cb93a386Sopenharmony_ci        // NOTE: This is the only instance where we need to set the manual resolve flag on a proxy.
98cb93a386Sopenharmony_ci        // Any other proxies that require manual resolve (e.g., wrapRenderableBackendTexture() with
99cb93a386Sopenharmony_ci        // a sample count)  will be wrapped, and the wrapped version of the GrSurface constructor
100cb93a386Sopenharmony_ci        // will automatically get the manual resolve flag when copying the target GrSurface's flags.
101cb93a386Sopenharmony_ci        fSurfaceFlags |= GrInternalSurfaceFlags::kRequiresManualMSAAResolve;
102cb93a386Sopenharmony_ci    }
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_cisize_t GrTextureRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
106cb93a386Sopenharmony_ci    int colorSamplesPerPixel = this->numSamples();
107cb93a386Sopenharmony_ci    if (colorSamplesPerPixel > 1) {
108cb93a386Sopenharmony_ci        // Add one to account for the resolve buffer.
109cb93a386Sopenharmony_ci        ++colorSamplesPerPixel;
110cb93a386Sopenharmony_ci    }
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    // TODO: do we have enough information to improve this worst case estimate?
113cb93a386Sopenharmony_ci    return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
114cb93a386Sopenharmony_ci                                  colorSamplesPerPixel, this->proxyMipmapped(),
115cb93a386Sopenharmony_ci                                  !this->priv().isExact());
116cb93a386Sopenharmony_ci}
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_cibool GrTextureRenderTargetProxy::instantiate(GrResourceProvider* resourceProvider) {
119cb93a386Sopenharmony_ci    if (this->isLazy()) {
120cb93a386Sopenharmony_ci        return false;
121cb93a386Sopenharmony_ci    }
122cb93a386Sopenharmony_ci
123cb93a386Sopenharmony_ci    const GrUniqueKey& key = this->getUniqueKey();
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci    if (!this->instantiateImpl(resourceProvider, this->numSamples(), GrRenderable::kYes,
126cb93a386Sopenharmony_ci                               this->mipmapped(), key.isValid() ? &key : nullptr)) {
127cb93a386Sopenharmony_ci        return false;
128cb93a386Sopenharmony_ci    }
129cb93a386Sopenharmony_ci    if (key.isValid()) {
130cb93a386Sopenharmony_ci        SkASSERT(key == this->getUniqueKey());
131cb93a386Sopenharmony_ci    }
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    SkASSERT(this->peekRenderTarget());
134cb93a386Sopenharmony_ci    SkASSERT(this->peekTexture());
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci    return true;
137cb93a386Sopenharmony_ci}
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_cisk_sp<GrSurface> GrTextureRenderTargetProxy::createSurface(
140cb93a386Sopenharmony_ci                                                    GrResourceProvider* resourceProvider) const {
141cb93a386Sopenharmony_ci    sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, this->numSamples(),
142cb93a386Sopenharmony_ci                                                       GrRenderable::kYes, this->mipmapped());
143cb93a386Sopenharmony_ci    if (!surface) {
144cb93a386Sopenharmony_ci        return nullptr;
145cb93a386Sopenharmony_ci    }
146cb93a386Sopenharmony_ci    SkASSERT(surface->asRenderTarget());
147cb93a386Sopenharmony_ci    SkASSERT(surface->asTexture());
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci    return surface;
150cb93a386Sopenharmony_ci}
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ciGrSurfaceProxy::LazySurfaceDesc GrTextureRenderTargetProxy::callbackDesc() const {
153cb93a386Sopenharmony_ci    SkISize dims;
154cb93a386Sopenharmony_ci    SkBackingFit fit;
155cb93a386Sopenharmony_ci    if (this->isFullyLazy()) {
156cb93a386Sopenharmony_ci        fit = SkBackingFit::kApprox;
157cb93a386Sopenharmony_ci        dims = {-1, -1};
158cb93a386Sopenharmony_ci    } else {
159cb93a386Sopenharmony_ci        fit = this->isFunctionallyExact() ? SkBackingFit::kExact : SkBackingFit::kApprox;
160cb93a386Sopenharmony_ci        dims = this->dimensions();
161cb93a386Sopenharmony_ci    }
162cb93a386Sopenharmony_ci    return {
163cb93a386Sopenharmony_ci            dims,
164cb93a386Sopenharmony_ci            fit,
165cb93a386Sopenharmony_ci            GrRenderable::kYes,
166cb93a386Sopenharmony_ci            this->mipmapped(),
167cb93a386Sopenharmony_ci            this->numSamples(),
168cb93a386Sopenharmony_ci            this->backendFormat(),
169cb93a386Sopenharmony_ci            this->textureType(),
170cb93a386Sopenharmony_ci            this->isProtected(),
171cb93a386Sopenharmony_ci            this->isBudgeted(),
172cb93a386Sopenharmony_ci    };
173cb93a386Sopenharmony_ci}
174cb93a386Sopenharmony_ci
175cb93a386Sopenharmony_ci#ifdef SK_DEBUG
176cb93a386Sopenharmony_civoid GrTextureRenderTargetProxy::onValidateSurface(const GrSurface* surface) {
177cb93a386Sopenharmony_ci    // Anything checked here should also be checking the GrTextureProxy version
178cb93a386Sopenharmony_ci    SkASSERT(surface->asTexture());
179cb93a386Sopenharmony_ci    SkASSERT(GrMipmapped::kNo == this->proxyMipmapped() ||
180cb93a386Sopenharmony_ci             GrMipmapped::kYes == surface->asTexture()->mipmapped());
181cb93a386Sopenharmony_ci
182cb93a386Sopenharmony_ci    // Anything checked here should also be checking the GrRenderTargetProxy version
183cb93a386Sopenharmony_ci    SkASSERT(surface->asRenderTarget());
184cb93a386Sopenharmony_ci    SkASSERT(surface->asRenderTarget()->numSamples() == this->numSamples());
185cb93a386Sopenharmony_ci
186cb93a386Sopenharmony_ci    SkASSERT(surface->asTexture()->textureType() == this->textureType());
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci    GrInternalSurfaceFlags proxyFlags = fSurfaceFlags;
189cb93a386Sopenharmony_ci    GrInternalSurfaceFlags surfaceFlags = surface->flags();
190cb93a386Sopenharmony_ci
191cb93a386Sopenharmony_ci    // Only non-RT textures can be read only.
192cb93a386Sopenharmony_ci    SkASSERT(!(proxyFlags & GrInternalSurfaceFlags::kReadOnly));
193cb93a386Sopenharmony_ci    SkASSERT(!(surfaceFlags & GrInternalSurfaceFlags::kReadOnly));
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_ci    SkASSERT(((int)proxyFlags & kGrInternalTextureRenderTargetFlagsMask) ==
196cb93a386Sopenharmony_ci             ((int)surfaceFlags & kGrInternalTextureRenderTargetFlagsMask));
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci    // We manually check the kVkRTSupportsInputAttachment since we only require it on the surface if
199cb93a386Sopenharmony_ci    // the proxy has it set. If the proxy doesn't have the flag it is legal for the surface to
200cb93a386Sopenharmony_ci    // have the flag.
201cb93a386Sopenharmony_ci    if (proxyFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment) {
202cb93a386Sopenharmony_ci        SkASSERT(surfaceFlags & GrInternalSurfaceFlags::kVkRTSupportsInputAttachment);
203cb93a386Sopenharmony_ci    }
204cb93a386Sopenharmony_ci}
205cb93a386Sopenharmony_ci#endif
206cb93a386Sopenharmony_ci
207