Home | History | Annotate | Download | only in mtl
      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 
     21 bool 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 
    108 id<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 
    116 const void* GrGetPtrFromId(id idObject) {
    117     return (__bridge const void*)idObject;
    118 }
    119 
    120 const void* GrReleaseId(id idObject) {
    121     return (__bridge_retained const void*)idObject;
    122 }
    123 
    124 MTLTextureDescriptor* 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
    139 void 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 
    150 id<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 
    191 id<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 
    217 GrMTLPixelFormat GrGetMTLPixelFormatFromMtlTextureInfo(const GrMtlTextureInfo& info) {
    218     id<MTLTexture> mtlTexture = GrGetMTLTexture(info.fTexture,
    219                                                 GrWrapOwnership::kBorrow_GrWrapOwnership);
    220     return static_cast<GrMTLPixelFormat>(mtlTexture.pixelFormat);
    221 }
    222