1/* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "GrMtlUtil.h" 9 10#include "GrTypesPriv.h" 11#include "GrSurface.h" 12#include "mtl/GrMtlGpu.h" 13#include "mtl/GrMtlTexture.h" 14#include "mtl/GrMtlRenderTarget.h" 15#include "SkSLCompiler.h" 16 17#import <Metal/Metal.h> 18 19#define PRINT_MSL 0 // print out the MSL code generated 20 21bool GrPixelConfigToMTLFormat(GrPixelConfig config, MTLPixelFormat* format) { 22 MTLPixelFormat dontCare; 23 if (!format) { 24 format = &dontCare; 25 } 26 27 switch (config) { 28 case kUnknown_GrPixelConfig: 29 return false; 30 case kRGBA_8888_GrPixelConfig: 31 *format = MTLPixelFormatRGBA8Unorm; 32 return true; 33 case kRGB_888_GrPixelConfig: 34 // TODO: MTLPixelFormatRGB8Unorm 35 return false; 36 case kRGB_888X_GrPixelConfig: 37 *format = MTLPixelFormatRGBA8Unorm; 38 return true; 39 case kRG_88_GrPixelConfig: 40 // TODO: MTLPixelFormatRG8Unorm 41 return false; 42 case kBGRA_8888_GrPixelConfig: 43 *format = MTLPixelFormatBGRA8Unorm; 44 return true; 45 case kSRGBA_8888_GrPixelConfig: 46 *format = MTLPixelFormatRGBA8Unorm_sRGB; 47 return true; 48 case kSBGRA_8888_GrPixelConfig: 49 *format = MTLPixelFormatBGRA8Unorm_sRGB; 50 return true; 51 case kRGBA_1010102_GrPixelConfig: 52 *format = MTLPixelFormatRGB10A2Unorm; 53 return true; 54 case kRGB_565_GrPixelConfig: 55#ifdef SK_BUILD_FOR_IOS 56 *format = MTLPixelFormatB5G6R5Unorm; 57 return true; 58#else 59 return false; 60#endif 61 case kRGBA_4444_GrPixelConfig: 62#ifdef SK_BUILD_FOR_IOS 63 *format = MTLPixelFormatABGR4Unorm; 64 return true; 65#else 66 return false; 67#endif 68 case kAlpha_8_GrPixelConfig: // fall through 69 case kAlpha_8_as_Red_GrPixelConfig: 70 *format = MTLPixelFormatR8Unorm; 71 return true; 72 case kAlpha_8_as_Alpha_GrPixelConfig: 73 return false; 74 case kGray_8_GrPixelConfig: // fall through 75 case kGray_8_as_Red_GrPixelConfig: 76 *format = MTLPixelFormatR8Unorm; 77 return true; 78 case kGray_8_as_Lum_GrPixelConfig: 79 return false; 80 case kRGBA_float_GrPixelConfig: 81 *format = MTLPixelFormatRGBA32Float; 82 return true; 83 case kRG_float_GrPixelConfig: 84 *format = MTLPixelFormatRG32Float; 85 return true; 86 case kRGBA_half_GrPixelConfig: 87 *format = MTLPixelFormatRGBA16Float; 88 return true; 89 case kRGBA_half_Clamped_GrPixelConfig: 90 *format = MTLPixelFormatRGBA16Float; 91 return true; 92 case kAlpha_half_GrPixelConfig: // fall through 93 case kAlpha_half_as_Red_GrPixelConfig: 94 *format = MTLPixelFormatR16Float; 95 return true; 96 case kRGB_ETC1_GrPixelConfig: 97#ifdef SK_BUILD_FOR_IOS 98 *format = MTLPixelFormatETC2_RGB8; 99 return true; 100#else 101 return false; 102#endif 103 } 104 SK_ABORT("Unexpected config"); 105 return false; 106} 107 108id<MTLTexture> GrGetMTLTexture(const void* mtlTexture, GrWrapOwnership wrapOwnership) { 109 if (GrWrapOwnership::kAdopt_GrWrapOwnership == wrapOwnership) { 110 return (__bridge_transfer id<MTLTexture>)mtlTexture; 111 } else { 112 return (__bridge id<MTLTexture>)mtlTexture; 113 } 114} 115 116const void* GrGetPtrFromId(id idObject) { 117 return (__bridge const void*)idObject; 118} 119 120const void* GrReleaseId(id idObject) { 121 return (__bridge_retained const void*)idObject; 122} 123 124MTLTextureDescriptor* GrGetMTLTextureDescriptor(id<MTLTexture> mtlTexture) { 125 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init]; 126 texDesc.textureType = mtlTexture.textureType; 127 texDesc.pixelFormat = mtlTexture.pixelFormat; 128 texDesc.width = mtlTexture.width; 129 texDesc.height = mtlTexture.height; 130 texDesc.depth = mtlTexture.depth; 131 texDesc.mipmapLevelCount = mtlTexture.mipmapLevelCount; 132 texDesc.arrayLength = mtlTexture.arrayLength; 133 texDesc.sampleCount = mtlTexture.sampleCount; 134 texDesc.usage = mtlTexture.usage; 135 return texDesc; 136} 137 138#if PRINT_MSL 139void print_msl(const char* source) { 140 SkTArray<SkString> lines; 141 SkStrSplit(source, "\n", kStrict_SkStrSplitMode, &lines); 142 for (int i = 0; i < lines.count(); i++) { 143 SkString& line = lines[i]; 144 line.prependf("%4i\t", i + 1); 145 SkDebugf("%s\n", line.c_str()); 146 } 147} 148#endif 149 150id<MTLLibrary> GrCompileMtlShaderLibrary(const GrMtlGpu* gpu, 151 const char* shaderString, 152 SkSL::Program::Kind kind, 153 const SkSL::Program::Settings& settings, 154 SkSL::Program::Inputs* outInputs) { 155 std::unique_ptr<SkSL::Program> program = 156 gpu->shaderCompiler()->convertProgram(kind, 157 SkSL::String(shaderString), 158 settings); 159 160 if (!program) { 161 SkDebugf("SkSL error:\n%s\n", gpu->shaderCompiler()->errorText().c_str()); 162 SkASSERT(false); 163 } 164 165 *outInputs = program->fInputs; 166 SkSL::String code; 167 if (!gpu->shaderCompiler()->toMetal(*program, &code)) { 168 SkDebugf("%s\n", gpu->shaderCompiler()->errorText().c_str()); 169 SkASSERT(false); 170 return nil; 171 } 172 NSString* mtlCode = [[NSString alloc] initWithCString: code.c_str() 173 encoding: NSASCIIStringEncoding]; 174#if PRINT_MSL 175 print_msl([mtlCode cStringUsingEncoding: NSASCIIStringEncoding]); 176#endif 177 178 MTLCompileOptions* defaultOptions = [[MTLCompileOptions alloc] init]; 179 NSError* error = nil; 180 id<MTLLibrary> compiledLibrary = [gpu->device() newLibraryWithSource: mtlCode 181 options: defaultOptions 182 error: &error]; 183 if (error) { 184 SkDebugf("Error compiling MSL shader: %s\n", 185 [[error localizedDescription] cStringUsingEncoding: NSASCIIStringEncoding]); 186 return nil; 187 } 188 return compiledLibrary; 189} 190 191id<MTLTexture> GrGetMTLTextureFromSurface(GrSurface* surface, bool doResolve) { 192 id<MTLTexture> mtlTexture = nil; 193 194 GrMtlRenderTarget* renderTarget = static_cast<GrMtlRenderTarget*>(surface->asRenderTarget()); 195 GrMtlTexture* texture; 196 if (renderTarget) { 197 if (doResolve) { 198 // TODO: do resolve and set mtlTexture to resolved texture. As of now, we shouldn't 199 // have any multisampled render targets. 200 SkASSERT(false); 201 } else { 202 mtlTexture = renderTarget->mtlRenderTexture(); 203 } 204 } else { 205 texture = static_cast<GrMtlTexture*>(surface->asTexture()); 206 if (texture) { 207 mtlTexture = texture->mtlTexture(); 208 } 209 } 210 return mtlTexture; 211} 212 213 214////////////////////////////////////////////////////////////////////////////// 215// CPP Utils 216 217GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) { 218 id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture, 219 GrWrapOwnership::kBorrow_GrWrapOwnership); 220 return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat); 221} 222