diff --git a/include/gpu/GrBackendSurface.h b/include/gpu/GrBackendSurface.h index 1254f88d7c..85313404d1 100644 --- a/include/gpu/GrBackendSurface.h +++ b/include/gpu/GrBackendSurface.h @@ -49,6 +49,7 @@ public: GrBackendRenderTarget() {} bool isValid() const { return false; } + bool isFramebufferOnly() const { return false; } }; #else @@ -371,6 +372,7 @@ public: int sampleCnt() const { return fSampleCnt; } int stencilBits() const { return fStencilBits; } GrBackendApi backend() const {return fBackend; } + bool isFramebufferOnly() const { return fFramebufferOnly; } // If the backend API is GL, copies a snapshot of the GrGLFramebufferInfo struct into the passed // in pointer and returns true. Otherwise returns false if the backend API is not GL. @@ -427,6 +429,7 @@ private: void cleanup(); bool fIsValid; + bool fFramebufferOnly = false; int fWidth; //asRenderTarget()); + fSurfaceFlags |= GrInternalSurfaceFlags::kFramebufferOnly; + } + protected: void setGLRTFBOIDIs0() { SkASSERT(!this->requiresManualMSAAResolve()); diff --git a/include/private/GrTypesPriv.h b/include/private/GrTypesPriv.h index 73733e10ea..0e91874c31 100644 --- a/include/private/GrTypesPriv.h +++ b/include/private/GrTypesPriv.h @@ -701,6 +701,10 @@ enum class GrInternalSurfaceFlags { // (asTexture() might or might not return the internal texture, but if it does, we always // resolve the render target before accessing this texture's data.) kRequiresManualMSAAResolve = 1 << 2, + + // This means the pixels in the render target are write-only. This is used for Dawn and Metal + // swap chain targets which can be rendered to, but not read or copied. + kFramebufferOnly = 1 << 3, }; GR_MAKE_BITFIELD_CLASS_OPS(GrInternalSurfaceFlags) diff --git a/src/gpu/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp index 3986afd903..f45b457bd4 100644 --- a/src/gpu/GrBackendSurface.cpp +++ b/src/gpu/GrBackendSurface.cpp @@ -665,6 +665,7 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width, int stencilBits, const GrDawnImageInfo& dawnInfo) : fIsValid(true) + , fFramebufferOnly(true) , fWidth(width) , fHeight(height) , fSampleCnt(sampleCnt) @@ -715,6 +716,7 @@ GrBackendRenderTarget::GrBackendRenderTarget(int width, int sampleCnt, const GrMtlTextureInfo& mtlInfo) : fIsValid(true) + , fFramebufferOnly(false) // TODO: set this from mtlInfo.fTexture->framebufferOnly , fWidth(width) , fHeight(height) , fSampleCnt(SkTMax(1, sampleCnt)) diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 035665112b..3c0e80897c 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -380,7 +380,11 @@ sk_sp GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget return nullptr; } - return this->onWrapBackendRenderTarget(backendRT, colorType); + sk_sp rt = this->onWrapBackendRenderTarget(backendRT, colorType); + if (backendRT.isFramebufferOnly()) { + rt->setFramebufferOnly(); + } + return rt; } sk_sp GrGpu::wrapBackendTextureAsRenderTarget(const GrBackendTexture& backendTex, @@ -432,6 +436,7 @@ bool GrGpu::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); SkASSERT(dst && src); + SkASSERT(!src->framebufferOnly()); if (dst->readOnly()) { return false; @@ -447,6 +452,7 @@ bool GrGpu::readPixels(GrSurface* surface, int left, int top, int width, int hei size_t rowBytes) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); SkASSERT(surface); + SkASSERT(!surface->framebufferOnly()); SkASSERT(this->caps()->isFormatTexturable(surface->backendFormat())); auto subRect = SkIRect::MakeXYWH(left, top, width, height); @@ -480,6 +486,7 @@ bool GrGpu::writePixels(GrSurface* surface, int left, int top, int width, int he const GrMipLevel texels[], int mipLevelCount, bool prepForTexSampling) { TRACE_EVENT0("skia.gpu", TRACE_FUNC); SkASSERT(surface); + SkASSERT(!surface->framebufferOnly()); SkASSERT(this->caps()->isFormatTexturableAndUploadable(surfaceColorType, surface->backendFormat())); diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp index 69d10da6ce..bab4d1db64 100644 --- a/src/gpu/GrRenderTargetContext.cpp +++ b/src/gpu/GrRenderTargetContext.cpp @@ -1688,6 +1688,10 @@ void GrRenderTargetContext::asyncRescaleAndReadPixels( callback(context, nullptr); return; } + if (this->asRenderTargetProxy()->framebufferOnly()) { + callback(context, nullptr); + return; + } auto dstCT = SkColorTypeToGrColorType(info.colorType()); if (dstCT == GrColorType::kUnknown) { callback(context, nullptr); @@ -1933,6 +1937,10 @@ void GrRenderTargetContext::asyncRescaleAndReadPixelsYUV420(SkYUVColorSpace yuvC callback(context, nullptr); return; } + if (this->asRenderTargetProxy()->framebufferOnly()) { + callback(context, nullptr); + return; + } if (this->asSurfaceProxy()->isProtected() == GrProtected::kYes) { callback(context, nullptr); return; diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp index f41d168d26..dc4860b351 100644 --- a/src/gpu/GrSurfaceContext.cpp +++ b/src/gpu/GrSurfaceContext.cpp @@ -157,6 +157,10 @@ bool GrSurfaceContext::readPixels(const GrImageInfo& origDstInfo, void* dst, siz GrSurfaceProxy* srcProxy = this->asSurfaceProxy(); + if (srcProxy->framebufferOnly()) { + return false; + } + // MDB TODO: delay this instantiation until later in the method if (!srcProxy->instantiate(direct->priv().resourceProvider())) { return false; @@ -315,6 +319,11 @@ bool GrSurfaceContext::writePixels(const GrImageInfo& origSrcInfo, const void* s } GrSurfaceProxy* dstProxy = this->asSurfaceProxy(); + + if (dstProxy->framebufferOnly()) { + return false; + } + if (!dstProxy->instantiate(direct->priv().resourceProvider())) { return false; } @@ -484,6 +493,10 @@ bool GrSurfaceContext::copy(GrSurfaceProxy* src, const SkIRect& srcRect, const S SkASSERT(src->textureSwizzle() == this->asSurfaceProxy()->textureSwizzle()); SkASSERT(src->backendFormat() == this->asSurfaceProxy()->backendFormat()); + if (this->asSurfaceProxy()->framebufferOnly()) { + return false; + } + if (!caps->canCopySurface(this->asSurfaceProxy(), src, srcRect, dstPoint)) { return false; } @@ -508,6 +521,10 @@ std::unique_ptr GrSurfaceContext::rescale( return nullptr; } + if (this->asSurfaceProxy()->framebufferOnly()) { + return nullptr; + } + // We rescale by drawing and don't currently support drawing to a kUnpremul destination. if (info.alphaType() == kUnpremul_SkAlphaType) { return nullptr; diff --git a/src/gpu/GrSurfaceProxy.h b/src/gpu/GrSurfaceProxy.h index 79ac4b4d93..f9f2197ffa 100644 --- a/src/gpu/GrSurfaceProxy.h +++ b/src/gpu/GrSurfaceProxy.h @@ -245,6 +245,9 @@ public: * assignment in GrResourceAllocator. */ bool readOnly() const { return fSurfaceFlags & GrInternalSurfaceFlags::kReadOnly; } + bool framebufferOnly() const { + return fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly; + } /** * This means surface is a multisampled render target, and internally holds a non-msaa texture diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp index a6b0e9e879..6b5d3f0143 100644 --- a/src/gpu/GrTextureProxy.cpp +++ b/src/gpu/GrTextureProxy.cpp @@ -32,7 +32,9 @@ GrTextureProxy::GrTextureProxy(const GrBackendFormat& format, , fMipMapped(mipMapped) , fMipMapsStatus(mipMapsStatus) SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) , fProxyProvider(nullptr) - , fDeferredUploader(nullptr) {} + , fDeferredUploader(nullptr) { + SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly)); +} // Lazy-callback version GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback, @@ -52,7 +54,9 @@ GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback, , fMipMapped(mipMapped) , fMipMapsStatus(mipMapsStatus) SkDEBUGCODE(, fInitialMipMapsStatus(fMipMapsStatus)) , fProxyProvider(nullptr) - , fDeferredUploader(nullptr) {} + , fDeferredUploader(nullptr) { + SkASSERT(!(fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly)); +} // Wrapped version GrTextureProxy::GrTextureProxy(sk_sp surf,