/* * 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; } sk_sp<GrGpu> GrMtlGpu::Make(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 sk_sp<GrGpu>(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); } if (!tex) { return nullptr; } if (mipLevelCount) { // Perform initial data upload here } if (desc.fFlags & kPerformInitialClear_GrSurfaceFlag) { // Do initial clear of the texture } return tex; }