aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Timothy Liang <timliang@google.com>2018-07-20 16:53:00 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-07-23 17:23:24 +0000
commite35055f31c7f2a2c7f3c693b9231c44d181ec599 (patch)
tree5283d4e83d140bc7f360430b2b891c04a696b401 /src
parent206dbe8a21b614bbf09b9d2b488ff453e41fdfd9 (diff)
implemented copy surface as blit for metal gpu backend
Bug: skia: Change-Id: Ic59fe585c02168a361985f0864242b3c11e9d98e Reviewed-on: https://skia-review.googlesource.com/142684 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Timothy Liang <timliang@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/mtl/GrMtlCaps.h9
-rw-r--r--src/gpu/mtl/GrMtlCaps.mm49
-rw-r--r--src/gpu/mtl/GrMtlGpu.h6
-rw-r--r--src/gpu/mtl/GrMtlGpu.mm127
-rw-r--r--src/gpu/mtl/GrMtlGpuCommandBuffer.h10
5 files changed, 179 insertions, 22 deletions
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index 1ff16adba4..5d6c82bea8 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -46,10 +46,13 @@ public:
return fPreferedStencilFormat;
}
#endif
+ bool canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount, GrSurfaceOrigin dstOrigin,
+ GrPixelConfig srcConfig, int srcSampleCount, GrSurfaceOrigin srcOrigin,
+ const SkIRect& srcRect, const SkIPoint& dstPoint,
+ bool areDstSrcSameObj) const;
+
bool canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
- const SkIRect& srcRect, const SkIPoint& dstPoint) const override {
- return false;
- }
+ const SkIRect& srcRect, const SkIPoint& dstPoint) const override;
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, GrSurfaceOrigin*,
bool* rectsMustMatch, bool* disallowSubrect) const override {
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index 2527be9ceb..3093352272 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -9,7 +9,10 @@
#include "GrBackendSurface.h"
#include "GrMtlUtil.h"
+#include "GrRenderTargetProxy.h"
#include "GrShaderCaps.h"
+#include "GrSurfaceProxy.h"
+#include "SkRect.h"
GrMtlCaps::GrMtlCaps(const GrContextOptions& contextOptions, const id<MTLDevice> device,
MTLFeatureSet featureSet)
@@ -101,6 +104,52 @@ void GrMtlCaps::initFeatureSet(MTLFeatureSet featureSet) {
SK_ABORT("Requested an unsupported feature set");
}
+bool GrMtlCaps::canCopyAsBlit(GrPixelConfig dstConfig, int dstSampleCount,
+ GrSurfaceOrigin dstOrigin,
+ GrPixelConfig srcConfig, int srcSampleCount,
+ GrSurfaceOrigin srcOrigin,
+ const SkIRect& srcRect, const SkIPoint& dstPoint,
+ bool areDstSrcSameObj) const {
+ if (dstConfig != srcConfig) {
+ return false;
+ }
+ if ((dstSampleCount > 1 || srcSampleCount > 1) && (dstSampleCount != srcSampleCount)) {
+ return false;
+ }
+ if (dstOrigin != srcOrigin) {
+ return false;
+ }
+ if (areDstSrcSameObj) {
+ SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
+ srcRect.width(), srcRect.height());
+ if (dstRect.intersect(srcRect)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool GrMtlCaps::canCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
+ const SkIRect& srcRect, const SkIPoint& dstPoint) const {
+ GrSurfaceOrigin dstOrigin = dst->origin();
+ GrSurfaceOrigin srcOrigin = src->origin();
+
+ int dstSampleCnt = 0;
+ int srcSampleCnt = 0;
+ if (const GrRenderTargetProxy* rtProxy = dst->asRenderTargetProxy()) {
+ dstSampleCnt = rtProxy->numColorSamples();
+ }
+ if (const GrRenderTargetProxy* rtProxy = src->asRenderTargetProxy()) {
+ srcSampleCnt = rtProxy->numColorSamples();
+ }
+ SkASSERT((dstSampleCnt > 0) == SkToBool(dst->asRenderTargetProxy()));
+ SkASSERT((srcSampleCnt > 0) == SkToBool(src->asRenderTargetProxy()));
+
+ return this->canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin,
+ src->config(), srcSampleCnt, srcOrigin,
+ srcRect, dstPoint, dst == src);
+}
+
void GrMtlCaps::initGrCaps(const id<MTLDevice> device) {
// Max vertex attribs is the same on all devices
fMaxVertexAttributes = 31;
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 054f1e6842..98132fa725 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -56,11 +56,15 @@ public:
void testingOnly_flushGpuAndSync() override;
#endif
+ bool copySurfaceAsBlit(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,
const SkIPoint& dstPoint,
- bool canDiscardOutsideDstRect) override { return false; }
+ bool canDiscardOutsideDstRect) override;
GrGpuRTCommandBuffer* createCommandBuffer(
GrRenderTarget*, GrSurfaceOrigin,
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index e4c7c64e5f..79eeb3ad6b 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -527,6 +527,117 @@ void GrMtlGpu::testingOnly_flushGpuAndSync() {
}
#endif // GR_TEST_UTILS
+id<MTLTexture> get_mtl_texture_from_surface(GrSurface* surface, bool doResolve) {
+ id<MTLTexture> mtlTexture = nil;
+
+ GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
+ GrMtlTexture* texture;
+ if (renderTarget) {
+ if (doResolve) {
+ // TODO: do resolve and set mtlTexture to resolved texture. As of now, we shouldn't
+ // have any multisampled render targets.
+ SkASSERT(false);
+ } else {
+ mtlTexture = renderTarget->mtlRenderTexture();
+ }
+ } else {
+ texture = static_cast<GrMtlTexture*>(surface->asTexture());
+ if (texture) {
+ mtlTexture = texture->mtlTexture();
+ }
+ }
+ return mtlTexture;
+}
+
+static int get_surface_sample_cnt(GrSurface* surf) {
+ if (const GrRenderTarget* rt = surf->asRenderTarget()) {
+ return rt->numColorSamples();
+ }
+ return 0;
+}
+
+bool GrMtlGpu::copySurfaceAsBlit(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(this->mtlCaps().canCopyAsBlit(dst->config(), dstSampleCnt, dstOrigin,
+ src->config(), srcSampleCnt, srcOrigin,
+ srcRect, dstPoint, dst == src));
+#endif
+ id<MTLTexture> dstTex = get_mtl_texture_from_surface(dst, false);
+ id<MTLTexture> srcTex = get_mtl_texture_from_surface(src, false);
+
+ // Flip rect if necessary
+ SkIRect srcMtlRect;
+ srcMtlRect.fLeft = srcRect.fLeft;
+ srcMtlRect.fRight = srcRect.fRight;
+ SkIRect dstRect;
+ dstRect.fLeft = dstPoint.fX;
+ dstRect.fRight = dstPoint.fX + srcRect.width();
+
+ if (kBottomLeft_GrSurfaceOrigin == srcOrigin) {
+ srcMtlRect.fTop = srcTex.height - srcRect.fBottom;
+ srcMtlRect.fBottom = srcTex.height - srcRect.fTop;
+ } else {
+ srcMtlRect.fTop = srcRect.fTop;
+ srcMtlRect.fBottom = srcRect.fBottom;
+ }
+
+ if (kBottomLeft_GrSurfaceOrigin == dstOrigin) {
+ dstRect.fTop = dstTex.height - dstPoint.fY - srcMtlRect.height();
+ } else {
+ dstRect.fTop = dstPoint.fY;
+ }
+ dstRect.fBottom = dstRect.fTop + srcMtlRect.height();
+
+ id<MTLBlitCommandEncoder> blitCmdEncoder = [fCmdBuffer blitCommandEncoder];
+ [blitCmdEncoder copyFromTexture: srcTex
+ sourceSlice: 0
+ sourceLevel: 0
+ sourceOrigin: MTLOriginMake(srcMtlRect.x(), srcMtlRect.y(), 0)
+ sourceSize: MTLSizeMake(srcMtlRect.width(), srcMtlRect.height(), 1)
+ toTexture: dstTex
+ destinationSlice: 0
+ destinationLevel: 0
+ destinationOrigin: MTLOriginMake(dstRect.x(), dstRect.y(), 0)];
+ [blitCmdEncoder endEncoding];
+
+ return true;
+}
+
+bool GrMtlGpu::onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin,
+ GrSurface* src, GrSurfaceOrigin srcOrigin,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint,
+ bool canDiscardOutsideDstRect) {
+
+ GrPixelConfig dstConfig = dst->config();
+ GrPixelConfig srcConfig = src->config();
+
+ int dstSampleCnt = get_surface_sample_cnt(dst);
+ int srcSampleCnt = get_surface_sample_cnt(src);
+
+ if (dstSampleCnt > 1 || srcSampleCnt > 1) {
+ SkASSERT(false); // Currently dont support MSAA
+ return false;
+ }
+
+ bool success = false;
+ if (this->mtlCaps().canCopyAsBlit(dstConfig, dstSampleCnt, dstOrigin,
+ srcConfig, srcSampleCnt, srcOrigin,
+ srcRect, dstPoint, dst == src)) {
+ success = this->copySurfaceAsBlit(dst, dstOrigin, src, srcOrigin, srcRect, dstPoint);
+ }
+ if (success) {
+ SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.x(), dstPoint.y(),
+ srcRect.width(), srcRect.height());
+ this->didWriteToSurface(dst, dstOrigin, &dstRect);
+ }
+ return success;
+}
+
bool GrMtlGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
GrColorType srcColorType, const GrMipLevel texels[],
int mipLevelCount) {
@@ -556,20 +667,8 @@ bool GrMtlGpu::onReadPixels(GrSurface* surface, int left, int top, int width, in
return false;
}
- id<MTLTexture> mtlTexture = nil;
- GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget());
- GrMtlTexture* texture;
- if (renderTarget) {
- // TODO: Handle resolving rt here when MSAA is supported. Right now we just grab the render
- // texture since we cannot currently have a multi-sampled rt.
- mtlTexture = renderTarget->mtlRenderTexture();
- } else {
- texture = static_cast<GrMtlTexture*>(surface->asTexture());
- if (texture) {
- mtlTexture = texture->mtlTexture();
- }
- }
-
+ bool doResolve = get_surface_sample_cnt(surface) > 1;
+ id<MTLTexture> mtlTexture = get_mtl_texture_from_surface(surface, doResolve);
if (!mtlTexture) {
return false;
}
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.h b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
index 8f1fd20d62..df1738d4e8 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.h
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
@@ -18,14 +18,14 @@ public:
GrMtlGpuTextureCommandBuffer(GrMtlGpu* gpu, GrTexture* texture, GrSurfaceOrigin origin)
: INHERITED(texture, origin)
, fGpu(gpu) {
- // Silence unused var warning
- (void)fGpu;
}
~GrMtlGpuTextureCommandBuffer() override {}
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
- const SkIPoint& dstPoint) override {}
+ const SkIPoint& dstPoint) override {
+ fGpu->copySurface(fTexture, fOrigin, src, srcOrigin, srcRect, dstPoint);
+ }
void insertEventMarker(const char* msg) override {}
@@ -63,7 +63,9 @@ public:
void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override {}
void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
- const SkIPoint& dstPoint) override {}
+ const SkIPoint& dstPoint) override {
+ fGpu->copySurface(fRenderTarget, fOrigin, src, srcOrigin, srcRect, dstPoint);
+ }
void submit() override {}