blob: d3e42bd335def928ba8d2aec1cbacea52ad5910b [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/GrContext.h"
#include "include/gpu/mtl/GrMtlTypes.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRenderTargetContext.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrResourceProviderPriv.h"
#include "src/image/SkSurface_Gpu.h"
#if SK_SUPPORT_GPU
#include "include/gpu/GrSurface.h"
#include "src/gpu/mtl/GrMtlTextureRenderTarget.h"
#ifdef SK_METAL
#import <Metal/Metal.h>
#import <QuartzCore/CAMetalLayer.h>
sk_sp<SkSurface> SkSurface::MakeFromCAMetalLayer(GrContext* context,
GrMTLHandle layer,
GrSurfaceOrigin origin,
int sampleCnt,
SkColorType colorType,
sk_sp<SkColorSpace> colorSpace,
const SkSurfaceProps* surfaceProps,
GrMTLHandle* drawable) {
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
const GrCaps* caps = context->priv().caps();
CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer;
GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(metalLayer.pixelFormat);
GrColorType grColorType = SkColorTypeToGrColorType(colorType);
GrPixelConfig config = caps->getConfigFromBackendFormat(backendFormat, grColorType);
if (config == kUnknown_GrPixelConfig) {
return nullptr;
}
GrSurfaceDesc desc;
desc.fWidth = metalLayer.drawableSize.width;
desc.fHeight = metalLayer.drawableSize.height;
desc.fConfig = config;
GrProxyProvider::TextureInfo texInfo;
texInfo.fMipMapped = GrMipMapped::kNo;
texInfo.fTextureType = GrTextureType::k2D;
sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy(
[layer, drawable, sampleCnt, config](GrResourceProvider* resourceProvider) {
CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer;
id<CAMetalDrawable> currentDrawable = [metalLayer nextDrawable];
GrSurfaceDesc desc;
desc.fWidth = metalLayer.drawableSize.width;
desc.fHeight = metalLayer.drawableSize.height;
desc.fConfig = config;
GrMtlGpu* mtlGpu = (GrMtlGpu*) resourceProvider->priv().gpu();
sk_sp<GrRenderTarget> surface;
if (metalLayer.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();
}
*drawable = (__bridge_retained GrMTLHandle) currentDrawable;
return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
},
backendFormat,
desc,
sampleCnt,
origin,
sampleCnt > 1 ? GrInternalSurfaceFlags::kRequiresManualMSAAResolve
: GrInternalSurfaceFlags::kNone,
metalLayer.framebufferOnly ? nullptr : &texInfo,
GrMipMapsStatus::kNotAllocated,
SkBackingFit::kExact,
SkBudgeted::kYes,
GrProtected::kNo,
false,
GrSurfaceProxy::UseAllocator::kYes);
auto c = context->priv().makeWrappedSurfaceContext(std::move(proxy),
grColorType,
kPremul_SkAlphaType,
colorSpace,
surfaceProps);
SkASSERT(c->asRenderTargetContext());
std::unique_ptr<GrRenderTargetContext> rtc(c.release()->asRenderTargetContext());
sk_sp<SkSurface> surface = SkSurface_Gpu::MakeWrappedRenderTarget(context, std::move(rtc));
return surface;
}
#endif
#endif