Implement support for framebufferOnly render targets.

This reflects Dawn and Metal functionality.
Implement a FramebufferOnly flag on GrSurface and GrBackendRenderTarget.
Forward the state from GrBackendRenderTarget to GrSurface.
Check the GrSurface flag in GrGpu::readPixels() and GrGpu::writePixels()
and early-return.

Change-Id: I27d3c9c912b366791bfd0e1db49638d8925742f3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/262802
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White 2020-01-16 18:19:54 -05:00 committed by Skia Commit-Bot
parent 4cb293392c
commit 3c0a50f038
9 changed files with 60 additions and 3 deletions

View File

@ -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; //<! width in pixels
int fHeight; //<! height in pixels

View File

@ -81,9 +81,18 @@ public:
*/
bool readOnly() const { return fSurfaceFlags & GrInternalSurfaceFlags::kReadOnly; }
bool framebufferOnly() const {
return fSurfaceFlags & GrInternalSurfaceFlags::kFramebufferOnly;
}
// Returns true if we are working with protected content.
bool isProtected() const { return fIsProtected == GrProtected::kYes; }
void setFramebufferOnly() {
SkASSERT(this->asRenderTarget());
fSurfaceFlags |= GrInternalSurfaceFlags::kFramebufferOnly;
}
protected:
void setGLRTFBOIDIs0() {
SkASSERT(!this->requiresManualMSAAResolve());

View File

@ -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)

View File

@ -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))

View File

@ -380,7 +380,11 @@ sk_sp<GrRenderTarget> GrGpu::wrapBackendRenderTarget(const GrBackendRenderTarget
return nullptr;
}
return this->onWrapBackendRenderTarget(backendRT, colorType);
sk_sp<GrRenderTarget> rt = this->onWrapBackendRenderTarget(backendRT, colorType);
if (backendRT.isFramebufferOnly()) {
rt->setFramebufferOnly();
}
return rt;
}
sk_sp<GrRenderTarget> 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()));

View File

@ -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;

View File

@ -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<GrRenderTargetContext> 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;

View File

@ -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

View File

@ -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<GrSurface> surf,