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