| /* |
| * Copyright 2017 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "GrMtlGpu.h" |
| |
| #include "GrMtlTexture.h" |
| |
| #if !__has_feature(objc_arc) |
| #error This file must be compiled with Arc. Use -fobjc-arc flag |
| #endif |
| |
| static bool get_feature_set(id<MTLDevice> device, MTLFeatureSet* featureSet) { |
| // Mac OSX |
| #ifdef SK_BUILD_FOR_MAC |
| if ([device supportsFeatureSet:MTLFeatureSet_OSX_GPUFamily1_v2]) { |
| *featureSet = MTLFeatureSet_OSX_GPUFamily1_v2; |
| return true; |
| } |
| if ([device supportsFeatureSet:MTLFeatureSet_OSX_GPUFamily1_v1]) { |
| *featureSet = MTLFeatureSet_OSX_GPUFamily1_v1; |
| return true; |
| } |
| #endif |
| |
| // iOS Family group 3 |
| #ifdef SK_BUILD_FOR_IOS |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily3_v2; |
| return true; |
| } |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily3_v1; |
| return true; |
| } |
| |
| // iOS Family group 2 |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v3]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily2_v3; |
| return true; |
| } |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v2]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily2_v2; |
| return true; |
| } |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily2_v1]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily2_v1; |
| return true; |
| } |
| |
| // iOS Family group 1 |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v3]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily1_v3; |
| return true; |
| } |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v2]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily1_v2; |
| return true; |
| } |
| if ([device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v1]) { |
| *featureSet = MTLFeatureSet_iOS_GPUFamily1_v1; |
| return true; |
| } |
| #endif |
| // No supported feature sets were found |
| return false; |
| } |
| |
| GrGpu* GrMtlGpu::Create(GrContext* context, const GrContextOptions& options, |
| id<MTLDevice> device, id<MTLCommandQueue> queue) { |
| if (!device || !queue) { |
| return nullptr; |
| } |
| MTLFeatureSet featureSet; |
| if (!get_feature_set(device, &featureSet)) { |
| return nullptr; |
| } |
| return new GrMtlGpu(context, options, device, queue, featureSet); |
| } |
| |
| GrMtlGpu::GrMtlGpu(GrContext* context, const GrContextOptions& options, |
| id<MTLDevice> device, id<MTLCommandQueue> queue, MTLFeatureSet featureSet) |
| : INHERITED(context) |
| , fDevice(device) |
| , fQueue(queue) { |
| |
| fMtlCaps.reset(new GrMtlCaps(options, fDevice, featureSet)); |
| fCaps = fMtlCaps; |
| |
| MTLTextureDescriptor* txDesc = [[MTLTextureDescriptor alloc] init]; |
| txDesc.textureType = MTLTextureType3D; |
| txDesc.height = 64; |
| txDesc.width = 64; |
| txDesc.depth = 64; |
| txDesc.pixelFormat = MTLPixelFormatRGBA8Unorm; |
| txDesc.arrayLength = 1; |
| txDesc.mipmapLevelCount = 1; |
| id<MTLTexture> testTexture = [fDevice newTextureWithDescriptor:txDesc]; |
| // To get ride of unused var warning |
| int width = [testTexture width]; |
| SkDebugf("width: %d\n", width); |
| // Unused queue warning fix |
| SkDebugf("ptr to queue: %p\n", fQueue); |
| } |
| |
| sk_sp<GrTexture> GrMtlGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, |
| const GrMipLevel texels[], int mipLevelCount) { |
| int mipLevels = !mipLevelCount ? 1 : mipLevelCount; |
| |
| if (!fMtlCaps->isConfigTexturable(desc.fConfig)) { |
| return nullptr; |
| } |
| |
| bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); |
| if (renderTarget) { |
| // Current we don't have render target support |
| return nullptr; |
| } |
| |
| sk_sp<GrMtlTexture> tex; |
| if (renderTarget) { |
| // Enable once we have render target support |
| #if 0 |
| tex = GrMtlTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, |
| desc, mipLevels); |
| #endif |
| } else { |
| tex = GrMtlTexture::CreateNewTexture(this, budgeted, desc, mipLevels, false); |
| } |
| |
| if (!tex) { |
| return nullptr; |
| } |
| |
| if (mipLevelCount) { |
| // Perform initial data upload here |
| } |
| |
| if (desc.fFlags & kPerformInitialClear_GrSurfaceFlag) { |
| // Do initial clear of the texture |
| } |
| return tex; |
| } |