blob: 8cc99a0afa5e0be62ad5d3976ebfd887beb616d3 [file] [log] [blame]
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkRefCnt.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/mtl/GrMtlTypes.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrResourceProviderPriv.h"
#include "src/gpu/GrSurfaceDrawContext.h"
#include "src/image/SkSurface_Gpu.h"
#if SK_SUPPORT_GPU
#include "src/gpu/GrSurface.h"
#include "src/gpu/mtl/GrMtlTextureRenderTarget.h"
#ifdef SK_METAL
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
#import <MetalKit/MetalKit.h>
sk_sp<SkSurface> SkSurface::MakeFromCAMetalLayer(GrRecordingContext* rContext,
GrMTLHandle layer,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps,
GrMTLHandle* drawable) {
GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer;
GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(metalLayer.pixelFormat);
GrColorType grColorType = SkColorTypeToGrColorType(colorType);
SkISize dims = {(int)metalLayer.drawableSize.width, (int)metalLayer.drawableSize.height};
GrProxyProvider::TextureInfo texInfo;
texInfo.fMipmapped = GrMipmapped::kNo;
texInfo.fTextureType = GrTextureType::k2D;
sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
[layer, drawable](GrResourceProvider* resourceProvider,
const GrSurfaceProxy::LazySurfaceDesc& desc) {
CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer;
id<CAMetalDrawable> currentDrawable = [metalLayer nextDrawable];
GrMtlGpu* mtlGpu = (GrMtlGpu*) resourceProvider->priv().gpu();
sk_sp<GrRenderTarget> surface;
if (metalLayer.framebufferOnly) {
surface = GrMtlRenderTarget::MakeWrappedRenderTarget(
mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture);
} else {
surface = GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget(
mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture,
GrWrapCacheable::kNo);
}
if (surface && desc.fSampleCnt > 1) {
surface->setRequiresManualMSAAResolve();
}
*drawable = (__bridge_retained GrMTLHandle) currentDrawable;
return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
},
backendFormat,
dims,
sampleCnt,
sampleCnt > 1 ? GrInternalSurfaceFlags::kRequiresManualMSAAResolve
: GrInternalSurfaceFlags::kNone,
metalLayer.framebufferOnly ? nullptr : &texInfo,
GrMipmapStatus::kNotAllocated,
SkBackingFit::kExact,
SkBudgeted::kYes,
GrProtected::kNo,
false,
GrSurfaceProxy::UseAllocator::kYes);
auto device = rContext->priv().createDevice(grColorType,
std::move(proxy),
std::move(colorSpace),
origin,
SkSurfacePropsCopyOrDefault(surfaceProps),
SkBaseGpuDevice::kUninit_InitContents);
if (!device) {
return nullptr;
}
return sk_make_sp<SkSurface_Gpu>(std::move(device));
}
sk_sp<SkSurface> SkSurface::MakeFromMTKView(GrRecordingContext* rContext,
GrMTLHandle view,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps) {
GrProxyProvider* proxyProvider = rContext->priv().proxyProvider();
MTKView* mtkView = (__bridge MTKView*)view;
GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(mtkView.colorPixelFormat);
GrColorType grColorType = SkColorTypeToGrColorType(colorType);
SkISize dims = {(int)mtkView.drawableSize.width, (int)mtkView.drawableSize.height};
GrProxyProvider::TextureInfo texInfo;
texInfo.fMipmapped = GrMipmapped::kNo;
texInfo.fTextureType = GrTextureType::k2D;
sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
[view](GrResourceProvider* resourceProvider,
const GrSurfaceProxy::LazySurfaceDesc& desc) {
MTKView* mtkView = (__bridge MTKView*)view;
id<CAMetalDrawable> currentDrawable = [mtkView currentDrawable];
GrMtlGpu* mtlGpu = (GrMtlGpu*) resourceProvider->priv().gpu();
sk_sp<GrRenderTarget> surface;
if (mtkView.framebufferOnly) {
surface = GrMtlRenderTarget::MakeWrappedRenderTarget(
mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture);
} else {
surface = GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget(
mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture,
GrWrapCacheable::kNo);
}
if (surface && desc.fSampleCnt > 1) {
surface->setRequiresManualMSAAResolve();
}
return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
},
backendFormat,
dims,
sampleCnt,
sampleCnt > 1 ? GrInternalSurfaceFlags::kRequiresManualMSAAResolve
: GrInternalSurfaceFlags::kNone,
mtkView.framebufferOnly ? nullptr : &texInfo,
GrMipmapStatus::kNotAllocated,
SkBackingFit::kExact,
SkBudgeted::kYes,
GrProtected::kNo,
false,
GrSurfaceProxy::UseAllocator::kYes);
auto device = rContext->priv().createDevice(grColorType,
std::move(proxy),
std::move(colorSpace),
origin,
SkSurfacePropsCopyOrDefault(surfaceProps),
SkBaseGpuDevice::kUninit_InitContents);
if (!device) {
return nullptr;
}
return sk_make_sp<SkSurface_Gpu>(std::move(device));
}
#endif
#endif