implemented copy surface as draw then blit for metal gpu backend
Bug: skia: Change-Id: Ifa2d7ced7c22f74c2829d11b24557dbe851e3473 Reviewed-on: https://skia-review.googlesource.com/142691 Commit-Queue: Timothy Liang <timliang@google.com> Reviewed-by: Greg Daniel <egdaniel@google.com>
This commit is contained in:
parent
722efde79c
commit
70c787ae5b
@ -477,6 +477,8 @@
|
||||
"_",
|
||||
".SRW",
|
||||
"--match",
|
||||
"CopySurface",
|
||||
"GrTestingBackendTextureUploadTest",
|
||||
"GrUploadPixelsTests",
|
||||
"--nonativeFonts",
|
||||
"--verbose"
|
||||
|
@ -817,7 +817,10 @@ def dm_flags(api, bot):
|
||||
if 'Metal' in bot:
|
||||
# If we modify the whitelist to include GMs, also update infra/bots/cfg.json
|
||||
# to remove Metal from no_upload.
|
||||
match = ['GrUploadPixelsTests']
|
||||
match = []
|
||||
match.append('CopySurface')
|
||||
match.append('GrTestingBackendTextureUploadTest')
|
||||
match.append('GrUploadPixelsTests')
|
||||
|
||||
if match:
|
||||
args.append('--match')
|
||||
|
@ -54,6 +54,9 @@ public:
|
||||
bool canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable,
|
||||
GrPixelConfig srcConfig, bool srcIsTextureable) const;
|
||||
|
||||
bool canCopyAsDrawThenBlit(GrPixelConfig dstConfig, GrPixelConfig srcConfig,
|
||||
bool srcIsTextureable) const;
|
||||
|
||||
bool canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
|
||||
|
||||
|
@ -143,6 +143,19 @@ bool GrMtlCaps::canCopyAsDraw(GrPixelConfig dstConfig, bool dstIsRenderable,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrMtlCaps::canCopyAsDrawThenBlit(GrPixelConfig dstConfig, GrPixelConfig srcConfig,
|
||||
bool srcIsTextureable) const {
|
||||
// TODO: Make copySurfaceAsDraw handle the swizzle
|
||||
if (this->shaderCaps()->configOutputSwizzle(srcConfig) !=
|
||||
this->shaderCaps()->configOutputSwizzle(dstConfig)) {
|
||||
return false;
|
||||
}
|
||||
if (!srcIsTextureable) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrMtlCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) const {
|
||||
GrSurfaceOrigin dstOrigin = dst->origin();
|
||||
@ -163,7 +176,9 @@ bool GrMtlCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy*
|
||||
src->config(), srcSampleCnt, srcOrigin,
|
||||
srcRect, dstPoint, dst == src) ||
|
||||
this->canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTargetProxy()),
|
||||
src->config(), SkToBool(src->asTextureProxy()));
|
||||
src->config(), SkToBool(src->asTextureProxy())) ||
|
||||
this->canCopyAsDrawThenBlit(dst->config(), src->config(),
|
||||
SkToBool(src->asTextureProxy()));
|
||||
}
|
||||
|
||||
void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
|
||||
|
@ -68,6 +68,13 @@ public:
|
||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint);
|
||||
|
||||
// This function is needed when we want to copy between two surfaces with different origins and
|
||||
// the destination surface is not a render target. We will first draw to a temporary render
|
||||
// target to adjust for the different origins and then blit from there to the destination.
|
||||
bool copySurfaceAsDrawThenBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint);
|
||||
|
||||
bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||
const SkIRect& srcRect,
|
||||
|
@ -591,6 +591,71 @@ bool GrMtlGpu::copySurfaceAsBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrMtlGpu::copySurfaceAsDrawThenBlit(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||
const SkIRect& srcRect, const SkIPoint& dstPoint) {
|
||||
#ifdef SK_DEBUG
|
||||
int dstSampleCnt = get_surface_sample_cnt(dst);
|
||||
int srcSampleCnt = get_surface_sample_cnt(src);
|
||||
SkASSERT(dstSampleCnt == 0); // dst shouldn't be a render target
|
||||
SkASSERT(!this->mtlCaps().canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin,
|
||||
src->config(), srcSampleCnt, srcOrigin,
|
||||
srcRect, dstPoint, dst == src));
|
||||
SkASSERT(!this->mtlCaps().canCopyAsDraw(dst->config(), SkToBool(dst->asRenderTarget()),
|
||||
src->config(), SkToBool(src->asTexture())));
|
||||
SkASSERT(this->mtlCaps().canCopyAsDrawThenBlit(dst->config(),src->config(),
|
||||
SkToBool(src->asTexture())));
|
||||
#endif
|
||||
GrSurfaceDesc surfDesc;
|
||||
surfDesc.fFlags = kRenderTarget_GrSurfaceFlag;
|
||||
surfDesc.fWidth = srcRect.width();
|
||||
surfDesc.fHeight = srcRect.height();
|
||||
surfDesc.fConfig = dst->config();
|
||||
surfDesc.fSampleCnt = 1;
|
||||
|
||||
id<MTLTexture> dstTex = GrGetMTLTextureFromSurface(dst, false);
|
||||
MTLTextureDescriptor* textureDesc = GrGetMTLTextureDescriptor(dstTex);
|
||||
textureDesc.width = srcRect.width();
|
||||
textureDesc.height = srcRect.height();
|
||||
textureDesc.mipmapLevelCount = 1;
|
||||
textureDesc.usage |= MTLTextureUsageRenderTarget;
|
||||
|
||||
sk_sp<GrMtlTexture> transferTexture =
|
||||
GrMtlTextureRenderTarget::CreateNewTextureRenderTarget(this,
|
||||
SkBudgeted::kYes,
|
||||
surfDesc,
|
||||
textureDesc,
|
||||
GrMipMapsStatus::kNotAllocated);
|
||||
|
||||
GrSurfaceOrigin transferOrigin = dstOrigin;
|
||||
SkASSERT(this->mtlCaps().canCopyAsDraw(transferTexture->config(),
|
||||
SkToBool(transferTexture->asRenderTarget()),
|
||||
src->config(),
|
||||
SkToBool(src->asTexture())));
|
||||
// TODO: Eventually we will need to handle resolves either in this function or make a separate
|
||||
// copySurfaceAsResolveThenBlit().
|
||||
if (!this->copySurface(transferTexture.get(), transferOrigin,
|
||||
src, srcOrigin,
|
||||
srcRect, SkIPoint::Make(0, 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkIRect transferRect = SkIRect::MakeXYWH(0, 0, srcRect.width(), srcRect.height());
|
||||
SkASSERT(this->mtlCaps().canCopyAsBlit(dst->config(),
|
||||
get_surface_sample_cnt(dst),
|
||||
dstOrigin,
|
||||
transferTexture->config(),
|
||||
get_surface_sample_cnt(transferTexture.get()),
|
||||
transferOrigin,
|
||||
transferRect, dstPoint, false));
|
||||
if (!this->copySurface(dst, dstOrigin,
|
||||
transferTexture.get(), transferOrigin,
|
||||
transferRect, dstPoint)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
GrSurface* src, GrSurfaceOrigin srcOrigin,
|
||||
const SkIRect& srcRect,
|
||||
@ -604,7 +669,7 @@ bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
int srcSampleCnt = get_surface_sample_cnt(src);
|
||||
|
||||
if (dstSampleCnt > 1 || srcSampleCnt > 1) {
|
||||
SkASSERT(false); // Currently dont support MSAA
|
||||
SkASSERT(false); // Currently dont support MSAA. TODO: add copySurfaceAsResolve().
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -617,6 +682,10 @@ bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
|
||||
srcConfig, srcSampleCnt, srcOrigin,
|
||||
srcRect, dstPoint, dst == src)) {
|
||||
success = this->copySurfaceAsBlit(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
|
||||
} else if (this->mtlCaps().canCopyAsDrawThenBlit(dst->config(), src->config(),
|
||||
SkToBool(src->asTexture()))) {
|
||||
success = this->copySurfaceAsDrawThenBlit(dst, dstOrigin, src, srcOrigin,
|
||||
srcRect, dstPoint);
|
||||
}
|
||||
if (success) {
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
|
||||
|
Loading…
Reference in New Issue
Block a user