blob: 9bdaa82ac7ea3af94fa9810a564e1ef82e4632b9 [file] [log] [blame]
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/mtl/GrMtlGpu.h"
#include "src/gpu/mtl/GrMtlTextureRenderTarget.h"
#include "src/gpu/mtl/GrMtlUtil.h"
#if !__has_feature(objc_arc)
#error This file must be compiled with Arc. Use -fobjc-arc flag
#endif
GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu,
SkBudgeted budgeted,
const GrSurfaceDesc& desc,
int sampleCnt,
id<MTLTexture> colorTexture,
id<MTLTexture> resolveTexture,
GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo)
, GrMtlTexture(gpu, desc, resolveTexture, mipMapsStatus)
, GrMtlRenderTarget(gpu, desc, sampleCnt, colorTexture, resolveTexture) {
this->registerWithCache(budgeted);
}
GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu,
SkBudgeted budgeted,
const GrSurfaceDesc& desc,
id<MTLTexture> colorTexture,
GrMipMapsStatus mipMapsStatus)
: GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo)
, GrMtlTexture(gpu, desc, colorTexture, mipMapsStatus)
, GrMtlRenderTarget(gpu, desc, colorTexture) {
this->registerWithCache(budgeted);
}
GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu,
const GrSurfaceDesc& desc,
int sampleCnt,
id<MTLTexture> colorTexture,
id<MTLTexture> resolveTexture,
GrMipMapsStatus mipMapsStatus,
GrWrapCacheable cacheable)
: GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo)
, GrMtlTexture(gpu, desc, resolveTexture, mipMapsStatus)
, GrMtlRenderTarget(gpu, desc, sampleCnt, colorTexture, resolveTexture) {
this->registerWithCacheWrapped(cacheable);
}
GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu,
const GrSurfaceDesc& desc,
id<MTLTexture> colorTexture,
GrMipMapsStatus mipMapsStatus,
GrWrapCacheable cacheable)
: GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo)
, GrMtlTexture(gpu, desc, colorTexture, mipMapsStatus)
, GrMtlRenderTarget(gpu, desc, colorTexture) {
this->registerWithCacheWrapped(cacheable);
}
id<MTLTexture> create_msaa_texture(GrMtlGpu* gpu, const GrSurfaceDesc& desc, int sampleCnt) {
MTLPixelFormat format;
if (!GrPixelConfigToMTLFormat(desc.fConfig, &format)) {
return nullptr;
}
MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
texDesc.textureType = MTLTextureType2DMultisample;
texDesc.pixelFormat = format;
texDesc.width = desc.fWidth;
texDesc.height = desc.fHeight;
texDesc.depth = 1;
texDesc.mipmapLevelCount = 1;
texDesc.sampleCount = sampleCnt;
texDesc.arrayLength = 1;
if (@available(macOS 10.11, iOS 9.0, *)) {
texDesc.storageMode = MTLStorageModePrivate;
texDesc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
}
return [gpu->device() newTextureWithDescriptor:texDesc];
}
sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeNewTextureRenderTarget(
GrMtlGpu* gpu,
SkBudgeted budgeted,
const GrSurfaceDesc& desc,
int sampleCnt,
MTLTextureDescriptor* texDesc,
GrMipMapsStatus mipMapsStatus) {
id<MTLTexture> texture = [gpu->device() newTextureWithDescriptor:texDesc];
if (!texture) {
return nullptr;
}
if (@available(macOS 10.11, iOS 9.0, *)) {
SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & texture.usage);
}
if (sampleCnt > 1) {
id<MTLTexture> colorTexture = create_msaa_texture(gpu, desc, sampleCnt);
if (!colorTexture) {
return nullptr;
}
if (@available(macOS 10.11, iOS 9.0, *)) {
SkASSERT((MTLTextureUsageShaderRead|MTLTextureUsageRenderTarget) & colorTexture.usage);
}
return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget(
gpu, budgeted, desc, sampleCnt, colorTexture, texture, mipMapsStatus));
} else {
return sk_sp<GrMtlTextureRenderTarget>(
new GrMtlTextureRenderTarget(gpu, budgeted, desc, texture, mipMapsStatus));
}
}
sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget(
GrMtlGpu* gpu,
const GrSurfaceDesc& desc,
int sampleCnt,
id<MTLTexture> texture,
GrWrapCacheable cacheable) {
SkASSERT(nil != texture);
if (@available(macOS 10.11, iOS 9.0, *)) {
SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & texture.usage);
}
GrMipMapsStatus mipMapsStatus = texture.mipmapLevelCount > 1
? GrMipMapsStatus::kDirty
: GrMipMapsStatus::kNotAllocated;
if (sampleCnt > 1) {
id<MTLTexture> colorTexture = create_msaa_texture(gpu, desc, sampleCnt);
if (!colorTexture) {
return nullptr;
}
if (@available(macOS 10.11, iOS 9.0, *)) {
SkASSERT((MTLTextureUsageShaderRead|MTLTextureUsageRenderTarget) & colorTexture.usage);
}
return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget(
gpu, desc, sampleCnt, colorTexture, texture, mipMapsStatus, cacheable));
} else {
return sk_sp<GrMtlTextureRenderTarget>(
new GrMtlTextureRenderTarget(gpu, desc, texture, mipMapsStatus, cacheable));
}
}