mirror of
https://github.com/libretro/RetroArch
synced 2025-02-06 00:39:53 +00:00
fix(Metal): Various Metal fixes
* OSD message background * clear glui background * add Metal to configuration * added optional config to compile Metal build without OpenGL * fixed fill_pathname_join_delim; if out_path and dir are same, don't strlcpy, as the results are undefined.
This commit is contained in:
parent
dbfccb25dd
commit
167ad3b57d
@ -125,6 +125,7 @@ enum video_driver_enum
|
||||
{
|
||||
VIDEO_GL = 0,
|
||||
VIDEO_VULKAN,
|
||||
VIDEO_METAL,
|
||||
VIDEO_DRM,
|
||||
VIDEO_XVIDEO,
|
||||
VIDEO_SDL,
|
||||
@ -291,6 +292,8 @@ enum midi_driver_enum
|
||||
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(__CELLOS_LV2__)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
|
||||
#elif defined(HAVE_METAL)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
|
||||
#elif defined(GEKKO)
|
||||
static enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WII;
|
||||
#elif defined(WIIU)
|
||||
@ -711,6 +714,8 @@ const char *config_get_default_video(void)
|
||||
return "gl";
|
||||
case VIDEO_VULKAN:
|
||||
return "vulkan";
|
||||
case VIDEO_METAL:
|
||||
return "metal";
|
||||
case VIDEO_DRM:
|
||||
return "drm";
|
||||
case VIDEO_WII:
|
||||
@ -2357,6 +2362,7 @@ static bool check_shader_compatibility(enum file_path_enum enum_idx)
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (string_is_equal(settings->arrays.video_driver, "vulkan") ||
|
||||
string_is_equal(settings->arrays.video_driver, "metal") ||
|
||||
string_is_equal(settings->arrays.video_driver, "d3d11") ||
|
||||
string_is_equal(settings->arrays.video_driver, "d3d12") ||
|
||||
string_is_equal(settings->arrays.video_driver, "gx2"))
|
||||
|
@ -28,12 +28,14 @@ typedef struct
|
||||
@property (nonatomic, readonly) id<MTLDevice> device;
|
||||
@property (nonatomic, readonly) id<MTLLibrary> library;
|
||||
@property (nonatomic, readwrite) MTLClearColor clearColor;
|
||||
@property (nonatomic, readwrite) video_viewport_t *viewport;
|
||||
@property (nonatomic, readonly) Uniforms *uniforms;
|
||||
|
||||
/*! @brief Specifies whether rendering is synchronized with the display */
|
||||
@property (nonatomic, readwrite) bool displaySyncEnabled;
|
||||
|
||||
/*! @brief Returns the command buffer used for pre-render work,
|
||||
* such as mip maps for applying filters
|
||||
* such as mip maps and shader effects
|
||||
* */
|
||||
@property (nonatomic, readonly) id<MTLCommandBuffer> blitCommandBuffer;
|
||||
|
||||
@ -51,6 +53,14 @@ typedef struct
|
||||
- (Texture *)newTexture:(struct texture_image)image filter:(enum texture_filter_type)filter;
|
||||
- (id<MTLTexture>)newTexture:(struct texture_image)image mipmapped:(bool)mipmapped;
|
||||
- (void)convertFormat:(RPixelFormat)fmt from:(id<MTLBuffer>)src to:(id<MTLTexture>)dst;
|
||||
- (id<MTLRenderPipelineState>)getStockShader:(int)index blend:(bool)blend;
|
||||
|
||||
/*! @brief resets the viewport for the main render encoder to the drawable size */
|
||||
- (void)resetRenderViewport;
|
||||
|
||||
/*! @brief draws a quad at the specified position (normalized coordinates) using the main render encoder */
|
||||
- (void)drawQuadX:(float)x y:(float)y w:(float)w h:(float)h
|
||||
r:(float)r g:(float)g b:(float)b a:(float)a;
|
||||
|
||||
- (bool)allocRange:(BufferRange *)range length:(NSUInteger)length;
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
id<MTLCommandQueue> _commandQueue;
|
||||
CAMetalLayer *_layer;
|
||||
id<CAMetalDrawable> _drawable;
|
||||
video_viewport_t _viewport;
|
||||
id<MTLSamplerState> _samplers[TEXTURE_FILTER_MIPMAP_NEAREST + 1];
|
||||
Filter *_filters[RPixelFormatCount]; // convert to bgra8888
|
||||
|
||||
@ -49,6 +50,10 @@
|
||||
NSUInteger _currentChain;
|
||||
BufferChain *_chain[CHAIN_LENGTH];
|
||||
MTLClearColor _clearColor;
|
||||
|
||||
id<MTLRenderPipelineState> _states[GFX_MAX_SHADERS][2];
|
||||
id<MTLRenderPipelineState> _clearState;
|
||||
Uniforms _uniforms;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDevice:(id<MTLDevice>)d
|
||||
@ -64,6 +69,7 @@
|
||||
_library = l;
|
||||
_commandQueue = [_device newCommandQueue];
|
||||
_clearColor = MTLClearColorMake(0, 0, 0, 1);
|
||||
_uniforms.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
|
||||
|
||||
{
|
||||
MTLSamplerDescriptor *sd = [MTLSamplerDescriptor new];
|
||||
@ -89,7 +95,10 @@
|
||||
if (![self _initConversionFilters])
|
||||
return nil;
|
||||
|
||||
if (![self _initMainState])
|
||||
if (![self _initClearState])
|
||||
return nil;
|
||||
|
||||
if (![self _initMenuStates])
|
||||
return nil;
|
||||
|
||||
for (int i = 0; i < CHAIN_LENGTH; i++)
|
||||
@ -100,21 +109,241 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (video_viewport_t *)viewport
|
||||
{
|
||||
return &_viewport;
|
||||
}
|
||||
|
||||
- (void)setViewport:(video_viewport_t *)viewport
|
||||
{
|
||||
_viewport = *viewport;
|
||||
_uniforms.outputSize = simd_make_float2(_viewport.full_width, _viewport.full_height);
|
||||
}
|
||||
|
||||
- (Uniforms *)uniforms
|
||||
{
|
||||
return &_uniforms;
|
||||
}
|
||||
|
||||
- (void)setDisplaySyncEnabled:(bool)displaySyncEnabled
|
||||
{
|
||||
_layer.displaySyncEnabled = displaySyncEnabled;
|
||||
}
|
||||
|
||||
#pragma mark - shaders
|
||||
|
||||
- (id<MTLRenderPipelineState>)getStockShader:(int)index blend:(bool)blend
|
||||
{
|
||||
assert(index > 0 && index < GFX_MAX_SHADERS);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case VIDEO_SHADER_STOCK_BLEND:
|
||||
case VIDEO_SHADER_MENU:
|
||||
case VIDEO_SHADER_MENU_2:
|
||||
case VIDEO_SHADER_MENU_3:
|
||||
case VIDEO_SHADER_MENU_4:
|
||||
case VIDEO_SHADER_MENU_5:
|
||||
case VIDEO_SHADER_MENU_6:
|
||||
break;
|
||||
default:
|
||||
index = VIDEO_SHADER_STOCK_BLEND;
|
||||
break;
|
||||
}
|
||||
|
||||
return _states[index][blend ? 1 : 0];
|
||||
}
|
||||
|
||||
- (bool)displaySyncEnabled
|
||||
{
|
||||
return _layer.displaySyncEnabled;
|
||||
}
|
||||
|
||||
- (bool)_initMainState
|
||||
- (MTLVertexDescriptor *)_spriteVertexDescriptor
|
||||
{
|
||||
MTLVertexDescriptor *vd = [MTLVertexDescriptor new];
|
||||
vd.attributes[0].offset = 0;
|
||||
vd.attributes[0].format = MTLVertexFormatFloat2;
|
||||
vd.attributes[1].offset = offsetof(SpriteVertex, texCoord);
|
||||
vd.attributes[1].format = MTLVertexFormatFloat2;
|
||||
vd.attributes[2].offset = offsetof(SpriteVertex, color);
|
||||
vd.attributes[2].format = MTLVertexFormatFloat4;
|
||||
vd.layouts[0].stride = sizeof(SpriteVertex);
|
||||
return vd;
|
||||
}
|
||||
|
||||
- (bool)_initClearState
|
||||
{
|
||||
MTLVertexDescriptor *vd = [self _spriteVertexDescriptor];
|
||||
MTLRenderPipelineDescriptor *psd = [MTLRenderPipelineDescriptor new];
|
||||
psd.label = @"clear_state";
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *ca = psd.colorAttachments[0];
|
||||
ca.pixelFormat = _layer.pixelFormat;
|
||||
|
||||
psd.vertexDescriptor = vd;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"stock_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"stock_fragment_color"];
|
||||
|
||||
NSError *err;
|
||||
_clearState = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating clear pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (bool)_initMenuStates
|
||||
{
|
||||
MTLVertexDescriptor *vd = [self _spriteVertexDescriptor];
|
||||
MTLRenderPipelineDescriptor *psd = [MTLRenderPipelineDescriptor new];
|
||||
psd.label = @"stock";
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *ca = psd.colorAttachments[0];
|
||||
ca.pixelFormat = _layer.pixelFormat;
|
||||
ca.blendingEnabled = NO;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
|
||||
ca.destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
ca.sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
|
||||
ca.destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
|
||||
psd.sampleCount = 1;
|
||||
psd.vertexDescriptor = vd;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"stock_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"stock_fragment"];
|
||||
|
||||
NSError *err;
|
||||
_states[VIDEO_SHADER_STOCK_BLEND][0] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"stock_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
_states[VIDEO_SHADER_STOCK_BLEND][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
MTLFunctionConstantValues *vals;
|
||||
|
||||
psd.label = @"snow_simple";
|
||||
ca.blendingEnabled = YES;
|
||||
{
|
||||
vals = [MTLFunctionConstantValues new];
|
||||
float values[3] = {
|
||||
1.25f, // baseScale
|
||||
0.50f, // density
|
||||
0.15f, // speed
|
||||
};
|
||||
[vals setConstantValue:&values[0] type:MTLDataTypeFloat withName:@"snowBaseScale"];
|
||||
[vals setConstantValue:&values[1] type:MTLDataTypeFloat withName:@"snowDensity"];
|
||||
[vals setConstantValue:&values[2] type:MTLDataTypeFloat withName:@"snowSpeed"];
|
||||
}
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"snow_fragment" constantValues:vals error:&err];
|
||||
_states[VIDEO_SHADER_MENU_3][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"snow";
|
||||
ca.blendingEnabled = YES;
|
||||
{
|
||||
vals = [MTLFunctionConstantValues new];
|
||||
float values[3] = {
|
||||
3.50f, // baseScale
|
||||
0.70f, // density
|
||||
0.25f, // speed
|
||||
};
|
||||
[vals setConstantValue:&values[0] type:MTLDataTypeFloat withName:@"snowBaseScale"];
|
||||
[vals setConstantValue:&values[1] type:MTLDataTypeFloat withName:@"snowDensity"];
|
||||
[vals setConstantValue:&values[2] type:MTLDataTypeFloat withName:@"snowSpeed"];
|
||||
}
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"snow_fragment" constantValues:vals error:&err];
|
||||
_states[VIDEO_SHADER_MENU_4][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"bokeh";
|
||||
ca.blendingEnabled = YES;
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"bokeh_fragment"];
|
||||
_states[VIDEO_SHADER_MENU_5][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"snowflake";
|
||||
ca.blendingEnabled = YES;
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"snowflake_fragment"];
|
||||
_states[VIDEO_SHADER_MENU_6][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon";
|
||||
ca.blendingEnabled = NO;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"ribbon_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"ribbon_fragment"];
|
||||
_states[VIDEO_SHADER_MENU][0] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
ca.destinationRGBBlendFactor = MTLBlendFactorOne;
|
||||
_states[VIDEO_SHADER_MENU][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon_simple";
|
||||
ca.blendingEnabled = NO;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"ribbon_simple_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"ribbon_simple_fragment"];
|
||||
_states[VIDEO_SHADER_MENU_2][0] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon_simple_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
ca.destinationRGBBlendFactor = MTLBlendFactorOne;
|
||||
_states[VIDEO_SHADER_MENU_2][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (bool)_initConversionFilters
|
||||
{
|
||||
NSError *err = nil;
|
||||
@ -255,6 +484,41 @@
|
||||
return _rce;
|
||||
}
|
||||
|
||||
- (void)resetRenderViewport
|
||||
{
|
||||
MTLViewport vp = {
|
||||
.originX = 0,
|
||||
.originY = 0,
|
||||
.width = _viewport.full_width,
|
||||
.height = _viewport.full_height,
|
||||
.znear = 0,
|
||||
.zfar = 1,
|
||||
};
|
||||
[self.rce setViewport:vp];
|
||||
}
|
||||
|
||||
- (void)drawQuadX:(float)x y:(float)y w:(float)w h:(float)h
|
||||
r:(float)r g:(float)g b:(float)b a:(float)a
|
||||
{
|
||||
SpriteVertex v[4];
|
||||
v[0].position = simd_make_float2(x, y);
|
||||
v[1].position = simd_make_float2(x + w, y);
|
||||
v[2].position = simd_make_float2(x, y + h);
|
||||
v[3].position = simd_make_float2(x + w, y + h);
|
||||
|
||||
simd_float4 color = simd_make_float4(r, g, b, a);
|
||||
v[0].color = color;
|
||||
v[1].color = color;
|
||||
v[2].color = color;
|
||||
v[3].color = color;
|
||||
|
||||
id<MTLRenderCommandEncoder> rce = self.rce;
|
||||
[rce setRenderPipelineState:_clearState];
|
||||
[rce setVertexBytes:&v length:sizeof(v) atIndex:BufferIndexPositions];
|
||||
[rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms];
|
||||
[rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4];
|
||||
}
|
||||
|
||||
- (void)end
|
||||
{
|
||||
assert(_commandBuffer != nil);
|
||||
@ -263,7 +527,7 @@
|
||||
|
||||
if (_blitCommandBuffer)
|
||||
{
|
||||
// pending blits for mipmaps
|
||||
// pending blits for mipmaps or render passes for slang shaders
|
||||
[_blitCommandBuffer commit];
|
||||
[_blitCommandBuffer waitUntilCompleted];
|
||||
_blitCommandBuffer = nil;
|
||||
|
@ -3,17 +3,15 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ShaderTypes.h"
|
||||
|
||||
@class Context;
|
||||
@class MetalDriver;
|
||||
|
||||
@interface MenuDisplay : NSObject
|
||||
|
||||
@property (nonatomic, readwrite) BOOL blend;
|
||||
@property (nonatomic, readwrite) MTLClearColor clearColor;
|
||||
|
||||
- (instancetype)initWithDriver:(MetalDriver *)driver;
|
||||
- (instancetype)initWithContext:(Context *)context;
|
||||
- (void)drawPipeline:(menu_display_ctx_draw_t *)draw video:(video_frame_info_t *)video;
|
||||
- (void)draw:(menu_display_ctx_draw_t *)draw video:(video_frame_info_t *)video;
|
||||
|
||||
@ -23,5 +21,4 @@
|
||||
+ (const float *)defaultTexCoords;
|
||||
+ (const float *)defaultColor;
|
||||
|
||||
|
||||
@end
|
||||
|
@ -12,19 +12,17 @@
|
||||
|
||||
@implementation MenuDisplay
|
||||
{
|
||||
__weak MetalDriver *_driver;
|
||||
Context *_context;
|
||||
MTLClearColor _clearColor;
|
||||
bool _clearNextRender;
|
||||
Uniforms _uniforms;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDriver:(MetalDriver *)driver
|
||||
- (instancetype)initWithContext:(Context *)context
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_driver = driver;
|
||||
_context = driver.context;
|
||||
_context = context;
|
||||
_clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 1.0);
|
||||
_uniforms.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
|
||||
}
|
||||
@ -45,10 +43,10 @@
|
||||
+ (const float *)defaultTexCoords
|
||||
{
|
||||
static float dummy[] = {
|
||||
0.0f, 0.0f,
|
||||
1.0f, 0.0f,
|
||||
0.0f, 1.0f,
|
||||
1.0f, 1.0f,
|
||||
0.0f, 0.0f,
|
||||
1.0f, 0.0f,
|
||||
};
|
||||
return &dummy[0];
|
||||
}
|
||||
@ -97,7 +95,7 @@
|
||||
draw->y = 0;
|
||||
draw->matrix_data = NULL;
|
||||
|
||||
_uniforms.outputSize = simd_make_float2(_driver.viewport->full_width, _driver.viewport->full_height);
|
||||
_uniforms.outputSize = simd_make_float2(_context.viewport->full_width, _context.viewport->full_height);
|
||||
|
||||
draw->pipeline.backend_data = &_uniforms;
|
||||
draw->pipeline.backend_data_size = sizeof(_uniforms);
|
||||
@ -147,7 +145,7 @@
|
||||
SpriteVertex *pv = (SpriteVertex *)range.data;
|
||||
for (unsigned i = 0; i < draw->coords->vertices; i++, pv++)
|
||||
{
|
||||
pv->position = simd_make_float2(vertex[0], 1.0f - vertex[1]);
|
||||
pv->position = simd_make_float2(vertex[0], vertex[1]);
|
||||
vertex += 2;
|
||||
|
||||
pv->texCoord = simd_make_float2(tex_coord[0], tex_coord[1]);
|
||||
@ -158,9 +156,24 @@
|
||||
}
|
||||
|
||||
id<MTLRenderCommandEncoder> rce = _context.rce;
|
||||
if (_clearNextRender)
|
||||
{
|
||||
[_context resetRenderViewport];
|
||||
[_context drawQuadX:0
|
||||
y:0
|
||||
w:1
|
||||
h:1
|
||||
r:(float)_clearColor.red
|
||||
g:(float)_clearColor.green
|
||||
b:(float)_clearColor.blue
|
||||
a:(float)_clearColor.alpha
|
||||
];
|
||||
_clearNextRender = NO;
|
||||
}
|
||||
|
||||
MTLViewport vp = {
|
||||
.originX = draw->x,
|
||||
.originY = _driver.viewport->full_height - draw->y - draw->height,
|
||||
.originY = _context.viewport->full_height - draw->y - draw->height,
|
||||
.width = draw->width,
|
||||
.height = draw->height,
|
||||
.znear = 0,
|
||||
@ -177,7 +190,7 @@
|
||||
case VIDEO_SHADER_MENU_4:
|
||||
case VIDEO_SHADER_MENU_5:
|
||||
case VIDEO_SHADER_MENU_6:
|
||||
[rce setRenderPipelineState:[_driver getStockShader:draw->pipeline.id blend:_blend]];
|
||||
[rce setRenderPipelineState:[_context getStockShader:draw->pipeline.id blend:_blend]];
|
||||
[rce setVertexBytes:draw->pipeline.backend_data length:draw->pipeline.backend_data_size atIndex:BufferIndexUniforms];
|
||||
[rce setVertexBuffer:range.buffer offset:range.offset atIndex:BufferIndexPositions];
|
||||
[rce setFragmentBytes:draw->pipeline.backend_data length:draw->pipeline.backend_data_size atIndex:BufferIndexUniforms];
|
||||
@ -192,13 +205,7 @@
|
||||
if (tex == nil)
|
||||
return;
|
||||
|
||||
if (_clearNextRender)
|
||||
{
|
||||
// TODO(sgc): draw quad to clear
|
||||
_clearNextRender = NO;
|
||||
}
|
||||
|
||||
[rce setRenderPipelineState:[_driver getStockShader:VIDEO_SHADER_STOCK_BLEND blend:_blend]];
|
||||
[rce setRenderPipelineState:[_context getStockShader:VIDEO_SHADER_STOCK_BLEND blend:_blend]];
|
||||
|
||||
Uniforms uniforms = {
|
||||
.projectionMatrix = draw->matrix_data ? make_matrix_float4x4((const float *)draw->matrix_data)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define RendererCommon_h
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "ShaderTypes.h"
|
||||
|
||||
// TODO(sgc): implement triple buffering
|
||||
/*! @brief maximum inflight frames */
|
||||
|
@ -55,11 +55,11 @@ NSString *NSStringFromRPixelFormat(RPixelFormat format)
|
||||
matrix_float4x4 make_matrix_float4x4(const float *v)
|
||||
{
|
||||
simd_float4 P = simd_make_float4(v[0], v[1], v[2], v[3]);
|
||||
v+=4;
|
||||
v += 4;
|
||||
simd_float4 Q = simd_make_float4(v[0], v[1], v[2], v[3]);
|
||||
v+=4;
|
||||
v += 4;
|
||||
simd_float4 R = simd_make_float4(v[0], v[1], v[2], v[3]);
|
||||
v+=4;
|
||||
v += 4;
|
||||
simd_float4 S = simd_make_float4(v[0], v[1], v[2], v[3]);
|
||||
|
||||
matrix_float4x4 mat = {P, Q, R, S};
|
||||
|
@ -74,6 +74,11 @@ fragment float4 stock_fragment(FontFragmentIn in [[ stage_in ]],
|
||||
return colorSample * in.color;
|
||||
}
|
||||
|
||||
fragment half4 stock_fragment_color(FontFragmentIn in [[ stage_in ]])
|
||||
{
|
||||
return half4(in.color);
|
||||
}
|
||||
|
||||
#pragma mark - filter kernels
|
||||
|
||||
kernel void convert_bgra4444_to_bgra8888(device uint16_t * in [[ buffer(0) ]],
|
||||
|
@ -7,8 +7,6 @@
|
||||
#import "View.h"
|
||||
#import "Filter.h"
|
||||
|
||||
#import "ShaderTypes.h"
|
||||
|
||||
@implementation TexturedView
|
||||
{
|
||||
Context *_context;
|
||||
|
@ -79,7 +79,6 @@ extern MTLPixelFormat SelectOptimalPixelFormat(MTLPixelFormat fmt);
|
||||
@property (nonatomic, readonly) Overlay *overlay;
|
||||
@property (nonatomic, readonly) Context *context;
|
||||
@property (nonatomic, readonly) Uniforms *viewportMVP;
|
||||
@property (nonatomic, readonly) Uniforms *viewportMVPNormalized;
|
||||
|
||||
- (instancetype)initWithVideo:(const video_info_t *)video
|
||||
input:(const input_driver_t **)input
|
||||
@ -94,8 +93,6 @@ extern MTLPixelFormat SelectOptimalPixelFormat(MTLPixelFormat fmt);
|
||||
msg:(const char *)msg
|
||||
info:(video_frame_info_t *)video_info;
|
||||
|
||||
- (id<MTLRenderPipelineState>)getStockShader:(int)index blend:(bool)blend;
|
||||
|
||||
/*! @brief setNeedsResize triggers a display resize */
|
||||
- (void)setNeedsResize;
|
||||
|
||||
|
@ -71,13 +71,9 @@
|
||||
id<MTLSamplerState> _samplerStateLinear;
|
||||
id<MTLSamplerState> _samplerStateNearest;
|
||||
|
||||
//
|
||||
id<MTLRenderPipelineState> _states[GFX_MAX_SHADERS][2];
|
||||
|
||||
// other state
|
||||
Uniforms _uniforms;
|
||||
Uniforms _viewportMVP;
|
||||
Uniforms _viewportMVPNormalized;
|
||||
}
|
||||
|
||||
- (instancetype)initWithVideo:(const video_info_t *)video
|
||||
@ -97,13 +93,9 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (![self _initStates])
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
_video = *video;
|
||||
_viewport = (video_viewport_t *)calloc(1, sizeof(video_viewport_t));
|
||||
_viewportMVP.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
|
||||
|
||||
_keepAspect = _video.force_aspect;
|
||||
|
||||
@ -118,7 +110,7 @@
|
||||
*inputData = NULL;
|
||||
|
||||
// menu display
|
||||
_display = [[MenuDisplay alloc] initWithDriver:self];
|
||||
_display = [[MenuDisplay alloc] initWithContext:_context];
|
||||
|
||||
// menu view
|
||||
_menu = [[MetalMenu alloc] initWithContext:_context];
|
||||
@ -214,162 +206,6 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (bool)_initStates
|
||||
{
|
||||
MTLVertexDescriptor *vd = [MTLVertexDescriptor new];
|
||||
vd.attributes[0].offset = 0;
|
||||
vd.attributes[0].format = MTLVertexFormatFloat2;
|
||||
vd.attributes[1].offset = offsetof(SpriteVertex, texCoord);
|
||||
vd.attributes[1].format = MTLVertexFormatFloat2;
|
||||
vd.attributes[2].offset = offsetof(SpriteVertex, color);
|
||||
vd.attributes[2].format = MTLVertexFormatFloat4;
|
||||
vd.layouts[0].stride = sizeof(SpriteVertex);
|
||||
|
||||
{
|
||||
MTLRenderPipelineDescriptor *psd = [MTLRenderPipelineDescriptor new];
|
||||
psd.label = @"stock";
|
||||
|
||||
MTLRenderPipelineColorAttachmentDescriptor *ca = psd.colorAttachments[0];
|
||||
ca.pixelFormat = _layer.pixelFormat;
|
||||
ca.blendingEnabled = NO;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
|
||||
ca.destinationRGBBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
ca.sourceAlphaBlendFactor = MTLBlendFactorSourceAlpha;
|
||||
ca.destinationAlphaBlendFactor = MTLBlendFactorOneMinusSourceAlpha;
|
||||
|
||||
psd.sampleCount = 1;
|
||||
psd.vertexDescriptor = vd;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"stock_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"stock_fragment"];
|
||||
|
||||
NSError *err;
|
||||
_states[VIDEO_SHADER_STOCK_BLEND][0] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"stock_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
_states[VIDEO_SHADER_STOCK_BLEND][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
MTLFunctionConstantValues *vals;
|
||||
|
||||
psd.label = @"snow_simple";
|
||||
ca.blendingEnabled = YES;
|
||||
{
|
||||
vals = [MTLFunctionConstantValues new];
|
||||
float values[3] = {
|
||||
1.25f, // baseScale
|
||||
0.50f, // density
|
||||
0.15f, // speed
|
||||
};
|
||||
[vals setConstantValue:&values[0] type:MTLDataTypeFloat withName:@"snowBaseScale"];
|
||||
[vals setConstantValue:&values[1] type:MTLDataTypeFloat withName:@"snowDensity"];
|
||||
[vals setConstantValue:&values[2] type:MTLDataTypeFloat withName:@"snowSpeed"];
|
||||
}
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"snow_fragment" constantValues:vals error:&err];
|
||||
_states[VIDEO_SHADER_MENU_3][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"snow";
|
||||
ca.blendingEnabled = YES;
|
||||
{
|
||||
vals = [MTLFunctionConstantValues new];
|
||||
float values[3] = {
|
||||
3.50f, // baseScale
|
||||
0.70f, // density
|
||||
0.25f, // speed
|
||||
};
|
||||
[vals setConstantValue:&values[0] type:MTLDataTypeFloat withName:@"snowBaseScale"];
|
||||
[vals setConstantValue:&values[1] type:MTLDataTypeFloat withName:@"snowDensity"];
|
||||
[vals setConstantValue:&values[2] type:MTLDataTypeFloat withName:@"snowSpeed"];
|
||||
}
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"snow_fragment" constantValues:vals error:&err];
|
||||
_states[VIDEO_SHADER_MENU_4][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"bokeh";
|
||||
ca.blendingEnabled = YES;
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"bokeh_fragment"];
|
||||
_states[VIDEO_SHADER_MENU_5][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"snowflake";
|
||||
ca.blendingEnabled = YES;
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"snowflake_fragment"];
|
||||
_states[VIDEO_SHADER_MENU_6][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon";
|
||||
ca.blendingEnabled = NO;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"ribbon_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"ribbon_fragment"];
|
||||
_states[VIDEO_SHADER_MENU][0] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
ca.destinationRGBBlendFactor = MTLBlendFactorOne;
|
||||
_states[VIDEO_SHADER_MENU][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon_simple";
|
||||
ca.blendingEnabled = NO;
|
||||
psd.vertexFunction = [_library newFunctionWithName:@"ribbon_simple_vertex"];
|
||||
psd.fragmentFunction = [_library newFunctionWithName:@"ribbon_simple_fragment"];
|
||||
_states[VIDEO_SHADER_MENU_2][0] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
|
||||
psd.label = @"ribbon_simple_blend";
|
||||
ca.blendingEnabled = YES;
|
||||
ca.sourceRGBBlendFactor = MTLBlendFactorOne;
|
||||
ca.destinationRGBBlendFactor = MTLBlendFactorOne;
|
||||
_states[VIDEO_SHADER_MENU_2][1] = [_device newRenderPipelineStateWithDescriptor:psd error:&err];
|
||||
if (err != nil)
|
||||
{
|
||||
RARCH_ERR("[Metal]: error creating pipeline state %s\n", err.localizedDescription.UTF8String);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)_updateUniforms
|
||||
{
|
||||
_uniforms.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
|
||||
@ -383,36 +219,9 @@
|
||||
_layer.drawableSize = size;
|
||||
video_driver_update_viewport(_viewport, NO, _keepAspect);
|
||||
|
||||
_context.viewport = _viewport;
|
||||
|
||||
_viewportMVP.outputSize = simd_make_float2(_viewport->full_width, _viewport->full_height);
|
||||
_viewportMVP.projectionMatrix = matrix_proj_ortho(0, _viewport->full_width, _viewport->full_height, 0);
|
||||
_viewportMVP.projectionMatrix = matrix_proj_ortho(0, _viewport->full_width, 0, _viewport->full_height);
|
||||
|
||||
_viewportMVPNormalized.outputSize = simd_make_float2(_viewport->full_width, _viewport->full_height);
|
||||
_viewportMVPNormalized.projectionMatrix = matrix_proj_ortho(0, 1, 0, 1);
|
||||
}
|
||||
|
||||
#pragma mark - shaders
|
||||
|
||||
- (id<MTLRenderPipelineState>)getStockShader:(int)index blend:(bool)blend
|
||||
{
|
||||
assert(index > 0 && index < GFX_MAX_SHADERS);
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case VIDEO_SHADER_STOCK_BLEND:
|
||||
case VIDEO_SHADER_MENU:
|
||||
case VIDEO_SHADER_MENU_2:
|
||||
case VIDEO_SHADER_MENU_3:
|
||||
case VIDEO_SHADER_MENU_4:
|
||||
case VIDEO_SHADER_MENU_5:
|
||||
case VIDEO_SHADER_MENU_6:
|
||||
break;
|
||||
default:
|
||||
index = VIDEO_SHADER_STOCK_BLEND;
|
||||
break;
|
||||
}
|
||||
|
||||
return _states[index][blend ? 1 : 0];
|
||||
}
|
||||
|
||||
#pragma mark - video
|
||||
@ -455,7 +264,7 @@
|
||||
{
|
||||
id<MTLRenderCommandEncoder> rce = _context.rce;
|
||||
[rce pushDebugGroup:@"overlay"];
|
||||
[rce setRenderPipelineState:[self getStockShader:VIDEO_SHADER_STOCK_BLEND blend:YES]];
|
||||
[rce setRenderPipelineState:[_context getStockShader:VIDEO_SHADER_STOCK_BLEND blend:YES]];
|
||||
[rce setVertexBytes:&_uniforms length:sizeof(_uniforms) atIndex:BufferIndexUniforms];
|
||||
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
|
||||
[_overlay drawWithEncoder:rce];
|
||||
@ -464,9 +273,7 @@
|
||||
#endif
|
||||
|
||||
if (msg && *msg)
|
||||
{
|
||||
font_driver_render_msg(video_info, NULL, msg, NULL);
|
||||
}
|
||||
[self _renderMessage:msg info:video_info];
|
||||
|
||||
[self _endFrame];
|
||||
}
|
||||
@ -474,6 +281,43 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)_renderMessage:(const char *)msg
|
||||
info:(video_frame_info_t *)video_info
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
if (settings && settings->bools.video_msg_bgcolor_enable)
|
||||
{
|
||||
int msg_width =
|
||||
font_driver_get_message_width(NULL, msg, (unsigned)strlen(msg), 1.0f);
|
||||
|
||||
float x = video_info->font_msg_pos_x;
|
||||
float y = 1.0f - video_info->font_msg_pos_y;
|
||||
float width = msg_width / (float)_viewport->full_width;
|
||||
float height =
|
||||
settings->floats.video_font_size / (float)_viewport->full_height;
|
||||
|
||||
y -= height;
|
||||
|
||||
|
||||
float x2 = 0.005f; /* extend background around text */
|
||||
float y2 = 0.005f;
|
||||
|
||||
x -= x2;
|
||||
y -= y2;
|
||||
width += x2;
|
||||
height += y2;
|
||||
|
||||
float r = settings->uints.video_msg_bgcolor_red / 255.0f;
|
||||
float g = settings->uints.video_msg_bgcolor_green / 255.0f;
|
||||
float b = settings->uints.video_msg_bgcolor_blue / 255.0f;
|
||||
float a = settings->floats.video_msg_bgcolor_opacity;
|
||||
[_context resetRenderViewport];
|
||||
[_context drawQuadX:x y:y w:width h:height r:r g:g b:b a:a];
|
||||
}
|
||||
|
||||
font_driver_render_msg(video_info, NULL, msg, NULL);
|
||||
}
|
||||
|
||||
- (void)_beginFrame
|
||||
{
|
||||
video_driver_update_viewport(_viewport, NO, _keepAspect);
|
||||
@ -555,11 +399,6 @@
|
||||
return &_viewportMVP;
|
||||
}
|
||||
|
||||
- (Uniforms *)viewportMVPNormalized
|
||||
{
|
||||
return &_viewportMVPNormalized;
|
||||
}
|
||||
|
||||
#pragma mark - MTKViewDelegate
|
||||
|
||||
- (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size
|
||||
|
@ -196,14 +196,6 @@ static void metal_set_video_mode(void *data,
|
||||
RARCH_LOG("[Metal]: set_video_mode res=%dx%d fullscreen=%s\n",
|
||||
width, height,
|
||||
fullscreen ? "YES" : "NO");
|
||||
MetalDriver *md = (__bridge MetalDriver *)data;
|
||||
gfx_ctx_mode_t mode = {
|
||||
.width = width,
|
||||
.height = height,
|
||||
.fullscreen = fullscreen,
|
||||
};
|
||||
|
||||
//[md setVideoMode:mode];
|
||||
}
|
||||
|
||||
static float metal_get_refresh_rate(void *data)
|
||||
|
@ -323,17 +323,8 @@ static INLINE void write_quad6(SpriteVertex *pv,
|
||||
|
||||
id<MTLRenderCommandEncoder> rce = _context.rce;
|
||||
[rce pushDebugGroup:@"render fonts"];
|
||||
|
||||
MTLViewport vp = {
|
||||
.originX = 0,
|
||||
.originY = 0,
|
||||
.width = _driver.viewport->full_width,
|
||||
.height = _driver.viewport->full_height,
|
||||
.znear = 0,
|
||||
.zfar = 1,
|
||||
};
|
||||
[rce setViewport:vp];
|
||||
|
||||
|
||||
[_context resetRenderViewport];
|
||||
[rce setRenderPipelineState:_state];
|
||||
[rce setVertexBytes:&_uniforms length:sizeof(Uniforms) atIndex:BufferIndexUniforms];
|
||||
[rce setVertexBuffer:_vert offset:start atIndex:BufferIndexPositions];
|
||||
|
@ -1235,7 +1235,7 @@ MENU
|
||||
#include "../menu/drivers/rgui.c"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_VITA2D) || defined(_3DS) || defined(_MSC_VER) || defined(__wiiu__)
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_VITA2D) || defined(_3DS) || defined(_MSC_VER) || defined(__wiiu__) || defined(HAVE_METAL)
|
||||
#ifdef HAVE_XMB
|
||||
#include "../menu/drivers/xmb.c"
|
||||
#endif
|
||||
|
@ -921,7 +921,12 @@ void fill_pathname_join_noext(char *out_path,
|
||||
void fill_pathname_join_delim(char *out_path, const char *dir,
|
||||
const char *path, const char delim, size_t size)
|
||||
{
|
||||
size_t copied = strlcpy(out_path, dir, size);
|
||||
size_t copied;
|
||||
// behavior of strlcpy is undefined if dst and src overlap
|
||||
if (out_path == dir)
|
||||
copied = strlen(dir);
|
||||
else
|
||||
copied = strlcpy(out_path, dir, size);
|
||||
|
||||
out_path[copied] = delim;
|
||||
out_path[copied+1] = '\0';
|
||||
|
@ -35,7 +35,7 @@ static void *menu_display_metal_get_default_mvp(video_frame_info_t *video_info)
|
||||
if (!md)
|
||||
return NULL;
|
||||
|
||||
return (void *)&md.viewportMVPNormalized->projectionMatrix;
|
||||
return (void *)&md.viewportMVP->projectionMatrix;
|
||||
}
|
||||
|
||||
static void menu_display_metal_blend_begin(video_frame_info_t *video_info)
|
||||
|
@ -4,6 +4,7 @@
|
||||
<option name="INDENT_C_STRUCT_MEMBERS" value="3" />
|
||||
<option name="INDENT_CLASS_MEMBERS" value="3" />
|
||||
<option name="INDENT_INSIDE_CODE_BLOCK" value="3" />
|
||||
<option name="METHOD_BRACE_PLACEMENT" value="2" />
|
||||
<option name="FUNCTION_BRACE_PLACEMENT" value="2" />
|
||||
<option name="FUNCTION_NON_TOP_AFTER_RETURN_TYPE_WRAP" value="1" />
|
||||
<option name="FUNCTION_TOP_AFTER_RETURN_TYPE_WRAP" value="1" />
|
||||
@ -46,14 +47,15 @@
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
<codeStyleSettings language="ObjectiveC">
|
||||
<option name="BLANK_LINES_BEFORE_IMPORTS" value="0" />
|
||||
<option name="BLANK_LINES_AFTER_IMPORTS" value="0" />
|
||||
<option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" />
|
||||
<option name="BRACE_STYLE" value="2" />
|
||||
<option name="CLASS_BRACE_STYLE" value="2" />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
|
||||
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
|
||||
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
|
||||
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
|
||||
<option name="SPACE_WITHIN_BRACES" value="true" />
|
||||
<option name="SPACE_AFTER_TYPE_CAST" value="false" />
|
||||
<option name="BINARY_OPERATION_WRAP" value="1" />
|
||||
@ -67,6 +69,8 @@
|
||||
<option name="INDENT_SIZE" value="3" />
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="3" />
|
||||
<option name="TAB_SIZE" value="3" />
|
||||
<option name="LABEL_INDENT_ABSOLUTE" value="true" />
|
||||
<option name="KEEP_INDENTS_ON_EMPTY_LINES" value="true" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
@ -428,6 +428,25 @@
|
||||
05D7753120A55D2700646447 /* BaseConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = BaseConfig.xcconfig; sourceTree = "<group>"; };
|
||||
05D7753320A5678300646447 /* griffin_cpp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = griffin_cpp.cpp; path = ../../griffin/griffin_cpp.cpp; sourceTree = "<group>"; };
|
||||
05D7753420A5678400646447 /* griffin_glslang.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = griffin_glslang.cpp; path = ../../griffin/griffin_glslang.cpp; sourceTree = "<group>"; };
|
||||
05F2872F20F2BEEA00632D47 /* task_autodetect.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_autodetect.c; sourceTree = "<group>"; };
|
||||
05F2873020F2BEEA00632D47 /* task_netplay_find_content.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_netplay_find_content.c; sourceTree = "<group>"; };
|
||||
05F2873120F2BEEA00632D47 /* task_netplay_nat_traversal.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_netplay_nat_traversal.c; sourceTree = "<group>"; };
|
||||
05F2873220F2BEEA00632D47 /* task_screenshot.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_screenshot.c; sourceTree = "<group>"; };
|
||||
05F2873320F2BEEA00632D47 /* task_file_transfer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_file_transfer.c; sourceTree = "<group>"; };
|
||||
05F2873420F2BEEA00632D47 /* task_database.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_database.c; sourceTree = "<group>"; };
|
||||
05F2873520F2BEEA00632D47 /* task_save.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_save.c; sourceTree = "<group>"; };
|
||||
05F2873620F2BEEA00632D47 /* task_powerstate.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_powerstate.c; sourceTree = "<group>"; };
|
||||
05F2873720F2BEEA00632D47 /* task_image.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_image.c; sourceTree = "<group>"; };
|
||||
05F2873820F2BEEA00632D47 /* tasks_internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tasks_internal.h; sourceTree = "<group>"; };
|
||||
05F2873920F2BEEA00632D47 /* task_overlay.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_overlay.c; sourceTree = "<group>"; };
|
||||
05F2873A20F2BEEA00632D47 /* task_audio_mixer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_audio_mixer.c; sourceTree = "<group>"; };
|
||||
05F2873B20F2BEEA00632D47 /* task_decompress.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_decompress.c; sourceTree = "<group>"; };
|
||||
05F2873C20F2BEEA00632D47 /* task_netplay_lan_scan.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_netplay_lan_scan.c; sourceTree = "<group>"; };
|
||||
05F2873D20F2BEEA00632D47 /* task_wifi.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_wifi.c; sourceTree = "<group>"; };
|
||||
05F2873E20F2BEEA00632D47 /* task_database_cue.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_database_cue.c; sourceTree = "<group>"; };
|
||||
05F2873F20F2BEEA00632D47 /* task_content.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_content.c; sourceTree = "<group>"; };
|
||||
05F2874020F2BEEA00632D47 /* task_http.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_http.c; sourceTree = "<group>"; };
|
||||
05F2874120F2BEEA00632D47 /* task_patch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_patch.c; sourceTree = "<group>"; };
|
||||
05FA11A120CC6684008C5D0A /* MetalRenderer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MetalRenderer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
089C165DFE840E0CC02AAC07 /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = OSX/en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
1DDD58150DA1D0A300B32029 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = OSX/en.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
@ -563,6 +582,7 @@
|
||||
05A8C57120DB72F000FF7857 /* intl */,
|
||||
05C5D53220E3DD0900654EE4 /* input */,
|
||||
05A8C51A20DB72F000FF7857 /* menu */,
|
||||
05F2872E20F2BEEA00632D47 /* tasks */,
|
||||
05A8C5AD20DB72F000FF7857 /* ui */,
|
||||
);
|
||||
name = Sources;
|
||||
@ -1194,6 +1214,33 @@
|
||||
path = drivers_joypad;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
05F2872E20F2BEEA00632D47 /* tasks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05F2872F20F2BEEA00632D47 /* task_autodetect.c */,
|
||||
05F2873020F2BEEA00632D47 /* task_netplay_find_content.c */,
|
||||
05F2873120F2BEEA00632D47 /* task_netplay_nat_traversal.c */,
|
||||
05F2873220F2BEEA00632D47 /* task_screenshot.c */,
|
||||
05F2873320F2BEEA00632D47 /* task_file_transfer.c */,
|
||||
05F2873420F2BEEA00632D47 /* task_database.c */,
|
||||
05F2873520F2BEEA00632D47 /* task_save.c */,
|
||||
05F2873620F2BEEA00632D47 /* task_powerstate.c */,
|
||||
05F2873720F2BEEA00632D47 /* task_image.c */,
|
||||
05F2873820F2BEEA00632D47 /* tasks_internal.h */,
|
||||
05F2873920F2BEEA00632D47 /* task_overlay.c */,
|
||||
05F2873A20F2BEEA00632D47 /* task_audio_mixer.c */,
|
||||
05F2873B20F2BEEA00632D47 /* task_decompress.c */,
|
||||
05F2873C20F2BEEA00632D47 /* task_netplay_lan_scan.c */,
|
||||
05F2873D20F2BEEA00632D47 /* task_wifi.c */,
|
||||
05F2873E20F2BEEA00632D47 /* task_database_cue.c */,
|
||||
05F2873F20F2BEEA00632D47 /* task_content.c */,
|
||||
05F2874020F2BEEA00632D47 /* task_http.c */,
|
||||
05F2874120F2BEEA00632D47 /* task_patch.c */,
|
||||
);
|
||||
name = tasks;
|
||||
path = ../../tasks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
Loading…
x
Reference in New Issue
Block a user