Add method to delay drawable acquisition from MTKView

Change-Id: Iad9fadd113d0c97e8ece51df19c7824252d7eb9c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/263197
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
Jim Van Verth 2020-01-08 12:15:44 -05:00 committed by Skia Commit-Bot
parent 04e77813f8
commit e27670172b
4 changed files with 125 additions and 18 deletions

View File

@ -8,6 +8,10 @@ Milestone 81
<Insert new notes here- top is most recent.>
* Add support to create an SkSurface from an MTKView, with delayed acquisition of
the MTLDrawable.
Entry point: SkSurface::MakeFromMTKView
* Removed SkIRect::EmptyIRect(). Use SkIRect::MakeEmpty() instead.
https://review.skia.org/262382/

View File

@ -318,8 +318,7 @@ public:
#endif
#ifdef SK_METAL
/** Private.
Creates SkSurface from CAMetalLayer.
/** Creates SkSurface from CAMetalLayer.
Returned SkSurface takes a reference on the CAMetalLayer. The ref on the layer will be
released when the SkSurface is destroyed.
@ -354,6 +353,37 @@ public:
const SkSurfaceProps* surfaceProps,
GrMTLHandle* drawable);
/** Creates SkSurface from MTKView.
Returned SkSurface takes a reference on the MTKView. The ref on the layer will be
released when the SkSurface is destroyed.
Only available when Metal API is enabled.
Will grab the current drawable from the layer and use its texture as a backendRT to
create a renderable surface.
@param context GPU context
@param layer GrMTLHandle (expected to be a MTKView*)
@param origin one of: kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin
@param sampleCnt samples per pixel, or 0 to disable full scene anti-aliasing
@param colorType one of:
kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType,
kARGB_4444_SkColorType, kRGBA_8888_SkColorType,
kRGB_888x_SkColorType, kBGRA_8888_SkColorType,
kRGBA_1010102_SkColorType, kRGB_101010x_SkColorType,
kGray_8_SkColorType, kRGBA_F16_SkColorType
@param colorSpace range of colors; may be nullptr
@param surfaceProps LCD striping orientation and setting for device independent
fonts; may be nullptr
@return created SkSurface, or nullptr
*/
static sk_sp<SkSurface> MakeFromMTKView(GrContext* context,
GrMTLHandle mtkView,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps);
#endif
/** Returns SkSurface on GPU indicated by context. Allocates memory for

View File

@ -25,6 +25,7 @@
#ifdef SK_METAL
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
#import <MetalKit/MetalKit.h>
sk_sp<SkSurface> SkSurface::MakeFromCAMetalLayer(GrContext* context,
GrMTLHandle layer,
@ -110,6 +111,90 @@ sk_sp<SkSurface> SkSurface::MakeFromCAMetalLayer(GrContext* context,
sk_sp<SkSurface> surface = SkSurface_Gpu::MakeWrappedRenderTarget(context, std::move(rtc));
return surface;
}
sk_sp<SkSurface> SkSurface::MakeFromMTKView(GrContext* context,
GrMTLHandle view,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps) {
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
const GrCaps* caps = context->priv().caps();
MTKView* mtkView = (__bridge MTKView*)view;
GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(mtkView.colorPixelFormat);
GrColorType grColorType = SkColorTypeToGrColorType(colorType);
GrPixelConfig config = caps->getConfigFromBackendFormat(backendFormat, grColorType);
if (config == kUnknown_GrPixelConfig) {
return nullptr;
}
GrSurfaceDesc desc;
desc.fWidth = mtkView.drawableSize.width;
desc.fHeight = mtkView.drawableSize.height;
desc.fConfig = config;
GrProxyProvider::TextureInfo texInfo;
texInfo.fMipMapped = GrMipMapped::kNo;
texInfo.fTextureType = GrTextureType::k2D;
sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
[view, sampleCnt, config](GrResourceProvider* resourceProvider) {
MTKView* mtkView = (__bridge MTKView*)view;
id<CAMetalDrawable> currentDrawable = [mtkView currentDrawable];
GrSurfaceDesc desc;
desc.fWidth = mtkView.drawableSize.width;
desc.fHeight = mtkView.drawableSize.height;
desc.fConfig = config;
GrMtlGpu* mtlGpu = (GrMtlGpu*) resourceProvider->priv().gpu();
sk_sp<GrRenderTarget> surface;
if (mtkView.framebufferOnly) {
surface = GrMtlRenderTarget::MakeWrappedRenderTarget(
mtlGpu, desc, sampleCnt, currentDrawable.texture);
} else {
surface = GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget(
mtlGpu, desc, sampleCnt, currentDrawable.texture,
GrWrapCacheable::kNo);
}
if (surface && sampleCnt > 1) {
surface->setRequiresManualMSAAResolve();
}
return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
},
backendFormat,
desc,
sampleCnt,
origin,
sampleCnt > 1 ? GrInternalSurfaceFlags::kRequiresManualMSAAResolve
: GrInternalSurfaceFlags::kNone,
mtkView.framebufferOnly ? nullptr : &texInfo,
GrMipMapsStatus::kNotAllocated,
SkBackingFit::kExact,
SkBudgeted::kYes,
GrProtected::kNo,
false,
GrSurfaceProxy::UseAllocator::kYes);
const GrSwizzle& readSwizzle = caps->getReadSwizzle(backendFormat, grColorType);
const GrSwizzle& outputSwizzle = caps->getOutputSwizzle(backendFormat, grColorType);
SkASSERT(readSwizzle == proxy->textureSwizzle());
auto rtc = std::make_unique<GrRenderTargetContext>(context, std::move(proxy),
grColorType, origin,
readSwizzle, outputSwizzle,
colorSpace, surfaceProps);
sk_sp<SkSurface> surface = SkSurface_Gpu::MakeWrappedRenderTarget(context, std::move(rtc));
return surface;
}
#endif
#endif

View File

@ -13,32 +13,20 @@
#import <MetalKit/MetalKit.h>
sk_sp<SkSurface> SkMtkViewToSurface(MTKView* mtkView, GrContext* grContext) {
if (![[mtkView currentDrawable] texture] ||
!grContext ||
if (!grContext ||
MTLPixelFormatDepth32Float_Stencil8 != [mtkView depthStencilPixelFormat] ||
MTLPixelFormatBGRA8Unorm != [mtkView colorPixelFormat]) {
return nullptr;
}
const SkColorType colorType = kBGRA_8888_SkColorType; // MTLPixelFormatBGRA8Unorm
sk_sp<SkColorSpace> colorSpace = nullptr; // MTLPixelFormatBGRA8Unorm
const GrSurfaceOrigin origin = kTopLeft_GrSurfaceOrigin;
const SkSurfaceProps surfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
int sampleCount = (int)[mtkView sampleCount];
CGSize size = [mtkView drawableSize];
int width = (int)size.width;
int height = (int)size.height;
GrMtlTextureInfo fbInfo;
fbInfo.fTexture.retain((__bridge const void*)([[mtkView currentDrawable] texture]));
if (sampleCount == 1) {
GrBackendRenderTarget backendRT(width, height, 1, fbInfo);
return SkSurface::MakeFromBackendRenderTarget(grContext, backendRT, origin,
colorType, colorSpace, &surfaceProps);
} else {
GrBackendTexture backendTexture(width, height, GrMipMapped::kNo, fbInfo);
return SkSurface::MakeFromBackendTexture(grContext, backendTexture, origin, sampleCount,
colorType, colorSpace, &surfaceProps);
}
return SkSurface::MakeFromMTKView(grContext, (__bridge GrMTLHandle)mtkView, origin, sampleCount,
colorType, colorSpace, &surfaceProps);
}
void GrContextRelease::operator()(GrContext* ptr) { SkSafeUnref(ptr); }