From 93b79fac90523f3954212d3e17d2c323878c33a7 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 15 Jul 2018 15:54:36 -0700 Subject: [PATCH 001/335] fix(gfx): Move enum to end to avoid breaking existing configurations * `aspect_ratio_index` relies on the ordinal values not changing --- gfx/video_defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/video_defines.h b/gfx/video_defines.h index 61b09d393a..b3aa82ce43 100644 --- a/gfx/video_defines.h +++ b/gfx/video_defines.h @@ -35,7 +35,6 @@ enum aspect_ratio ASPECT_RATIO_16_9, ASPECT_RATIO_16_10, ASPECT_RATIO_16_15, - ASPECT_RATIO_21_9, ASPECT_RATIO_1_1, ASPECT_RATIO_2_1, ASPECT_RATIO_3_2, @@ -55,6 +54,7 @@ enum aspect_ratio ASPECT_RATIO_SQUARE, ASPECT_RATIO_CORE, ASPECT_RATIO_CUSTOM, + ASPECT_RATIO_21_9, ASPECT_RATIO_END }; From 1264e9c533fdb5c80aff9e7355dfb03eb741f8eb Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 15 Jul 2018 15:56:47 -0700 Subject: [PATCH 002/335] fix(Metal): Use ifdef syntax; add correct default for Metal build --- frontend/drivers/platform_darwin.m | 6 ++++++ ui/drivers/ui_cocoa.m | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/drivers/platform_darwin.m b/frontend/drivers/platform_darwin.m index e63bd59056..2e367ec0f7 100644 --- a/frontend/drivers/platform_darwin.m +++ b/frontend/drivers/platform_darwin.m @@ -347,9 +347,15 @@ static void frontend_darwin_get_environment_settings(int *argc, char *argv[], #endif strlcat(home_dir_buf, "/RetroArch", sizeof(home_dir_buf)); +#ifdef HAVE_METAL + fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SHADER], + home_dir_buf, "shaders_slang", + sizeof(g_defaults.dirs[DEFAULT_DIR_SHADER])); +#else fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_SHADER], home_dir_buf, "shaders_glsl", sizeof(g_defaults.dirs[DEFAULT_DIR_SHADER])); +#endif #if TARGET_OS_IPHONE int major, minor; get_ios_version(&major, &minor); diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index 05259411e0..bf66477fe6 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -37,7 +37,7 @@ #include "../../retroarch.h" #include "../../tasks/tasks_internal.h" -#if HAVE_METAL +#ifdef HAVE_METAL #import #import #endif From 577d81071eae21541359a3443d7993cb02601162 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 15 Jul 2018 15:58:23 -0700 Subject: [PATCH 003/335] fix(Metal): Cleanup shader logging messages --- gfx/common/metal_common.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gfx/common/metal_common.m b/gfx/common/metal_common.m index ad433da056..007f451abf 100644 --- a/gfx/common/metal_common.m +++ b/gfx/common/metal_common.m @@ -1204,7 +1204,7 @@ static vertex_t vertex_bytes[] = { if (lib == nil) { save_msl = true; - RARCH_ERR("Metal]: unable to compile vertex shader: %s\n", err.localizedDescription.UTF8String); + RARCH_ERR("[Metal]: unable to compile vertex shader: %s\n", err.localizedDescription.UTF8String); return NO; } #if DEBUG @@ -1220,7 +1220,7 @@ static vertex_t vertex_bytes[] = { if (lib == nil) { save_msl = true; - RARCH_ERR("Metal]: unable to compile fragment shader: %s\n", err.localizedDescription.UTF8String); + RARCH_ERR("[Metal]: unable to compile fragment shader: %s\n", err.localizedDescription.UTF8String); return NO; } #if DEBUG @@ -1234,7 +1234,8 @@ static vertex_t vertex_bytes[] = { if (err != nil) { save_msl = true; - RARCH_ERR("error creating pipeline state: %s", err.localizedDescription.UTF8String); + RARCH_ERR("[Metal]: error creating pipeline state for pass %d: %s\n", i, + err.localizedDescription.UTF8String); return NO; } @@ -1253,10 +1254,11 @@ static vertex_t vertex_bytes[] = { { if (save_msl) { - RARCH_LOG("[Metal]: saving metal shader files\n"); + NSString *basePath = [[NSString stringWithUTF8String:shader->pass[i].source.path] stringByDeletingPathExtension]; + + RARCH_LOG("[Metal]: saving metal shader files to %s\n", basePath.UTF8String); NSError *err = nil; - NSString *basePath = [[NSString stringWithUTF8String:shader->pass[i].source.path] stringByDeletingPathExtension]; [vs_src writeToFile:[basePath stringByAppendingPathExtension:@"vs.metal"] atomically:NO encoding:NSStringEncodingConversionAllowLossy From 802697fdecfd767f87deaa4e29d31fcbc0b66a7c Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Tue, 17 Jul 2018 20:59:06 -0700 Subject: [PATCH 004/335] fix(Metal): Use textures for pixel conversion --- gfx/common/metal/Context.h | 2 +- gfx/common/metal/Context.m | 34 ++++++++++---- gfx/common/metal/Shaders.metal | 54 ++++++++++----------- gfx/common/metal/TexturedView.m | 42 ++++++----------- gfx/common/metal_common.m | 83 +++++++++++++++------------------ ui/drivers/ui_cocoa.m | 2 + 6 files changed, 102 insertions(+), 115 deletions(-) diff --git a/gfx/common/metal/Context.h b/gfx/common/metal/Context.h index 497da8e44d..62a799a389 100644 --- a/gfx/common/metal/Context.h +++ b/gfx/common/metal/Context.h @@ -52,7 +52,7 @@ typedef struct - (Texture *)newTexture:(struct texture_image)image filter:(enum texture_filter_type)filter; - (id)newTexture:(struct texture_image)image mipmapped:(bool)mipmapped; -- (void)convertFormat:(RPixelFormat)fmt from:(id)src to:(id)dst; +- (void)convertFormat:(RPixelFormat)fmt from:(id)src to:(id)dst; - (id)getStockShader:(int)index blend:(bool)blend; /*! @brief resets the viewport for the main render encoder to the drawable size */ diff --git a/gfx/common/metal/Context.m b/gfx/common/metal/Context.m index f610320c24..70f7f66643 100644 --- a/gfx/common/metal/Context.m +++ b/gfx/common/metal/Context.m @@ -65,7 +65,9 @@ _inflightSemaphore = dispatch_semaphore_create(MAX_INFLIGHT); _device = d; _layer = layer; +#if TARGET_OS_OSX _layer.displaySyncEnabled = YES; +#endif _library = l; _commandQueue = [_device newCommandQueue]; _clearColor = MTLClearColorMake(0, 0, 0, 1); @@ -127,7 +129,16 @@ - (void)setDisplaySyncEnabled:(bool)displaySyncEnabled { +#if TARGET_OS_OSX _layer.displaySyncEnabled = displaySyncEnabled; +#endif +} + +- (bool)displaySyncEnabled +{ +#if TARGET_OS_OSX + return _layer.displaySyncEnabled; +#endif } #pragma mark - shaders @@ -154,11 +165,6 @@ return _states[index][blend ? 1 : 0]; } -- (bool)displaySyncEnabled -{ - return _layer.displaySyncEnabled; -} - - (MTLVertexDescriptor *)_spriteVertexDescriptor { MTLVertexDescriptor *vd = [MTLVertexDescriptor new]; @@ -441,13 +447,13 @@ return _drawable; } -- (void)convertFormat:(RPixelFormat)fmt from:(id)src to:(id)dst +- (void)convertFormat:(RPixelFormat)fmt from:(id)src to:(id)dst { - assert(dst.width * dst.height == src.length / RPixelFormatToBPP(fmt)); + assert(src.width == dst.width && src.height == dst.height); assert(fmt >= 0 && fmt < RPixelFormatCount); Filter *conv = _filters[fmt]; assert(conv != nil); - [conv apply:self.blitCommandBuffer inBuf:src outTex:dst]; + [conv apply:self.blitCommandBuffer in:src out:dst]; } - (id)blitCommandBuffer @@ -615,6 +621,7 @@ static const NSUInteger kConstantAlignment = 4; - (void)commitRanges { +#if TARGET_OS_OSX for (BufferNode *n = _head; n != nil; n = n.next) { if (n.allocated > 0) @@ -622,6 +629,7 @@ static const NSUInteger kConstantAlignment = 4; [n.src didModifyRange:NSMakeRange(0, n.allocated)]; } } +#endif } - (void)discard @@ -635,9 +643,15 @@ static const NSUInteger kConstantAlignment = 4; { bzero(range, sizeof(*range)); +#if TARGET_OS_OSX + MTLResourceOptions opts = MTLResourceStorageModeManaged; +#else + MTLResourceOptions opts = MTLResourceStorageModeShared; +#endif + if (!_head) { - _head = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:_blockLen options:MTLResourceStorageModeManaged]]; + _head = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:_blockLen options:opts]]; _length += _blockLen; _current = _head; _offset = 0; @@ -659,7 +673,7 @@ static const NSUInteger kConstantAlignment = 4; blockLen = length; } - _current.next = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:blockLen options:MTLResourceStorageModeManaged]]; + _current.next = [[BufferNode alloc] initWithBuffer:[_device newBufferWithLength:blockLen options:opts]]; if (!_current.next) return NO; diff --git a/gfx/common/metal/Shaders.metal b/gfx/common/metal/Shaders.metal index c5449b2989..396eafd050 100644 --- a/gfx/common/metal/Shaders.metal +++ b/gfx/common/metal/Shaders.metal @@ -81,38 +81,32 @@ fragment half4 stock_fragment_color(FontFragmentIn in [[ stage_in ]]) #pragma mark - filter kernels -kernel void convert_bgra4444_to_bgra8888(device uint16_t * in [[ buffer(0) ]], - texture2d out [[ texture(0) ]], - uint id [[ thread_position_in_grid ]]) +kernel void convert_bgra4444_to_bgra8888(texture2d in [[ texture(0) ]], + texture2d out [[ texture(1) ]], + uint2 gid [[ thread_position_in_grid ]]) { - uint16_t pix = in[id]; - uchar4 pix2 = uchar4( - extract_bits(pix, 4, 4), - extract_bits(pix, 8, 4), - extract_bits(pix, 12, 4), - extract_bits(pix, 0, 4) - ); - - uint ypos = id / out.get_width(); - uint xpos = id % out.get_width(); - - out.write(half4(pix2) / 15.0, uint2(xpos, ypos)); + ushort pix = in.read(gid).r; + uchar4 pix2 = uchar4( + extract_bits(pix, 4, 4), + extract_bits(pix, 8, 4), + extract_bits(pix, 12, 4), + extract_bits(pix, 0, 4) + ); + + out.write(half4(pix2) / 15.0, gid); } -kernel void convert_rgb565_to_bgra8888(device uint16_t * in [[ buffer(0) ]], - texture2d out [[ texture(0) ]], - uint id [[ thread_position_in_grid ]]) +kernel void convert_rgb565_to_bgra8888(texture2d in [[ texture(0) ]], + texture2d out [[ texture(1) ]], + uint2 gid [[ thread_position_in_grid ]]) { - uint16_t pix = in[id]; - uchar4 pix2 = uchar4( - extract_bits(pix, 11, 5), - extract_bits(pix, 5, 6), - extract_bits(pix, 0, 5), - 0xf - ); - - uint ypos = id / out.get_width(); - uint xpos = id % out.get_width(); - - out.write(half4(pix2) / half4(0x1f, 0x3f, 0x1f, 0xf), uint2(xpos, ypos)); + ushort pix = in.read(gid).r; + uchar4 pix2 = uchar4( + extract_bits(pix, 11, 5), + extract_bits(pix, 5, 6), + extract_bits(pix, 0, 5), + 0xf + ); + + out.write(half4(pix2) / half4(0x1f, 0x3f, 0x1f, 0xf), gid); } diff --git a/gfx/common/metal/TexturedView.m b/gfx/common/metal/TexturedView.m index f89346a654..89859ec2b0 100644 --- a/gfx/common/metal/TexturedView.m +++ b/gfx/common/metal/TexturedView.m @@ -16,8 +16,8 @@ CGRect _frame; NSUInteger _bpp; - id _pixels; // frame buffer in _srcFmt - bool _pixelsDirty; + id _src; // source texture + bool _srcDirty; } - (instancetype)initWithDescriptor:(ViewDescriptor *)d context:(Context *)c @@ -53,7 +53,6 @@ _size = size; - // create new texture { MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm width:(NSUInteger)size.width @@ -65,8 +64,11 @@ if (_format != RPixelFormatBGRA8Unorm && _format != RPixelFormatBGRX8Unorm) { - _pixels = [_context.device newBufferWithLength:(NSUInteger)(size.width * size.height * 2) - options:MTLResourceStorageModeManaged]; + MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Uint + width:(NSUInteger)size.width + height:(NSUInteger)size.height + mipmapped:NO]; + _src = [_context.device newTextureWithDescriptor:td]; } } @@ -112,11 +114,11 @@ if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm) return; - if (!_pixelsDirty) + if (!_srcDirty) return; - [_context convertFormat:_format from:_pixels to:_texture]; - _pixelsDirty = NO; + [_context convertFormat:_format from:_src to:_texture]; + _srcDirty = NO; } - (void)drawWithContext:(Context *)ctx @@ -141,26 +143,10 @@ } else { - void *dst = _pixels.contents; - size_t len = (size_t)(_bpp * _size.width); - assert(len <= pitch); // the length can't be larger? - - if (len < pitch) - { - for (int i = 0; i < _size.height; i++) - { - memcpy(dst, src, len); - dst += len; - src += pitch; - } - } - else - { - memcpy(dst, src, _pixels.length); - } - - [_pixels didModifyRange:NSMakeRange(0, _pixels.length)]; - _pixelsDirty = YES; + [_src replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)_size.width, (NSUInteger)_size.height) + mipmapLevel:0 withBytes:src + bytesPerRow:(NSUInteger)(pitch)]; + _srcDirty = YES; } } diff --git a/gfx/common/metal_common.m b/gfx/common/metal_common.m index 007f451abf..f1c146bd40 100644 --- a/gfx/common/metal_common.m +++ b/gfx/common/metal_common.m @@ -299,30 +299,29 @@ settings_t *settings = config_get_ptr(); if (settings && settings->bools.video_msg_bgcolor_enable) { - int msg_width = + 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 = + + 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; + 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]; } @@ -332,7 +331,12 @@ - (void)_beginFrame { + video_viewport_t vp = *_viewport; video_driver_update_viewport(_viewport, NO, _keepAspect); + if (memcmp(&vp, _viewport, sizeof(vp)) != 0) + { + _context.viewport = _viewport; + } [_context begin]; [self _updateUniforms]; } @@ -546,8 +550,8 @@ typedef struct MTLALIGN(16) CGRect _frame; NSUInteger _bpp; - id _pixels; // frame buffer in _srcFmt - bool _pixelsDirty; + id _src; // src texture + bool _srcDirty; id _samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX]; struct video_shader *_shader; @@ -655,8 +659,11 @@ typedef struct MTLALIGN(16) if (_format != RPixelFormatBGRA8Unorm && _format != RPixelFormatBGRX8Unorm) { - _pixels = [_context.device newBufferWithLength:(NSUInteger)(size.width * size.height * 2) - options:MTLResourceStorageModeManaged]; + MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR16Uint + width:(NSUInteger)size.width + height:(NSUInteger)size.height + mipmapped:NO]; + _src = [_context.device newTextureWithDescriptor:td]; } } @@ -702,11 +709,11 @@ typedef struct MTLALIGN(16) if (_format == RPixelFormatBGRA8Unorm || _format == RPixelFormatBGRX8Unorm) return; - if (!_pixelsDirty) + if (!_srcDirty) return; - [_context convertFormat:_format from:_pixels to:_texture]; - _pixelsDirty = NO; + [_context convertFormat:_format from:_src to:_texture]; + _srcDirty = NO; } - (void)_updateHistory @@ -778,26 +785,10 @@ typedef struct MTLALIGN(16) } else { - void *dst = _pixels.contents; - size_t len = (size_t)(_bpp * _size.width); - assert(len <= pitch); // the length can't be larger? - - if (len < pitch) - { - for (int i = 0; i < _size.height; i++) - { - memcpy(dst, src, len); - dst += len; - src += pitch; - } - } - else - { - memcpy(dst, src, _pixels.length); - } - - [_pixels didModifyRange:NSMakeRange(0, _pixels.length)]; - _pixelsDirty = YES; + [_src replaceRegion:MTLRegionMake2D(0, 0, (NSUInteger)_size.width, (NSUInteger)_size.height) + mipmapLevel:0 withBytes:src + bytesPerRow:(NSUInteger)(pitch)]; + _srcDirty = YES; } } diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index bf66477fe6..5de129189a 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -297,6 +297,8 @@ static char** waiting_argv; [self performSelectorOnMainThread:@selector(rarch_main) withObject:nil waitUntilDone:NO]; } +#pragma mark - ApplePlatform + - (void)setViewType:(apple_view_type_t)vt { if (vt == _vt) { return; From 6b7572d166621d6dec4b19e8687cd7177b12c83a Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sat, 1 Sep 2018 16:12:43 -0700 Subject: [PATCH 005/335] fix(macOS): Fix stack overflow when raising Metal shader load event --- ui/drivers/ui_cocoa.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index 5de129189a..aee410946e 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -741,7 +741,7 @@ static void *ui_companion_cocoa_init(void) static void ui_companion_cocoa_event_command(void *data, enum event_command cmd) { (void)data; - command_event(cmd, NULL); + (void)cmd; } static void ui_companion_cocoa_notify_list_pushed(void *data, From eadc3f4a918d507324d720c25e2949fa0c501907 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sat, 1 Sep 2018 16:13:23 -0700 Subject: [PATCH 006/335] fix(Metal): Fix SIGFAULT if any attribute is 0 --- gfx/common/metal/Context.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/common/metal/Context.m b/gfx/common/metal/Context.m index 70f7f66643..021de465d9 100644 --- a/gfx/common/metal/Context.m +++ b/gfx/common/metal/Context.m @@ -382,7 +382,7 @@ { assert(filter >= TEXTURE_FILTER_LINEAR && filter <= TEXTURE_FILTER_MIPMAP_NEAREST); - if (!image.pixels && !image.width && !image.height) + if (!image.pixels || !image.width || !image.height) { /* Create a dummy texture instead. */ #define T0 0xff000000u @@ -403,6 +403,7 @@ image.pixels = (uint32_t *)checkerboard; image.width = 8; image.height = 8; + filter = TEXTURE_FILTER_MIPMAP_NEAREST; } BOOL mipmapped = filter == TEXTURE_FILTER_MIPMAP_LINEAR || filter == TEXTURE_FILTER_MIPMAP_NEAREST; From b592f254b9de165863c9a9e8c914a36536fbc9fe Mon Sep 17 00:00:00 2001 From: David Walters Date: Sun, 2 Sep 2018 18:24:51 +0100 Subject: [PATCH 007/335] Support for "OEM-102" key (usually '\' on Euro keyboards) --- input/input_defines.h | 2 +- input/input_keymaps.c | 7 ++++++- libretro-common/include/libretro.h | 1 + menu/menu_cbs.c | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/input/input_defines.h b/input/input_defines.h index 5e4103bcc9..fa9a868634 100644 --- a/input/input_defines.h +++ b/input/input_defines.h @@ -28,7 +28,7 @@ RETRO_BEGIN_DECLS #define MAX_INPUT_DEVICES 16 -#define RARCH_MAX_KEYS 136 +#define RARCH_MAX_KEYS 137 #define RARCH_FIRST_CUSTOM_BIND 16 #define RARCH_FIRST_LIGHTGUN_BIND RARCH_ANALOG_BIND_LIST_END diff --git a/input/input_keymaps.c b/input/input_keymaps.c index 8060d92b80..ff3817ad92 100644 --- a/input/input_keymaps.c +++ b/input/input_keymaps.c @@ -288,6 +288,7 @@ const struct input_key_map input_config_key_map[] = { { "euro", RETROK_EURO }, { "undo", RETROK_UNDO }, { "clear", RETROK_CLEAR }, + { "oem102", RETROK_OEM_102 }, { "nul", RETROK_UNKNOWN }, { NULL, RETROK_UNKNOWN }, @@ -328,7 +329,7 @@ const struct rarch_key_map rarch_key_map_sdl[] = { { SDLK_9, RETROK_9 }, { SDLK_COLON, RETROK_COLON }, { SDLK_SEMICOLON, RETROK_SEMICOLON }, - { SDLK_LESS, RETROK_LESS }, + { SDLK_LESS, RETROK_OEM_102 }, { SDLK_EQUALS, RETROK_EQUALS }, { SDLK_GREATER, RETROK_GREATER }, { SDLK_QUESTION, RETROK_QUESTION }, @@ -574,6 +575,7 @@ const struct rarch_key_map rarch_key_map_dinput[] = { { DIK_SCROLL, RETROK_SCROLLOCK }, { DIK_CAPSLOCK, RETROK_CAPSLOCK }, { DIK_NUMLOCK, RETROK_NUMLOCK }, + { DIK_OEM_102, RETROK_OEM_102 }, { 0, RETROK_UNKNOWN }, }; #endif @@ -831,6 +833,7 @@ const struct rarch_key_map rarch_key_map_x11[] = { /*{ ?, RETROK_POWER },*/ { XK_EuroSign, RETROK_EURO }, { XK_Undo, RETROK_UNDO }, + /*{ ?, RETROK_OEM_102 },*/ /* FIXME(shizeeg): RetroArch can't handle these buttons atm. * Do we really need RETROK_KP_INSERT, RETROK_KP_END, * RETROK_KP_DOWN, RETROK_KP_PAGEDOWN ??? @@ -986,6 +989,7 @@ const struct rarch_key_map rarch_key_map_linux[] = { { KEY_EURO, RETROK_EURO }, #endif { KEY_UNDO, RETROK_UNDO }, + /*{ ?, RETROK_OEM_102 },*/ { 0, RETROK_UNKNOWN }, }; #endif @@ -1320,6 +1324,7 @@ const struct rarch_key_map rarch_key_map_apple_hid[] = { /* { ?, RETROK_POWER }, */ /* { ?, RETROK_EURO }, */ /* { ?, RETROK_UNDO }, */ + { KEY_NonUSBackslash, RETROK_OEM_102 }, { 0, RETROK_UNKNOWN } }; #endif diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index 86e1652e57..826283b3fa 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -450,6 +450,7 @@ enum retro_key RETROK_POWER = 320, RETROK_EURO = 321, RETROK_UNDO = 322, + RETROK_OEM_102 = 323, RETROK_LAST, diff --git a/menu/menu_cbs.c b/menu/menu_cbs.c index 33d4b5a01e..002e5039fe 100644 --- a/menu/menu_cbs.c +++ b/menu/menu_cbs.c @@ -174,7 +174,8 @@ struct key_desc key_descriptors[RARCH_MAX_KEYS] = {RETROK_MENU, "Menu"}, {RETROK_POWER, "Power"}, {RETROK_EURO, "€"}, - {RETROK_UNDO, "Undo"} + {RETROK_UNDO, "Undo"}, + {RETROK_OEM_102, "OEM-102"} }; /* This sets up all the callback functions for a menu entry. From 611e4846338d1d9428d5343949374ddbfac68736 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 2 Sep 2018 12:49:44 -0700 Subject: [PATCH 008/335] fix(xmb): Fix buffer overflow --- menu/drivers/xmb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index c97d052893..a79d783c6d 100755 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -2007,7 +2007,8 @@ static void xmb_context_reset_horizontal_list( { struct texture_image ti; - char sysname[256]; + char *sysname = (char*) + malloc(PATH_MAX_LENGTH * sizeof(char)); char *iconpath = (char*) malloc(PATH_MAX_LENGTH * sizeof(char)); char *texturepath = (char*) @@ -2018,7 +2019,8 @@ static void xmb_context_reset_horizontal_list( iconpath[0] = sysname[0] = texturepath[0] = content_texturepath[0] = '\0'; - fill_pathname_base_noext(sysname, path, sizeof(sysname)); + fill_pathname_base_noext(sysname, path, + PATH_MAX_LENGTH * sizeof(char)); fill_pathname_application_special(iconpath, PATH_MAX_LENGTH * sizeof(char), @@ -2080,6 +2082,7 @@ static void xmb_context_reset_horizontal_list( image_texture_free(&ti); } + free(sysname); free(iconpath); free(texturepath); free(content_texturepath); From f1ad1ff4447cc319bba5fd4a0571569aff6db17a Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 2 Sep 2018 12:51:34 -0700 Subject: [PATCH 009/335] fix(Metal): Fix invalid selector Removed selector logic and wrapped in HAVE_METAL, given this is only called when Metal is enabled. --- ui/drivers/ui_cocoa.m | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index aee410946e..159395497f 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -361,19 +361,16 @@ static char** waiting_argv; return [NSApp isActive]; } -#define NS_FULLSCREEN_WINDOW_MASK (1 << 14) - - (void)setVideoMode:(gfx_ctx_mode_t)mode { - BOOL isFullScreen = (self.window.styleMask & NS_FULLSCREEN_WINDOW_MASK) == NS_FULLSCREEN_WINDOW_MASK; - SEL fselector = NSSelectorFromString(BOXSTRING("toggleFullScreen")); - - if (mode.fullscreen && !isFullScreen && [self.window respondsToSelector:fselector]) +#ifdef HAVE_METAL + BOOL isFullScreen = (self.window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask; + if (mode.fullscreen && !isFullScreen) { [self.window toggleFullScreen:self]; return; } - if (!mode.fullscreen && isFullScreen && [self.window respondsToSelector:fselector]) + if (!mode.fullscreen && isFullScreen) { [self.window toggleFullScreen:self]; } @@ -384,6 +381,7 @@ static char** waiting_argv; [self.window setContentSize:NSMakeSize(mode.width-1, mode.height)]; } [self.window setContentSize:NSMakeSize(mode.width, mode.height)]; +#endif } - (void)setCursorVisible:(bool)v { From 8a63ace201233256672241346b2a67a7c0d372f8 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 2 Sep 2018 13:03:16 -0700 Subject: [PATCH 010/335] Revert "fix(gfx): Move enum to end to avoid breaking existing configurations" This reverts commit 93b79fa --- gfx/video_defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/video_defines.h b/gfx/video_defines.h index b3aa82ce43..61b09d393a 100644 --- a/gfx/video_defines.h +++ b/gfx/video_defines.h @@ -35,6 +35,7 @@ enum aspect_ratio ASPECT_RATIO_16_9, ASPECT_RATIO_16_10, ASPECT_RATIO_16_15, + ASPECT_RATIO_21_9, ASPECT_RATIO_1_1, ASPECT_RATIO_2_1, ASPECT_RATIO_3_2, @@ -54,7 +55,6 @@ enum aspect_ratio ASPECT_RATIO_SQUARE, ASPECT_RATIO_CORE, ASPECT_RATIO_CUSTOM, - ASPECT_RATIO_21_9, ASPECT_RATIO_END }; From 9d22aacaa720e56142e27ef3b1a475cf87c4d3c0 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 2 Sep 2018 17:53:18 -0700 Subject: [PATCH 011/335] refactor: Add vertex buffer struct to ShaderTypes and remove global --- gfx/common/metal/ShaderTypes.h | 6 ++++++ gfx/common/metal_common.m | 31 ++++++++++++++----------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/gfx/common/metal/ShaderTypes.h b/gfx/common/metal/ShaderTypes.h index 42a588a1fe..ea06c64289 100644 --- a/gfx/common/metal/ShaderTypes.h +++ b/gfx/common/metal/ShaderTypes.h @@ -55,6 +55,12 @@ typedef struct vector_float2 texCoord METAL_ATTRIBUTE(VertexAttributeTexcoord); } Vertex; +typedef struct +{ + vector_float4 position; + vector_float2 texCoord; +} VertexSlang; + typedef struct { vector_float4 position METAL_POSITION; diff --git a/gfx/common/metal_common.m b/gfx/common/metal_common.m index f1c146bd40..bb428673e1 100644 --- a/gfx/common/metal_common.m +++ b/gfx/common/metal_common.m @@ -546,6 +546,7 @@ typedef struct MTLALIGN(16) Context *_context; id _texture; // final render texture Vertex _v[4]; + VertexSlang _vertex[4]; CGSize _size; // size of view in pixels CGRect _frame; NSUInteger _bpp; @@ -587,6 +588,15 @@ typedef struct MTLALIGN(16) self.size = d.size; self.frame = CGRectMake(0, 0, 1, 1); resize_render_targets = YES; + + // init slang vertex buffer + VertexSlang v[4] = { + {simd_make_float4(0, 1, 0, 1), simd_make_float2(0, 1)}, + {simd_make_float4(1, 1, 0, 1), simd_make_float2(1, 1)}, + {simd_make_float4(0, 0, 0, 1), simd_make_float2(0, 0)}, + {simd_make_float4(1, 0, 0, 1), simd_make_float2(1, 0)}, + }; + memcpy(_vertex, v, sizeof(_vertex)); } return self; } @@ -816,19 +826,6 @@ typedef struct MTLALIGN(16) init_history = NO; } -typedef struct vertex -{ - simd_float4 pos; - simd_float2 tex; -} vertex_t; - -static vertex_t vertex_bytes[] = { - {{0, 1, 0, 1}, {0, 1}}, - {{1, 1, 0, 1}, {1, 1}}, - {{0, 0, 0, 1}, {0, 0}}, - {{1, 0, 0, 1}, {1, 0}}, -}; - - (void)drawWithEncoder:(id)rce { if (_texture) @@ -942,7 +939,7 @@ static vertex_t vertex_bytes[] = { [rce setFragmentTextures:textures withRange:NSMakeRange(0, SLANG_NUM_BINDINGS)]; [rce setFragmentSamplerStates:samplers withRange:NSMakeRange(0, SLANG_NUM_BINDINGS)]; - [rce setVertexBytes:vertex_bytes length:sizeof(vertex_bytes) atIndex:4]; + [rce setVertexBytes:_vertex length:sizeof(_vertex) atIndex:4]; [rce drawPrimitives:MTLPrimitiveTypeTriangleStrip vertexStart:0 vertexCount:4]; if (!backBuffer) @@ -1162,13 +1159,13 @@ static vertex_t vertex_bytes[] = { @try { MTLVertexDescriptor *vd = [MTLVertexDescriptor new]; - vd.attributes[0].offset = offsetof(vertex_t, pos); + vd.attributes[0].offset = offsetof(VertexSlang, position); vd.attributes[0].format = MTLVertexFormatFloat4; vd.attributes[0].bufferIndex = 4; - vd.attributes[1].offset = offsetof(vertex_t, tex); + vd.attributes[1].offset = offsetof(VertexSlang, texCoord); vd.attributes[1].format = MTLVertexFormatFloat2; vd.attributes[1].bufferIndex = 4; - vd.layouts[4].stride = sizeof(vertex_t); + vd.layouts[4].stride = sizeof(VertexSlang); vd.layouts[4].stepFunction = MTLVertexStepFunctionPerVertex; MTLRenderPipelineDescriptor *psd = [MTLRenderPipelineDescriptor new]; From 99f497de85cc5dc57284bd0689ccf0751f419442 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Sun, 2 Sep 2018 17:55:02 -0700 Subject: [PATCH 012/335] feat(Metal): Add support for screen shots --- gfx/common/metal/Context.h | 5 +++ gfx/common/metal/Context.m | 63 +++++++++++++++++++++++++++++++++++++- gfx/common/metal_common.h | 1 + gfx/common/metal_common.m | 18 +++++++++++ gfx/drivers/metal.m | 3 +- 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/gfx/common/metal/Context.h b/gfx/common/metal/Context.h index 62a799a389..7e8e7eab7c 100644 --- a/gfx/common/metal/Context.h +++ b/gfx/common/metal/Context.h @@ -34,6 +34,9 @@ typedef struct /*! @brief Specifies whether rendering is synchronized with the display */ @property (nonatomic, readwrite) bool displaySyncEnabled; +/*! @brief captureEnabled allows previous frames to be read */ +@property (nonatomic, readwrite) bool captureEnabled; + /*! @brief Returns the command buffer used for pre-render work, * such as mip maps and shader effects * */ @@ -70,4 +73,6 @@ typedef struct /*! @brief end commits the command buffer */ - (void)end; +- (bool)readBackBuffer:(uint8_t *)buffer; + @end diff --git a/gfx/common/metal/Context.m b/gfx/common/metal/Context.m index 021de465d9..00ca54e3f4 100644 --- a/gfx/common/metal/Context.m +++ b/gfx/common/metal/Context.m @@ -54,6 +54,9 @@ id _states[GFX_MAX_SHADERS][2]; id _clearState; Uniforms _uniforms; + + bool _captureEnabled; + id _backBuffer; } - (instancetype)initWithDevice:(id)d @@ -470,11 +473,65 @@ [_chain[_currentChain] discard]; } +- (void)setCaptureEnabled:(bool)captureEnabled +{ + if (_captureEnabled == captureEnabled) + return; + + _captureEnabled = captureEnabled; + //_layer.framebufferOnly = !captureEnabled; +} + +- (bool)captureEnabled +{ + return _captureEnabled; +} + +- (bool)readBackBuffer:(uint8_t *)buffer +{ + if (!_captureEnabled || _backBuffer == nil) + return NO; + + if (_backBuffer.pixelFormat != MTLPixelFormatBGRA8Unorm) + { + RARCH_WARN("[Metal]: unexpected pixel format %d\n", _backBuffer.pixelFormat); + return NO; + } + + uint8_t *tmp = malloc(_backBuffer.width * _backBuffer.height * 4); + + [_backBuffer getBytes:tmp + bytesPerRow:4 * _backBuffer.width + fromRegion:MTLRegionMake2D(0, 0, _backBuffer.width, _backBuffer.height) + mipmapLevel:0]; + + NSUInteger srcStride = _backBuffer.width * 4; + uint8_t const *src = tmp + (_viewport.y * srcStride); + + NSUInteger dstStride = _viewport.width * 3; + uint8_t *dst = buffer + (_viewport.height - 1) * dstStride; + + for (int y = _viewport.y; y < _viewport.height; y++, src += srcStride, dst -= dstStride) + { + for (int x = _viewport.x; x < _viewport.width; x++) + { + dst[3 * x + 0] = src[4 * x + 0]; + dst[3 * x + 1] = src[4 * x + 1]; + dst[3 * x + 2] = src[4 * x + 2]; + } + } + + free(tmp); + + return YES; +} + - (void)begin { assert(_commandBuffer == nil); dispatch_semaphore_wait(_inflightSemaphore, DISPATCH_TIME_FOREVER); _commandBuffer = [_commandQueue commandBuffer]; + _backBuffer = nil; } - (id)rce @@ -486,6 +543,10 @@ rpd.colorAttachments[0].clearColor = _clearColor; rpd.colorAttachments[0].loadAction = MTLLoadActionClear; rpd.colorAttachments[0].texture = self.nextDrawable.texture; + if (_captureEnabled) + { + _backBuffer = self.nextDrawable.texture; + } _rce = [_commandBuffer renderCommandEncoderWithDescriptor:rpd]; } return _rce; @@ -643,7 +704,7 @@ static const NSUInteger kConstantAlignment = 4; - (bool)allocRange:(BufferRange *)range length:(NSUInteger)length { bzero(range, sizeof(*range)); - + #if TARGET_OS_OSX MTLResourceOptions opts = MTLResourceStorageModeManaged; #else diff --git a/gfx/common/metal_common.h b/gfx/common/metal_common.h index c7271cee01..66b7f08b92 100644 --- a/gfx/common/metal_common.h +++ b/gfx/common/metal_common.h @@ -40,6 +40,7 @@ extern MTLPixelFormat SelectOptimalPixelFormat(MTLPixelFormat fmt); - (void)setFilteringIndex:(int)index smooth:(bool)smooth; - (BOOL)setShaderFromPath:(NSString *)path; - (void)updateFrame:(void const *)src pitch:(NSUInteger)pitch; +- (bool)readViewport:(uint8_t *)buffer isIdle:(bool)isIdle; @end diff --git a/gfx/common/metal_common.m b/gfx/common/metal_common.m index bb428673e1..3358883392 100644 --- a/gfx/common/metal_common.m +++ b/gfx/common/metal_common.m @@ -760,6 +760,24 @@ typedef struct MTLALIGN(16) } } +- (bool)readViewport:(uint8_t *)buffer isIdle:(bool)isIdle +{ + RARCH_LOG("[Metal]: readViewport is_idle = %s\n", isIdle ? "YES" : "NO"); + + bool enabled = _context.captureEnabled; + if (!enabled) + _context.captureEnabled = YES; + + video_driver_cached_frame(); + + bool res = [_context readBackBuffer:buffer]; + + if (!enabled) + _context.captureEnabled = NO; + + return res; +} + - (void)updateFrame:(void const *)src pitch:(NSUInteger)pitch { if (_shader && (_engine.frame.output_size.x != _viewport->width || diff --git a/gfx/drivers/metal.m b/gfx/drivers/metal.m index d788d09bfa..0fcd932d01 100644 --- a/gfx/drivers/metal.m +++ b/gfx/drivers/metal.m @@ -163,7 +163,8 @@ static void metal_viewport_info(void *data, struct video_viewport *vp) static bool metal_read_viewport(void *data, uint8_t *buffer, bool is_idle) { - return true; + MetalDriver *md = (__bridge MetalDriver *)data; + return [md.frameView readViewport:buffer isIdle:is_idle]; } static uintptr_t metal_load_texture(void *video_data, void *data, From 96d27b6ac6ed77ae8cecd971c0afbd19b0bd9e0d Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Mon, 3 Sep 2018 03:09:37 +0200 Subject: [PATCH 013/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 3b2ff8445e..333d090427 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,6 +29,7 @@ - MENU/XMB: Add an option to show the desktop ui - METAL: Initial work-in-progress video driver for Metal. macOS-only right now, and currently requires macOS 10.13. - METAL: Supports XMB/MaterialUI, has a menu display driver. Has a font rendering driver. +- METAL: Add screenshot support. - METAL/SLANG: Slang shaders should be compatible with Metal video driver. - NETWORK: Enable SSL/TLS support by default for desktop platforms. - QNX: Fix Game Focus Toggle. From e224d1cd0408c0001fdf3d86adff78d8bfb5d26f Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Mon, 3 Sep 2018 03:10:08 +0200 Subject: [PATCH 014/335] Update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 333d090427..22e79b6f18 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,5 @@ # 1.7.5 (future) +- METAL: Add screenshot support. # 1.7.4 - ANDROID: Add sustained performance mode, can be turned on/off in Power Management settings menu. @@ -29,7 +30,6 @@ - MENU/XMB: Add an option to show the desktop ui - METAL: Initial work-in-progress video driver for Metal. macOS-only right now, and currently requires macOS 10.13. - METAL: Supports XMB/MaterialUI, has a menu display driver. Has a font rendering driver. -- METAL: Add screenshot support. - METAL/SLANG: Slang shaders should be compatible with Metal video driver. - NETWORK: Enable SSL/TLS support by default for desktop platforms. - QNX: Fix Game Focus Toggle. From 4409c6173015167407e36d8f54ce9b9fbfe0abc0 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Mon, 3 Sep 2018 03:10:36 +0200 Subject: [PATCH 015/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 22e79b6f18..77735321c9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,5 @@ # 1.7.5 (future) +- COMMON: Support for "OEM-102" key (usually '\' on Euro keyboards). - METAL: Add screenshot support. # 1.7.4 From c57e259fa7ce856b3226e6c12336e5247dae73db Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Mon, 3 Sep 2018 03:11:23 +0200 Subject: [PATCH 016/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 77735321c9..106a225cdc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,6 @@ # 1.7.5 (future) - COMMON: Support for "OEM-102" key (usually '\' on Euro keyboards). +- MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. # 1.7.4 From b2c704862a0a8621d1185fca5043a3f9f8a32ff9 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Sun, 2 Sep 2018 21:57:06 -0400 Subject: [PATCH 017/335] travis: deploy OSX Metal build --- .travis.yml | 6 ++++++ travis-deploy-key.enc | Bin 0 -> 1680 bytes travis_metal_deploy.sh | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 travis-deploy-key.enc create mode 100644 travis_metal_deploy.sh diff --git a/.travis.yml b/.travis.yml index 898ad6c5f9..167f2f1b94 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,12 @@ matrix: osx_image: xcode9.3 script: - xcodebuild -target RetroArch -configuration Release -project pkg/apple/RetroArch_Metal.xcodeproj + deploy: + skip_cleanup: true + provider: script + script: bash travis_metal_deploy.sh + on: + branch: master script: - ./configure diff --git a/travis-deploy-key.enc b/travis-deploy-key.enc new file mode 100644 index 0000000000000000000000000000000000000000..c4866927015bb5a7f442ee8e5a699205e52a819f GIT binary patch literal 1680 zcmV;B25?%bt=3zDWr{L(B0x!&-;ClR?`>9MhPGi{i81^N5A zK7R^8?N?ujd-B59emjBRJ6BnkMVrD73?xAN7Q~wc_6po?wcAN}xzr3Lyx6x*Og+=C zP<&iZp)N6YLF^|)pO8JY7C@b%$~tbe5ZsuiZ~S30KVNSAu^X}<1^VWgq=6Ay!k$no zCI0@SIY{*N@4-G9eApbFaJkyLQLH^<7-d~0*HA1Wu2Il@HgEmzFcF|UqF!_+VE^R5 zuv1K+x*OnqnA=aS*v~Q(5?DXkRUF%1K6LiE8T8Vdem81@Zj05zI?;Y1PG>;-{gbJI z1+>j+YZa|CNx@ib@ZIh3cGy*?F)}6{NimOR$Kv!+)3J3(Q|s~wPyrK+uGpdCkMAf5-N-v))73SGhH&cFfxHQ|gH})On@-(;u~y zo%fbTNg`jM3Z8IVS?$(cj1w=Q!z%3U{uQ)ybW&_QPrTDUIRlN ztQ`#!-tru~ys!-zB3lbEU~yEWv6-o=MfoD? zb4cM?MQV27v#K~`MA1|lf7-Pa`ZK(gPk9P`GnaQUK}xi`8yPX?XfTr}JETKfqx`cR zrIA}kijT>#iYo6w!XEmv9wttMHb@2ff3bM6zcXNpxcXxpV#t zUt-fExg~RGYkrta61S|6-v5NJOe$e-yBXzRg7mRKotcz_GcxV&T^{>DT zLjAiEB2#UIAsS7It1l?>0t z@qLZR6R%C6m5NsT^*!ger7Q3ZMa1_dr*J}|eo152Gdi_~dl)Y>WPAQ(go4oF?9suX z1vmbx&G8_h#LPEq7!yzw+-rNh+A5+tD0E270W)he9|`^}sAx2gk8lOU5RJXrVLYNl zRwOK=tzrVL-c^FV=sUe9`WN1z3!l0QRS|xCu{9N$)bGmV=oApt|6niSdxKi0mBhyc z5np#Tu*E>Y(1H4D#<2#7k@f+VuHBf^2I8zZlIJP6nXDT)(|Hkl%}#RC!nqJ`lRKr` zCoTpBWK(PO+~rMMmzC056b5T(c~zp>qA$RAbCp(m3HimL0;3bvpZVT&-9cEY7JjZ* zep%e|*)p3l_ctpCo=c=vZHa;lr774P_Vq5V3@EY@A`Ker&Q2%M;-a|w&J5(HBC3cV z4L=b1xO6=v7GK=~8`vbU1o>m<-lQ#YUb z!$rD*r2KY9hgOFc-TIEt+oVj#6ml1OaT_0}B2v|xU)c;Il~0eyPB6${lQfYl)e?4T zFbqOY5h@wHFQPjTj#N%ec%j5vFn|cYy?*Q!-EUAU431?mtUT-K5(^Gg^p&&p5EsRu zuhgSdvZDvi7&S+FgwKHNv(}!d(0$+gE>f92{)+k@WyYShRcPOiCRLTOai$TLSjtnY^xF-@V!c`f$X38&~-@fEii%T-n88nUGQ-_ a*qSfoJ!)yu00{}5`P{92EfV>r78xB&$xn#@ literal 0 HcmV?d00001 diff --git a/travis_metal_deploy.sh b/travis_metal_deploy.sh new file mode 100644 index 0000000000..2fb7316123 --- /dev/null +++ b/travis_metal_deploy.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +mkdir -p ~/.ssh + +chmod 700 ~/.ssh + +echo "Decrypting SSH key..." + +openssl aes-256-cbc -K $encrypted_e9bb4da59666_key -iv $encrypted_e9bb4da59666_iv -in travis-deploy-key.enc -out ~/.ssh/id_rsa -d + +chmod 600 ~/.ssh/id_rsa + +echo "Creating DMG image..." + +cd ${TRAVIS_BUILD_DIR}/pkg/apple/build/Release + +FILENAME=$(date +%F)_RetroArch_Metal.dmg + +hdiutil create -volname RetroArch -srcfolder ./ -ov -format UDZO ${FILENAME} + +echo "Uploading to server..." + +rsync -avhP -e 'ssh -p 12346 -o StrictHostKeyChecking=no' ${FILENAME} travis@bot.libretro.com:~/nightly/apple/osx/x86_64/ From 511dcb0d56d1a208716b908193dbdab9eddd56c0 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Mon, 3 Sep 2018 09:07:04 -0400 Subject: [PATCH 018/335] travis: build Metal with libretro-super instead --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 167f2f1b94..a46d3de536 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,10 @@ matrix: - os: osx osx_image: xcode9.3 script: - - xcodebuild -target RetroArch -configuration Release -project pkg/apple/RetroArch_Metal.xcodeproj + - cd ~/ + - git clone --depth=50 https://github.com/libretro/libretro-super + - cd libretro-super/travis + - ./build-retroarch-metal.sh deploy: skip_cleanup: true provider: script From 9214f6079f8cf73f5603a17c34bb869e9da739c9 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Mon, 3 Sep 2018 09:37:59 -0400 Subject: [PATCH 019/335] travis: go to correct folder to deploy Metal --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a46d3de536..8cce088599 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,7 +44,7 @@ matrix: deploy: skip_cleanup: true provider: script - script: bash travis_metal_deploy.sh + script: cd ../retroarch; bash travis_metal_deploy.sh on: branch: master From 9da261c6d9a3f276e44c7f1999aef4fc758cbafd Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Mon, 3 Sep 2018 13:31:46 -0400 Subject: [PATCH 020/335] Update config entries pointer to the new beginning of the list after sorting --- libretro-common/file/config_file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libretro-common/file/config_file.c b/libretro-common/file/config_file.c index 9c2b76b170..0a63e7781a 100644 --- a/libretro-common/file/config_file.c +++ b/libretro-common/file/config_file.c @@ -999,6 +999,7 @@ void config_file_dump(config_file_t *conf, FILE *file) } list = merge_sort_linked_list((struct config_entry_list*)conf->entries, config_sort_compare_func); + conf->entries = list; while (list) { @@ -1092,7 +1093,7 @@ static void test_config_file(void) test_config_file_parse_contains("foo = \"bar\"", "foo", "bar"); #if 0 - /* turns out it treats empty as nonexistent - + /* turns out it treats empty as nonexistent - * should probably be fixed */ test_config_file_parse_contains("foo = \"\"\n", "foo", ""); test_config_file_parse_contains("foo = \"\"", "foo", ""); From c64a75c58aece70a0679281d4668bcb87c0b0b75 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Mon, 3 Sep 2018 19:50:04 -0400 Subject: [PATCH 021/335] travis: clean up OSX Metal image and add assets --- travis_metal_deploy.sh | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/travis_metal_deploy.sh b/travis_metal_deploy.sh index 2fb7316123..a6cf39a386 100644 --- a/travis_metal_deploy.sh +++ b/travis_metal_deploy.sh @@ -10,14 +10,28 @@ openssl aes-256-cbc -K $encrypted_e9bb4da59666_key -iv $encrypted_e9bb4da59666_i chmod 600 ~/.ssh/id_rsa +mkdir ~/dist +cd ~/dist + +echo "Copying binary into dist folder..." + +cp -rv ~/libretro-super/retroarch/pkg/apple/build/Release/RetroArch.app . + +echo "Downloading assets..." + +cd RetroArch.app/Contents/Resources/ +curl -O http://bot.libretro.com/assets/frontend/bundle.zip +unzip -o bundle.zip +rm -rf bundle.zip + echo "Creating DMG image..." -cd ${TRAVIS_BUILD_DIR}/pkg/apple/build/Release +cd ~/dist FILENAME=$(date +%F)_RetroArch_Metal.dmg -hdiutil create -volname RetroArch -srcfolder ./ -ov -format UDZO ${FILENAME} +hdiutil create -volname RetroArch -srcfolder ./ -ov -format UDZO ~/${FILENAME} echo "Uploading to server..." -rsync -avhP -e 'ssh -p 12346 -o StrictHostKeyChecking=no' ${FILENAME} travis@bot.libretro.com:~/nightly/apple/osx/x86_64/ +rsync -avhP -e 'ssh -p 12346 -o StrictHostKeyChecking=no' ~/${FILENAME} travis@bot.libretro.com:~/nightly/apple/osx/x86_64/ From a48cc2f9b5022d016c95273eaa685b99a703d2c8 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Mon, 3 Sep 2018 20:00:03 -0400 Subject: [PATCH 022/335] travis: unzip quietly so build log is not truncated --- travis_metal_deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis_metal_deploy.sh b/travis_metal_deploy.sh index a6cf39a386..13ad04aeb3 100644 --- a/travis_metal_deploy.sh +++ b/travis_metal_deploy.sh @@ -21,7 +21,7 @@ echo "Downloading assets..." cd RetroArch.app/Contents/Resources/ curl -O http://bot.libretro.com/assets/frontend/bundle.zip -unzip -o bundle.zip +unzip -q -o bundle.zip rm -rf bundle.zip echo "Creating DMG image..." From c60fdf0b2e947668370c69d5928b4008362b1131 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Wed, 5 Sep 2018 00:07:11 -0400 Subject: [PATCH 023/335] Qt: fix duplicate function name with griffin --- ui/drivers/qt/thumbnailpackdownload.cpp | 4 ++-- ui/drivers/qt/updateretroarch.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/drivers/qt/thumbnailpackdownload.cpp b/ui/drivers/qt/thumbnailpackdownload.cpp index a9b551498b..df4b68145c 100644 --- a/ui/drivers/qt/thumbnailpackdownload.cpp +++ b/ui/drivers/qt/thumbnailpackdownload.cpp @@ -21,7 +21,7 @@ extern "C" { #define THUMBNAILPACK_URL_HEADER "http://thumbnailpacks.libretro.com/" #define THUMBNAILPACK_EXTENSION ".zip" -static void extractCB(void *task_data, void *user_data, const char *err) +static void extractThumbnailPackCB(void *task_data, void *user_data, const char *err) { decompress_task_data_t *dec = (decompress_task_data_t*)task_data; MainWindow *mainwindow = (MainWindow*)user_data; @@ -167,7 +167,7 @@ void MainWindow::onThumbnailPackDownloadFinished() if (settings) { RARCH_LOG("[Qt]: Thumbnail pack download finished successfully.\n"); - emit extractArchiveDeferred(newFileName, settings->paths.directory_thumbnails, TEMP_EXTENSION, extractCB); + emit extractArchiveDeferred(newFileName, settings->paths.directory_thumbnails, TEMP_EXTENSION, extractThumbnailPackCB); } } else diff --git a/ui/drivers/qt/updateretroarch.cpp b/ui/drivers/qt/updateretroarch.cpp index 9f524abc9e..0952a5e094 100644 --- a/ui/drivers/qt/updateretroarch.cpp +++ b/ui/drivers/qt/updateretroarch.cpp @@ -18,7 +18,7 @@ extern "C" { #define TEMP_EXTENSION ".update_tmp" #define RETROARCH_NIGHTLY_UPDATE_PATH "../RetroArch_update.zip" -static void extractCB(void *task_data, void *user_data, const char *err) +static void extractUpdateCB(void *task_data, void *user_data, const char *err) { decompress_task_data_t *dec = (decompress_task_data_t*)task_data; MainWindow *mainwindow = (MainWindow*)user_data; @@ -157,7 +157,7 @@ void MainWindow::onRetroArchUpdateDownloadFinished() if (m_updateFile.rename(newFileName)) { RARCH_LOG("[Qt]: RetroArch update finished downloading successfully.\n"); - emit extractArchiveDeferred(newFileName, ".", TEMP_EXTENSION, extractCB); + emit extractArchiveDeferred(newFileName, ".", TEMP_EXTENSION, extractUpdateCB); } else { From 428f895b6f9deb036d5a5f0b171397b623b7ba01 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Wed, 5 Sep 2018 20:10:54 -0700 Subject: [PATCH 024/335] feat(macOS): Initial Desktop UI (Qt) support * Adds new RetroArchQT build target to RetroArch_Metal.xcodeproj Prerequisites: * Install Qt Frameworks $ brew install qt * Build `moc` files using $ make -f Makefile.apple HAVE_QT=1 Q=/usr/local/opt/qt/bin/moc generate Limitations: * Qt frameworks are not embedded in bundle, therefore Qt must be installed via the `brew` command --- .gitignore | 3 + Makefile.apple | 24 ++ griffin/griffin_cpp.cpp | 11 + pkg/apple/BaseConfig.xcconfig | 15 +- pkg/apple/Metal.xcconfig | 9 + pkg/apple/QTConfig.xcconfig | 24 ++ pkg/apple/RetroArch copy-Info.plist | 49 ++++ .../RetroArch_Metal.xcodeproj/project.pbxproj | 213 +++++++++++++++++- pkg/apple/VulkanConfig.xcconfig | 20 ++ 9 files changed, 352 insertions(+), 16 deletions(-) create mode 100644 Makefile.apple create mode 100644 pkg/apple/Metal.xcconfig create mode 100644 pkg/apple/QTConfig.xcconfig create mode 100644 pkg/apple/RetroArch copy-Info.plist create mode 100644 pkg/apple/VulkanConfig.xcconfig diff --git a/.gitignore b/.gitignore index edbc60d340..645b3bf4f1 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,9 @@ wiiu/wut/elf2rpl/elf2rpl pkg/apple/iOS/build/ pkg/apple/iOS/modules/ +pkg/apple/build/ +ui/drivers/qt/moc_* +ui/drivers/moc_* obj-unix/ .vagrant/ diff --git a/Makefile.apple b/Makefile.apple new file mode 100644 index 0000000000..e7f76d96e0 --- /dev/null +++ b/Makefile.apple @@ -0,0 +1,24 @@ +include Makefile.common + +# Qt MOC generation, required for QObject-derived classes +ifneq ($(MOC_HEADERS),) + # prefix moc_ to base filename of paths and change extension from h to cpp, so a/b/foo.h becomes a/b/moc_foo.cpp + MOC_SRC := $(join $(addsuffix moc_,$(dir $(MOC_HEADERS))), $(notdir $(MOC_HEADERS:.h=.cpp))) +endif + +Q ?= $(error missing moc) + +.PHONY: generate + +$(MOC_SRC): + @$(if $(Q), $(shell echo echo MOC $<),) + $(eval MOC_TMP := $(patsubst %.h,%_moc.cpp,$@)) + $(Q)$(MOC) -o $(MOC_TMP) $< + +$(foreach x,$(join $(addsuffix :,$(MOC_SRC)),$(MOC_HEADERS)),$(eval $x)) + +generate: $(MOC_SRC) + @echo $(MOC_SRC) + +print-%: + @echo '$*=$($*)' \ No newline at end of file diff --git a/griffin/griffin_cpp.cpp b/griffin/griffin_cpp.cpp index c3b2bc7116..fd3673afa0 100644 --- a/griffin/griffin_cpp.cpp +++ b/griffin/griffin_cpp.cpp @@ -33,7 +33,9 @@ MENU UI ============================================================ */ #if defined(HAVE_QT) +#ifndef __APPLE__ #define HAVE_MAIN /* also requires defining in frontend.c */ +#endif #include "../ui/drivers/ui_qt.cpp" #include "../ui/drivers/qt/ui_qt_window.cpp" @@ -53,6 +55,15 @@ UI #include "../ui/drivers/qt/thumbnaildownload.cpp" #include "../ui/drivers/qt/thumbnailpackdownload.cpp" #include "../ui/drivers/qt/playlistthumbnaildownload.cpp" +#include "../ui/drivers/moc_ui_qt.cpp" +#include "../ui/drivers/qt/moc_coreinfodialog.cpp" +#include "../ui/drivers/qt/moc_coreoptionsdialog.cpp" +#include "../ui/drivers/qt/moc_filedropwidget.cpp" +#include "../ui/drivers/qt/moc_flowlayout.cpp" +#include "../ui/drivers/qt/moc_playlistentrydialog.cpp" +#include "../ui/drivers/qt/moc_shaderparamsdialog.cpp" +#include "../ui/drivers/qt/moc_ui_qt_load_core_window.cpp" +#include "../ui/drivers/qt/moc_viewoptionsdialog.cpp" #endif /*============================================================ diff --git a/pkg/apple/BaseConfig.xcconfig b/pkg/apple/BaseConfig.xcconfig index 1969463c8a..d1386170a1 100644 --- a/pkg/apple/BaseConfig.xcconfig +++ b/pkg/apple/BaseConfig.xcconfig @@ -4,24 +4,11 @@ // // Created by Stuart Carnie on 5/10/18. // -VULKAN_PACKAGE_PATH = /Volumes/Data/projects/frameworks/vulkan/moltenvk/Package -// macOS -VULKAN_FRAMEWORK_PATH[sdk=macosx*] = $(VULKAN_PACKAGE_PATH)/$(CONFIGURATION)/MoltenVK/macOS - - -// general -FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(LOCAL_LIBRARY_DIR)/Frameworks $(VULKAN_FRAMEWORK_PATH) -LIBRARY_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(VULKAN_FRAMEWORK_PATH) - -// OTHER_LDFLAGS = $(inherited) -lMoltenVK -framework MoltenVK - -OTHER_CFLAGS = $(inherited) -DHAVE_RUNAHEAD -DHAVE_GRIFFIN -DHAVE_FLAC -DHAVE_DR_FLAC -DHAVE_DR_MP3 -DHAVE_LROUND -DFLAC__HAS_OGG=0 -DHAVE_CHD -DHAVE_STB_VORBIS -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DHAVE_UPDATE_ASSETS -DHAVE_LANGEXTRA -DHAVE_CHEEVOS -DHAVE_IMAGEVIEWER -DHAVE_IOHIDMANAGER -DHAVE_CORETEXT -DHAVE_RGUI -DHAVE_MENU -DOSX -DHAVE_OPENGL -DHAVE_CC_RESAMPLER -DHAVE_GLSL -DINLINE=inline -D__LIBRETRO__ -DHAVE_COREAUDIO -DHAVE_DYNAMIC -DHAVE_OVERLAY -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_COCOA -DHAVE_MAIN -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DRARCH_INTERNAL -DHAVE_THREADS -DHAVE_DYLIB -DHAVE_7ZIP -DHAVE_MATERIALUI -DHAVE_HID -DHAVE_XMB -DHAVE_SEGA -DHAVE_SHADERPIPELINE -DHAVE_MMAP -DHAVE_LIBRETRODB -DHAVE_GETOPT_LONG -DHAVE_METAL -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_SPIRV_CROSS -DWANT_GLSLANG -DENABLE_HLSL -DGLSLANG_OSINCLUDE_UNIX -DMETAL_DEBUG +OTHER_CFLAGS = $(inherited) -DHAVE_RUNAHEAD -DHAVE_GRIFFIN -DHAVE_FLAC -DHAVE_DR_FLAC -DHAVE_DR_MP3 -DHAVE_LROUND -DFLAC__HAS_OGG=0 -DHAVE_CHD -DHAVE_STB_VORBIS -DHAVE_MINIUPNPC -DHAVE_BUILTINMINIUPNPC -DHAVE_UPDATE_ASSETS -DHAVE_LANGEXTRA -DHAVE_CHEEVOS -DHAVE_IMAGEVIEWER -DHAVE_IOHIDMANAGER -DHAVE_CORETEXT -DHAVE_RGUI -DHAVE_MENU -DOSX -DHAVE_OPENGL -DHAVE_CC_RESAMPLER -DHAVE_GLSL -DINLINE=inline -D__LIBRETRO__ -DHAVE_COREAUDIO -DHAVE_DYNAMIC -DHAVE_OVERLAY -DHAVE_ZLIB -DHAVE_RPNG -DHAVE_RJPEG -DHAVE_RBMP -DHAVE_RTGA -DHAVE_COCOA -DHAVE_NETWORKGAMEPAD -DHAVE_NETWORKING -DRARCH_INTERNAL -DHAVE_THREADS -DHAVE_DYLIB -DHAVE_7ZIP -DHAVE_MATERIALUI -DHAVE_HID -DHAVE_XMB -DHAVE_SEGA -DHAVE_SHADERPIPELINE -DHAVE_MMAP -DHAVE_LIBRETRODB -DHAVE_GETOPT_LONG -DHAVE_METAL -DHAVE_SLANG -DHAVE_GLSLANG -DHAVE_SPIRV_CROSS -DWANT_GLSLANG -DENABLE_HLSL -DGLSLANG_OSINCLUDE_UNIX -DMETAL_DEBUG SRCBASE = $(SRCROOT)/../.. DEPS_DIR = $(SRCBASE)/deps HEADER_SEARCH_PATHS = $(inherited) $(SRCBASE) $(SRCBASE)/gfx/include $(SRCBASE)/libretro-common/include $(DEPS_DIR)/libFLAC/include $(DEPS_DIR)/7zip $(DEPS_DIR)/stb $(DEPS_DIR) $(DEPS_DIR)/SPIRV-Cross $(DEPS_DIR)/glslang $(DEPS_DIR)/glslang/glslang/glslang/Public $(DEPS_DIR)/glslang/glslang/glslang/MachineIndependent $(DEPS_DIR)/glslang/glslang/SPIRV $(DEPS_DIR)/glslang/glslang/glslang/OSDependent/Unix CLANG_CXX_LANGUAGE_STANDARD=c++11 -LD_RUNPATH_SEARCH_PATHS = @executable_path CLANG_ENABLE_OBJC_ARC=YES -//SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk diff --git a/pkg/apple/Metal.xcconfig b/pkg/apple/Metal.xcconfig new file mode 100644 index 0000000000..27d22dd265 --- /dev/null +++ b/pkg/apple/Metal.xcconfig @@ -0,0 +1,9 @@ +// +// BaseConfig.xcconfig +// RetroArch +// +// Created by Stuart Carnie on 5/10/18. +// + +OTHER_CFLAGS = $(inherited) -DHAVE_MAIN + diff --git a/pkg/apple/QTConfig.xcconfig b/pkg/apple/QTConfig.xcconfig new file mode 100644 index 0000000000..01ef9d0d01 --- /dev/null +++ b/pkg/apple/QTConfig.xcconfig @@ -0,0 +1,24 @@ +// +// RetroArch build configuration specific to Qt +// +// Created by Stuart Carnie on 5/10/18. +// + +// QT Support +QT_INSTALL = /usr/local/opt/qt +QT_FRAMEWORK_PATH = $(QT_INSTALL)/lib +QT_FRAMEWORKS = -framework QtWidgets -framework QtGui -framework QtConcurrent -framework QtNetwork -framework QtCore + +QT_HEADERS = $(QT_INSTALL)/include +QT_HEADER_SEARCH_PATHS = $(QT_HEADERS) $(QT_HEADERS)/QtWidgets $(QT_HEADERS)/QtGui $(QT_HEADERS)/QtConcurrent $(QT_HEADERS)/QtNetwork $(QT_HEADERS)/QtCore +QT_CFLAGS = -DHAVE_QT -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CONCURRENT_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB + +// general +FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(QT_FRAMEWORK_PATH) + +OTHER_LDFLAGS = $(inherited) $(QT_FRAMEWORKS) + +OTHER_CFLAGS = $(inherited) $(QT_CFLAGS) + +HEADER_SEARCH_PATHS = $(inherited) $(QT_HEADER_SEARCH_PATHS) +LD_RUNPATH_SEARCH_PATHS = @executable_path diff --git a/pkg/apple/RetroArch copy-Info.plist b/pkg/apple/RetroArch copy-Info.plist new file mode 100644 index 0000000000..a28050a571 --- /dev/null +++ b/pkg/apple/RetroArch copy-Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + * + + CFBundleTypeName + All Files + CFBundleTypeRole + Viewer + + + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + retroarch + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.7.4 + CFBundleSignature + ???? + CFBundleVersion + 1.7.4 + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSHighResolutionCapable + + NSHumanReadableCopyright + Copyright © 2018 RetroArch. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + RApplication + + diff --git a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj index 2b2e562f91..ff6a1ed853 100644 --- a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj @@ -8,6 +8,26 @@ /* Begin PBXBuildFile section */ 05269A6220ABF20500C29F1E /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05269A6120ABF20500C29F1E /* MetalKit.framework */; }; + 05422E3E2140C8DB00F09961 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; + 05422E3F2140C8DB00F09961 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; }; + 05422E402140C8DB00F09961 /* retroarch.icns in Resources */ = {isa = PBXBuildFile; fileRef = 84DD5EB71A89F1C7007336C1 /* retroarch.icns */; }; + 05422E432140C8DB00F09961 /* griffin_glslang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D7753420A5678400646447 /* griffin_glslang.cpp */; }; + 05422E442140C8DB00F09961 /* menu_pipeline.metal in Sources */ = {isa = PBXBuildFile; fileRef = 05770B9820E805160013DABC /* menu_pipeline.metal */; }; + 05422E452140C8DB00F09961 /* griffin_cpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 05D7753320A5678300646447 /* griffin_cpp.cpp */; }; + 05422E462140C8DB00F09961 /* griffin_objc.m in Sources */ = {isa = PBXBuildFile; fileRef = 509F0C9C1AA23AFC00619ECC /* griffin_objc.m */; }; + 05422E472140C8DB00F09961 /* griffin.c in Sources */ = {isa = PBXBuildFile; fileRef = 840222FB1A889EE2009AB261 /* griffin.c */; }; + 05422E482140C8DB00F09961 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 05A8C74E20DB72F100FF7857 /* Shaders.metal */; }; + 05422E4A2140C8DB00F09961 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A8E23B20A63CF50084ABDA /* QuartzCore.framework */; }; + 05422E4B2140C8DB00F09961 /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A8E23920A63CED0084ABDA /* IOSurface.framework */; }; + 05422E4C2140C8DB00F09961 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A8E23720A63CB40084ABDA /* Metal.framework */; }; + 05422E4D2140C8DB00F09961 /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05269A6120ABF20500C29F1E /* MetalKit.framework */; }; + 05422E4E2140C8DB00F09961 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5061C8A31AE47E510080AE14 /* libz.dylib */; }; + 05422E4F2140C8DB00F09961 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84DD5EA81A89E4BE007336C1 /* CoreAudio.framework */; }; + 05422E502140C8DB00F09961 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84DD5EB21A89E6C0007336C1 /* AudioUnit.framework */; }; + 05422E512140C8DB00F09961 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84DD5EAC1A89E5B4007336C1 /* OpenGL.framework */; }; + 05422E522140C8DB00F09961 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29B97324FDCFA39411CA2CEA /* AppKit.framework */; }; + 05422E532140C8DB00F09961 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84DD5E9E1A88E45B007336C1 /* CoreVideo.framework */; }; + 05422E542140C8DB00F09961 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84DD5EB41A89E737007336C1 /* IOKit.framework */; }; 05770B9920E805160013DABC /* menu_pipeline.metal in Sources */ = {isa = PBXBuildFile; fileRef = 05770B9820E805160013DABC /* menu_pipeline.metal */; }; 05A8C7B420DB75A500FF7857 /* Shaders.metal in Sources */ = {isa = PBXBuildFile; fileRef = 05A8C74E20DB72F100FF7857 /* Shaders.metal */; }; 05A8E23820A63CB40084ABDA /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05A8E23720A63CB40084ABDA /* Metal.framework */; }; @@ -40,10 +60,47 @@ name = "Embed Libraries"; runOnlyForDeploymentPostprocessing = 0; }; + 05422E552140C8DB00F09961 /* Embed Libraries */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 6; + files = ( + ); + name = "Embed Libraries"; + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 05269A6120ABF20500C29F1E /* MetalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalKit.framework; path = System/Library/Frameworks/MetalKit.framework; sourceTree = SDKROOT; }; + 05366512213F8BE5007E7EA0 /* thumbnailpackdownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thumbnailpackdownload.cpp; sourceTree = ""; }; + 05366513213F8BE5007E7EA0 /* ui_qt_application.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_qt_application.cpp; sourceTree = ""; }; + 05366514213F8BE5007E7EA0 /* coreoptionsdialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreoptionsdialog.h; sourceTree = ""; }; + 05366515213F8BE5007E7EA0 /* viewoptionsdialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = viewoptionsdialog.h; sourceTree = ""; }; + 05366516213F8BE5007E7EA0 /* filedropwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filedropwidget.h; sourceTree = ""; }; + 05366517213F8BE5007E7EA0 /* ui_qt_load_core_window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_qt_load_core_window.cpp; sourceTree = ""; }; + 05366518213F8BE5007E7EA0 /* playlistentrydialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playlistentrydialog.cpp; sourceTree = ""; }; + 05366519213F8BE5007E7EA0 /* ui_qt_load_core_window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_qt_load_core_window.h; sourceTree = ""; }; + 0536651A213F8BE5007E7EA0 /* shaderparamsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shaderparamsdialog.cpp; sourceTree = ""; }; + 0536651B213F8BE5007E7EA0 /* ui_qt_browser_window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_qt_browser_window.cpp; sourceTree = ""; }; + 0536651C213F8BE5007E7EA0 /* ui_qt_msg_window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_qt_msg_window.cpp; sourceTree = ""; }; + 0536651D213F8BE5007E7EA0 /* flowlayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = flowlayout.h; sourceTree = ""; }; + 0536651E213F8BE5007E7EA0 /* playlistthumbnaildownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playlistthumbnaildownload.cpp; sourceTree = ""; }; + 0536651F213F8BE5007E7EA0 /* playlistentrydialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = playlistentrydialog.h; sourceTree = ""; }; + 05366520213F8BE5007E7EA0 /* coreinfodialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coreinfodialog.cpp; sourceTree = ""; }; + 05366521213F8BE5007E7EA0 /* filedropwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filedropwidget.cpp; sourceTree = ""; }; + 05366522213F8BE5007E7EA0 /* thumbnaildownload.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thumbnaildownload.cpp; sourceTree = ""; }; + 05366523213F8BE5007E7EA0 /* playlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playlist.cpp; sourceTree = ""; }; + 05366524213F8BE5007E7EA0 /* ui_qt_themes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_qt_themes.h; sourceTree = ""; }; + 05366525213F8BE5007E7EA0 /* shaderparamsdialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shaderparamsdialog.h; sourceTree = ""; }; + 05366526213F8BE5007E7EA0 /* flowlayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flowlayout.cpp; sourceTree = ""; }; + 05366527213F8BE5007E7EA0 /* viewoptionsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = viewoptionsdialog.cpp; sourceTree = ""; }; + 05366528213F8BE5007E7EA0 /* coreoptionsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coreoptionsdialog.cpp; sourceTree = ""; }; + 05366529213F8BE5007E7EA0 /* ui_qt_window.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_qt_window.cpp; sourceTree = ""; }; + 0536652A213F8BE5007E7EA0 /* invader_png.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = invader_png.h; sourceTree = ""; }; + 0536652B213F8BE5007E7EA0 /* coreinfodialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coreinfodialog.h; sourceTree = ""; }; + 0536652C213F8BE5007E7EA0 /* updateretroarch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = updateretroarch.cpp; sourceTree = ""; }; 0538874D20DDD5C600769232 /* dxgi_common.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = dxgi_common.c; sourceTree = ""; }; 0538874E20DDD5C600769232 /* dxgi_common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dxgi_common.h; sourceTree = ""; }; 0538875120DE11D200769232 /* retro_common_api.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_common_api.h; sourceTree = ""; }; @@ -55,6 +112,10 @@ 0538875720DE11D300769232 /* retro_assert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_assert.h; sourceTree = ""; }; 0538875820DE11D300769232 /* retro_endianness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_endianness.h; sourceTree = ""; }; 0538875920DE11D300769232 /* libretro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libretro.h; sourceTree = ""; }; + 05422E592140C8DB00F09961 /* RetroArchQT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArchQT.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 05422E5A2140C8DC00F09961 /* RetroArch copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "RetroArch copy-Info.plist"; path = "/Volumes/Data/projects/libretro/retroarch/pkg/apple/RetroArch copy-Info.plist"; sourceTree = ""; }; + 05422E5B2140CE3500F09961 /* VulkanConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = VulkanConfig.xcconfig; sourceTree = ""; }; + 05422E5C2140CFC500F09961 /* Metal.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Metal.xcconfig; sourceTree = ""; }; 0548E2B220F976E10094A083 /* driver.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = driver.c; path = ../../driver.c; sourceTree = ""; }; 0548E2B320F976E10094A083 /* dynamic.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = dynamic.c; path = ../../dynamic.c; sourceTree = ""; }; 0548E2B420F976E10094A083 /* dynamic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dynamic.h; path = ../../dynamic.h; sourceTree = ""; }; @@ -459,7 +520,6 @@ 089C165DFE840E0CC02AAC07 /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = OSX/en.lproj/InfoPlist.strings; sourceTree = ""; }; 1DDD58150DA1D0A300B32029 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = OSX/en.lproj/MainMenu.xib; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; - 5008453B1B89300700CE6073 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = /../../pkg/apple/OSX/Info.plist; sourceTree = SOURCE_ROOT; }; 5061C8A31AE47E510080AE14 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; 509F0C9C1AA23AFC00619ECC /* griffin_objc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = griffin_objc.m; path = ../../griffin/griffin_objc.m; sourceTree = ""; }; 840222FB1A889EE2009AB261 /* griffin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = griffin.c; path = ../../griffin/griffin.c; sourceTree = SOURCE_ROOT; }; @@ -475,9 +535,28 @@ 8D1107320486CEB800E47090 /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; }; A902040DE66D42F9EE47BFE3 /* MenuDisplay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuDisplay.h; sourceTree = ""; }; A902070F2C43F222FD56A95A /* MenuDisplay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MenuDisplay.m; sourceTree = ""; }; + A90207489289602F593626D5 /* QTConfig.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = QTConfig.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 05422E492140C8DB00F09961 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 05422E4A2140C8DB00F09961 /* QuartzCore.framework in Frameworks */, + 05422E4B2140C8DB00F09961 /* IOSurface.framework in Frameworks */, + 05422E4C2140C8DB00F09961 /* Metal.framework in Frameworks */, + 05422E4D2140C8DB00F09961 /* MetalKit.framework in Frameworks */, + 05422E4E2140C8DB00F09961 /* libz.dylib in Frameworks */, + 05422E4F2140C8DB00F09961 /* CoreAudio.framework in Frameworks */, + 05422E502140C8DB00F09961 /* AudioUnit.framework in Frameworks */, + 05422E512140C8DB00F09961 /* OpenGL.framework in Frameworks */, + 05422E522140C8DB00F09961 /* AppKit.framework in Frameworks */, + 05422E532140C8DB00F09961 /* CoreVideo.framework in Frameworks */, + 05422E542140C8DB00F09961 /* IOKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D11072E0486CEB800E47090 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -499,6 +578,40 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 05366511213F8BE5007E7EA0 /* qt */ = { + isa = PBXGroup; + children = ( + 05366520213F8BE5007E7EA0 /* coreinfodialog.cpp */, + 0536652B213F8BE5007E7EA0 /* coreinfodialog.h */, + 05366528213F8BE5007E7EA0 /* coreoptionsdialog.cpp */, + 05366514213F8BE5007E7EA0 /* coreoptionsdialog.h */, + 05366521213F8BE5007E7EA0 /* filedropwidget.cpp */, + 05366516213F8BE5007E7EA0 /* filedropwidget.h */, + 05366526213F8BE5007E7EA0 /* flowlayout.cpp */, + 0536651D213F8BE5007E7EA0 /* flowlayout.h */, + 0536652A213F8BE5007E7EA0 /* invader_png.h */, + 05366523213F8BE5007E7EA0 /* playlist.cpp */, + 05366518213F8BE5007E7EA0 /* playlistentrydialog.cpp */, + 0536651F213F8BE5007E7EA0 /* playlistentrydialog.h */, + 0536651E213F8BE5007E7EA0 /* playlistthumbnaildownload.cpp */, + 0536651A213F8BE5007E7EA0 /* shaderparamsdialog.cpp */, + 05366525213F8BE5007E7EA0 /* shaderparamsdialog.h */, + 05366522213F8BE5007E7EA0 /* thumbnaildownload.cpp */, + 05366512213F8BE5007E7EA0 /* thumbnailpackdownload.cpp */, + 05366513213F8BE5007E7EA0 /* ui_qt_application.cpp */, + 0536651B213F8BE5007E7EA0 /* ui_qt_browser_window.cpp */, + 05366517213F8BE5007E7EA0 /* ui_qt_load_core_window.cpp */, + 05366519213F8BE5007E7EA0 /* ui_qt_load_core_window.h */, + 0536651C213F8BE5007E7EA0 /* ui_qt_msg_window.cpp */, + 05366524213F8BE5007E7EA0 /* ui_qt_themes.h */, + 05366529213F8BE5007E7EA0 /* ui_qt_window.cpp */, + 0536652C213F8BE5007E7EA0 /* updateretroarch.cpp */, + 05366527213F8BE5007E7EA0 /* viewoptionsdialog.cpp */, + 05366515213F8BE5007E7EA0 /* viewoptionsdialog.h */, + ); + path = qt; + sourceTree = ""; + }; 0538874F20DE117B00769232 /* libretro-common */ = { isa = PBXGroup; children = ( @@ -797,6 +910,7 @@ isa = PBXGroup; children = ( 05A8C5BB20DB72F000FF7857 /* cocoa */, + 05366511213F8BE5007E7EA0 /* qt */, 05A8C5CE20DB72F000FF7857 /* ui_cocoa.h */, 05A8C5BA20DB72F000FF7857 /* ui_cocoa.m */, 05A8C5CF20DB72F000FF7857 /* ui_cocoatouch.m */, @@ -1283,6 +1397,7 @@ isa = PBXGroup; children = ( 8D1107320486CEB800E47090 /* RetroArch.app */, + 05422E592140C8DB00F09961 /* RetroArchQT.app */, ); name = Products; sourceTree = ""; @@ -1291,13 +1406,16 @@ isa = PBXGroup; children = ( 05D7753120A55D2700646447 /* BaseConfig.xcconfig */, + 05422E5C2140CFC500F09961 /* Metal.xcconfig */, + A90207489289602F593626D5 /* QTConfig.xcconfig */, + 05422E5B2140CE3500F09961 /* VulkanConfig.xcconfig */, 840222FA1A889EA2009AB261 /* Core */, 05A8C51920DB72C200FF7857 /* Sources */, 841CBB821A8A33810066E9F1 /* Assets */, 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, - 5008453B1B89300700CE6073 /* Info.plist */, + 05422E5A2140C8DC00F09961 /* RetroArch copy-Info.plist */, ); indentWidth = 3; name = RetroArch; @@ -1352,6 +1470,25 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + 05422E3C2140C8DB00F09961 /* RetroArchQT */ = { + isa = PBXNativeTarget; + buildConfigurationList = 05422E562140C8DB00F09961 /* Build configuration list for PBXNativeTarget "RetroArchQT" */; + buildPhases = ( + 05422E3D2140C8DB00F09961 /* Resources */, + 05422E422140C8DB00F09961 /* Sources */, + 05422E492140C8DB00F09961 /* Frameworks */, + 05422E552140C8DB00F09961 /* Embed Libraries */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RetroArchQT; + productInstallPath = "$(HOME)/Applications"; + productName = RetroArch; + productReference = 05422E592140C8DB00F09961 /* RetroArchQT.app */; + productType = "com.apple.product-type.application"; + }; 8D1107260486CEB800E47090 /* RetroArch */ = { isa = PBXNativeTarget; buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "RetroArch" */; @@ -1391,11 +1528,22 @@ projectRoot = ""; targets = ( 8D1107260486CEB800E47090 /* RetroArch */, + 05422E3C2140C8DB00F09961 /* RetroArchQT */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 05422E3D2140C8DB00F09961 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 05422E3E2140C8DB00F09961 /* InfoPlist.strings in Resources */, + 05422E3F2140C8DB00F09961 /* MainMenu.xib in Resources */, + 05422E402140C8DB00F09961 /* retroarch.icns in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D1107290486CEB800E47090 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -1409,6 +1557,19 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 05422E422140C8DB00F09961 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 05422E432140C8DB00F09961 /* griffin_glslang.cpp in Sources */, + 05422E442140C8DB00F09961 /* menu_pipeline.metal in Sources */, + 05422E452140C8DB00F09961 /* griffin_cpp.cpp in Sources */, + 05422E462140C8DB00F09961 /* griffin_objc.m in Sources */, + 05422E472140C8DB00F09961 /* griffin.c in Sources */, + 05422E482140C8DB00F09961 /* Shaders.metal in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D11072C0486CEB800E47090 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1444,8 +1605,46 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 05422E572140C8DB00F09961 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A90207489289602F593626D5 /* QTConfig.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INFOPLIST_FILE = "RetroArch copy-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES; + PRODUCT_BUNDLE_IDENTIFIER = libretro.RetroArch; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 05422E582140C8DB00F09961 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A90207489289602F593626D5 /* QTConfig.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COMBINE_HIDPI_IMAGES = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + INFOPLIST_FILE = "RetroArch copy-Info.plist"; + INSTALL_PATH = "$(HOME)/Applications"; + PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES; + PRODUCT_BUNDLE_IDENTIFIER = libretro.RetroArch; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 05422E5C2140CFC500F09961 /* Metal.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COMBINE_HIDPI_IMAGES = YES; @@ -1465,6 +1664,7 @@ }; C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 05422E5C2140CFC500F09961 /* Metal.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COMBINE_HIDPI_IMAGES = YES; @@ -1559,6 +1759,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 05422E562140C8DB00F09961 /* Build configuration list for PBXNativeTarget "RetroArchQT" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 05422E572140C8DB00F09961 /* Debug */, + 05422E582140C8DB00F09961 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "RetroArch" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/pkg/apple/VulkanConfig.xcconfig b/pkg/apple/VulkanConfig.xcconfig new file mode 100644 index 0000000000..afdca6d08d --- /dev/null +++ b/pkg/apple/VulkanConfig.xcconfig @@ -0,0 +1,20 @@ +// +// BaseConfig.xcconfig +// RetroArch +// +// Created by Stuart Carnie on 5/10/18. +// +VULKAN_PACKAGE_PATH = /Volumes/Data/projects/frameworks/vulkan/moltenvk/Package + +// macOS +VULKAN_FRAMEWORK_PATH[sdk=macosx*] = $(VULKAN_PACKAGE_PATH)/$(CONFIGURATION)/MoltenVK/macOS + +// general +FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(LOCAL_LIBRARY_DIR)/Frameworks $(VULKAN_FRAMEWORK_PATH) +LIBRARY_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(VULKAN_FRAMEWORK_PATH) + +OTHER_LDFLAGS = $(inherited) -lMoltenVK -framework MoltenVK + +OTHER_CFLAGS = $(inherited) $(QT_CFLAGS) -DHAVE_VULKAN + +LD_RUNPATH_SEARCH_PATHS = @executable_path From b4081d9347fee08a60e1e54a4ec390a3b65672b3 Mon Sep 17 00:00:00 2001 From: Sven <40953353+RetroSven@users.noreply.github.com> Date: Fri, 7 Sep 2018 19:09:56 -0400 Subject: [PATCH 025/335] implement libretro private def to allow cores to tell RA to save states in background --- core_impl.c | 2 + dynamic.c | 10 +++ retroarch.h | 2 + tasks/task_save.c | 173 ++++++++++++++++++++++++++--------------- tasks/tasks_internal.h | 2 + 5 files changed, 128 insertions(+), 61 deletions(-) diff --git a/core_impl.c b/core_impl.c index e0fc8633c8..eb4b2fffd0 100644 --- a/core_impl.c +++ b/core_impl.c @@ -43,6 +43,7 @@ #include "verbosity.h" #include "gfx/video_driver.h" #include "audio/audio_driver.h" +#include "tasks/tasks_internal.h" #ifdef HAVE_RUNAHEAD #include "runahead/copy_load_info.h" @@ -298,6 +299,7 @@ bool core_load_game(retro_ctx_load_content_info_t *load_info) #endif content_get_status(&contentless, &is_inited); + set_save_state_in_background(false); if (load_info && load_info->special) current_core.game_loaded = current_core.retro_load_game_special( diff --git a/dynamic.c b/dynamic.c index 4a91c2693b..6b35a0117d 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1387,6 +1387,16 @@ bool rarch_environment_cb(unsigned cmd, void *data) break; } + case RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND: + { + bool state = *(const bool*)data; + RARCH_LOG("Environ SET_SAVE_STATE_IN_BACKGROUND: %s.\n", state ? "yes" : "no"); + + set_save_state_in_background(state) ; + + break; + } + case RETRO_ENVIRONMENT_GET_LIBRETRO_PATH: { const char **path = (const char**)data; diff --git a/retroarch.h b/retroarch.h index 46d882deed..dda1628c29 100644 --- a/retroarch.h +++ b/retroarch.h @@ -33,6 +33,8 @@ RETRO_BEGIN_DECLS +#define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND RETRO_ENVIRONMENT_PRIVATE+1 + enum rarch_ctl_state { RARCH_CTL_NONE = 0, diff --git a/tasks/task_save.c b/tasks/task_save.c index 1b5d93be4e..650f88f2ce 100644 --- a/tasks/task_save.c +++ b/tasks/task_save.c @@ -56,6 +56,7 @@ #define SAVE_STATE_CHUNK 4096 +static bool save_state_in_background = false; static struct string_list *task_save_files = NULL; struct ram_type @@ -555,6 +556,33 @@ static void task_save_handler_finished(retro_task_t *task, free(state); } +void* get_serialized_data(const char *path, size_t serial_size) +{ + retro_ctx_serialize_info_t serial_info; + bool ret = false; + void *data = NULL; + + data = malloc(serial_size); + + if (!data) + return NULL; + + RARCH_LOG("%s: %d %s.\n", + msg_hash_to_str(MSG_STATE_SIZE), + (int)serial_size, + msg_hash_to_str(MSG_BYTES)); + + serial_info.data = data; + serial_info.size = serial_size; + ret = core_serialize(&serial_info); + if ( !ret ) + { + free(data) ; + return NULL ; + } + return data ; +} + /** * task_save_handler: * @task : the task being worked on @@ -576,9 +604,22 @@ static void task_save_handler(retro_task_t *task) return; } + if (!state->data) + { + state->data = get_serialized_data(state->path, state->size) ; + } + remaining = MIN(state->size - state->written, SAVE_STATE_CHUNK); - written = (int)intfstream_write(state->file, + + if ( state->data ) + { + written = (int)intfstream_write(state->file, (uint8_t*)state->data + state->written, remaining); + } + else + { + written = 0 ; + } state->written += written; @@ -1144,85 +1185,90 @@ error: **/ bool content_save_state(const char *path, bool save_to_disk, bool autosave) { - retro_ctx_serialize_info_t serial_info; retro_ctx_size_info_t info; bool ret = false; void *data = NULL; core_serialize_size(&info); - RARCH_LOG("%s: \"%s\".\n", - msg_hash_to_str(MSG_SAVING_STATE), - path); - if (info.size == 0) return false; - data = malloc(info.size); - - if (!data) - return false; - - RARCH_LOG("%s: %d %s.\n", - msg_hash_to_str(MSG_STATE_SIZE), - (int)info.size, - msg_hash_to_str(MSG_BYTES)); - - serial_info.data = data; - serial_info.size = info.size; - ret = core_serialize(&serial_info); - - if (ret) + if ( !save_state_in_background ) { - if (save_to_disk) - { - if (filestream_exists(path) && !autosave) - { - /* Before overwritting the savestate file, load it into a buffer - to allow undo_save_state() to work */ - /* TODO/FIXME - Use msg_hash_to_str here */ - RARCH_LOG("%s ...\n", - msg_hash_to_str(MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER)); + RARCH_LOG("%s: \"%s\".\n", + msg_hash_to_str(MSG_SAVING_STATE), + path); - task_push_load_and_save_state(path, data, info.size, true, autosave); - } - else - task_push_save_state(path, data, info.size, autosave); + data = get_serialized_data(path, info.size) ; + + + if (!data) + { + RARCH_ERR("%s \"%s\".\n", + msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), + path); + return false; + } + + RARCH_LOG("%s: %d %s.\n", + msg_hash_to_str(MSG_STATE_SIZE), + (int)info.size, + msg_hash_to_str(MSG_BYTES)); + + } + + if (save_to_disk) + { + if (filestream_exists(path) && !autosave) + { + /* Before overwritting the savestate file, load it into a buffer + to allow undo_save_state() to work */ + /* TODO/FIXME - Use msg_hash_to_str here */ + RARCH_LOG("%s ...\n", + msg_hash_to_str(MSG_FILE_ALREADY_EXISTS_SAVING_TO_BACKUP_BUFFER)); + + task_push_load_and_save_state(path, data, info.size, true, autosave); } else - { - /* save_to_disk is false, which means we are saving the state - in undo_load_buf to allow content_undo_load_state() to restore it */ - - /* If we were holding onto an old state already, clean it up first */ - if (undo_load_buf.data) - { - free(undo_load_buf.data); - undo_load_buf.data = NULL; - } - - undo_load_buf.data = malloc(info.size); - if (!undo_load_buf.data) - { - free(data); - return false; - } - - memcpy(undo_load_buf.data, data, info.size); - free(data); - undo_load_buf.size = info.size; - strlcpy(undo_load_buf.path, path, sizeof(undo_load_buf.path)); - } + task_push_save_state(path, data, info.size, autosave); } else { + if ( data == NULL ) + data = get_serialized_data(path, info.size) ; + + if ( data == NULL ) + { + RARCH_ERR("%s \"%s\".\n", + msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), + path); + return false ; + } + /* save_to_disk is false, which means we are saving the state + in undo_load_buf to allow content_undo_load_state() to restore it */ + + /* If we were holding onto an old state already, clean it up first */ + if (undo_load_buf.data) + { + free(undo_load_buf.data); + undo_load_buf.data = NULL; + } + + undo_load_buf.data = malloc(info.size); + if (!undo_load_buf.data) + { + free(data); + return false; + } + + memcpy(undo_load_buf.data, data, info.size); free(data); - RARCH_ERR("%s \"%s\".\n", - msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO), - path); + undo_load_buf.size = info.size; + strlcpy(undo_load_buf.path, path, sizeof(undo_load_buf.path)); } - return ret; + return true; } /** @@ -1546,3 +1592,8 @@ void *savefile_ptr_get(void) { return task_save_files; } + +void set_save_state_in_background(bool state) +{ + save_state_in_background = state ; +} diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index a2632e4ac8..4647a1dea1 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -267,6 +267,8 @@ bool task_push_audio_mixer_load( extern const char* const input_builtin_autoconfs[]; +void set_save_state_in_background(bool state) ; + RETRO_END_DECLS #endif From 7c2da36af93876b66522d0abcd12b2ab6513033d Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 8 Sep 2018 02:11:18 +0200 Subject: [PATCH 026/335] Prevent warning --- dynamic.c | 1 + tasks/tasks_internal.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/dynamic.c b/dynamic.c index 6b35a0117d..230ec324c2 100644 --- a/dynamic.c +++ b/dynamic.c @@ -66,6 +66,7 @@ #include "configuration.h" #include "msg_hash.h" #include "verbosity.h" +#include "tasks/tasks_internal.h" #ifdef HAVE_RUNAHEAD #include "runahead/secondary_core.h" diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 4647a1dea1..dbcf0e2963 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -265,9 +265,10 @@ bool task_push_audio_mixer_load_and_play( bool task_push_audio_mixer_load( const char *fullpath, retro_task_callback_t cb, void *user_data); +void set_save_state_in_background(bool state); + extern const char* const input_builtin_autoconfs[]; -void set_save_state_in_background(bool state) ; RETRO_END_DECLS From df059c585f45f4b4ae14295560ba8ce91e8eb4d5 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 8 Sep 2018 02:19:05 +0200 Subject: [PATCH 027/335] Implement RETRO_ENVIRONMENT_GET_FASTFORWARDING --- dynamic.c | 9 +++++++++ libretro-common/include/libretro.h | 6 ++++++ retroarch.c | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/dynamic.c b/dynamic.c index 230ec324c2..3a70ddf884 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1851,6 +1851,15 @@ bool rarch_environment_cb(unsigned cmd, void *data) } } break; + + case RETRO_ENVIRONMENT_GET_FASTFORWARDING: + { + extern bool runloop_fastmotion; + RARCH_LOG("RETRO_ENVIRONMENT_GET_FASTFORWARDING %d\n", runloop_fastmotion); + *(bool *)data = runloop_fastmotion; + } + break; + default: RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd); diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index 826283b3fa..78e67a0781 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1189,6 +1189,12 @@ struct retro_led_interface * Returns a MIDI interface that can be used for raw data I/O. */ +#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that indicates whether or not the frontend is in + * fastforwarding mode. + */ + /* Retrieves the current state of the MIDI input. * Returns true if it's enabled, false otherwise. */ typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void); diff --git a/retroarch.c b/retroarch.c index 42c8fa24b6..6b49f0e41c 100644 --- a/retroarch.c +++ b/retroarch.c @@ -238,7 +238,7 @@ static bool runloop_paused = false; static bool runloop_idle = false; static bool runloop_exec = false; static bool runloop_slowmotion = false; -static bool runloop_fastmotion = false; +bool runloop_fastmotion = false; static bool runloop_shutdown_initiated = false; static bool runloop_core_shutdown_initiated = false; static bool runloop_perfcnt_enable = false; From 4d7fe0e96cf7ae86e30961503ff4babf6e2d1019 Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Fri, 7 Sep 2018 17:38:46 -0700 Subject: [PATCH 028/335] feat(macOS): Embed Qt frameworks and frameworks to @executable_path * note that install_name_tool is used to update the frameworks via a post-build script --- pkg/apple/QTConfig.xcconfig | 3 +- pkg/apple/RetroArch copy-Info.plist | 49 ------------ .../RetroArch_Metal.xcodeproj/project.pbxproj | 79 +++++++++++++++++-- 3 files changed, 72 insertions(+), 59 deletions(-) delete mode 100644 pkg/apple/RetroArch copy-Info.plist diff --git a/pkg/apple/QTConfig.xcconfig b/pkg/apple/QTConfig.xcconfig index 01ef9d0d01..9351c4511d 100644 --- a/pkg/apple/QTConfig.xcconfig +++ b/pkg/apple/QTConfig.xcconfig @@ -8,6 +8,7 @@ QT_INSTALL = /usr/local/opt/qt QT_FRAMEWORK_PATH = $(QT_INSTALL)/lib QT_FRAMEWORKS = -framework QtWidgets -framework QtGui -framework QtConcurrent -framework QtNetwork -framework QtCore +QT_VERSION = 5 QT_HEADERS = $(QT_INSTALL)/include QT_HEADER_SEARCH_PATHS = $(QT_HEADERS) $(QT_HEADERS)/QtWidgets $(QT_HEADERS)/QtGui $(QT_HEADERS)/QtConcurrent $(QT_HEADERS)/QtNetwork $(QT_HEADERS)/QtCore @@ -16,8 +17,6 @@ QT_CFLAGS = -DHAVE_QT -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CONCURRENT // general FRAMEWORK_SEARCH_PATHS[sdk=macosx*] = $(inherited) $(QT_FRAMEWORK_PATH) -OTHER_LDFLAGS = $(inherited) $(QT_FRAMEWORKS) - OTHER_CFLAGS = $(inherited) $(QT_CFLAGS) HEADER_SEARCH_PATHS = $(inherited) $(QT_HEADER_SEARCH_PATHS) diff --git a/pkg/apple/RetroArch copy-Info.plist b/pkg/apple/RetroArch copy-Info.plist deleted file mode 100644 index a28050a571..0000000000 --- a/pkg/apple/RetroArch copy-Info.plist +++ /dev/null @@ -1,49 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleDocumentTypes - - - CFBundleTypeExtensions - - * - - CFBundleTypeName - All Files - CFBundleTypeRole - Viewer - - - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - retroarch - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.7.4 - CFBundleSignature - ???? - CFBundleVersion - 1.7.4 - LSMinimumSystemVersion - ${MACOSX_DEPLOYMENT_TARGET} - NSHighResolutionCapable - - NSHumanReadableCopyright - Copyright © 2018 RetroArch. All rights reserved. - NSMainNibFile - MainMenu - NSPrincipalClass - RApplication - - diff --git a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj index ff6a1ed853..449099d9e3 100644 --- a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj @@ -8,6 +8,16 @@ /* Begin PBXBuildFile section */ 05269A6220ABF20500C29F1E /* MetalKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05269A6120ABF20500C29F1E /* MetalKit.framework */; }; + 053FC25E21433F2200D98D46 /* QtConcurrent.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25521433F1700D98D46 /* QtConcurrent.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 053FC26021433F2200D98D46 /* QtCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25421433F1700D98D46 /* QtCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 053FC26221433F2200D98D46 /* QtGui.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25321433F1700D98D46 /* QtGui.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 053FC26421433F2200D98D46 /* QtNetwork.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25621433F1800D98D46 /* QtNetwork.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 053FC26521433F2200D98D46 /* QtWidgets.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25721433F1800D98D46 /* QtWidgets.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 053FC26621433F2200D98D46 /* QtWidgets.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25721433F1800D98D46 /* QtWidgets.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 053FC270214340F500D98D46 /* QtGui.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25321433F1700D98D46 /* QtGui.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 053FC271214340F500D98D46 /* QtNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25621433F1800D98D46 /* QtNetwork.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 053FC272214341E000D98D46 /* QtConcurrent.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25521433F1700D98D46 /* QtConcurrent.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; + 053FC275214341F000D98D46 /* QtCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 053FC25421433F1700D98D46 /* QtCore.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 05422E3E2140C8DB00F09961 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 05422E3F2140C8DB00F09961 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; }; 05422E402140C8DB00F09961 /* retroarch.icns in Resources */ = {isa = PBXBuildFile; fileRef = 84DD5EB71A89F1C7007336C1 /* retroarch.icns */; }; @@ -60,6 +70,21 @@ name = "Embed Libraries"; runOnlyForDeploymentPostprocessing = 0; }; + 053FC26721433F2200D98D46 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 053FC26021433F2200D98D46 /* QtCore.framework in Embed Frameworks */, + 053FC25E21433F2200D98D46 /* QtConcurrent.framework in Embed Frameworks */, + 053FC26621433F2200D98D46 /* QtWidgets.framework in Embed Frameworks */, + 053FC26421433F2200D98D46 /* QtNetwork.framework in Embed Frameworks */, + 053FC26221433F2200D98D46 /* QtGui.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; 05422E552140C8DB00F09961 /* Embed Libraries */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -112,8 +137,12 @@ 0538875720DE11D300769232 /* retro_assert.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_assert.h; sourceTree = ""; }; 0538875820DE11D300769232 /* retro_endianness.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = retro_endianness.h; sourceTree = ""; }; 0538875920DE11D300769232 /* libretro.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libretro.h; sourceTree = ""; }; + 053FC25321433F1700D98D46 /* QtGui.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QtGui.framework; path = /usr/local/opt/qt/lib/QtGui.framework; sourceTree = ""; }; + 053FC25421433F1700D98D46 /* QtCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QtCore.framework; path = /usr/local/opt/qt/lib/QtCore.framework; sourceTree = ""; }; + 053FC25521433F1700D98D46 /* QtConcurrent.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QtConcurrent.framework; path = /usr/local/opt/qt/lib/QtConcurrent.framework; sourceTree = ""; }; + 053FC25621433F1800D98D46 /* QtNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QtNetwork.framework; path = /usr/local/opt/qt/lib/QtNetwork.framework; sourceTree = ""; }; + 053FC25721433F1800D98D46 /* QtWidgets.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QtWidgets.framework; path = /usr/local/opt/qt/lib/QtWidgets.framework; sourceTree = ""; }; 05422E592140C8DB00F09961 /* RetroArchQT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArchQT.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 05422E5A2140C8DC00F09961 /* RetroArch copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "RetroArch copy-Info.plist"; path = "/Volumes/Data/projects/libretro/retroarch/pkg/apple/RetroArch copy-Info.plist"; sourceTree = ""; }; 05422E5B2140CE3500F09961 /* VulkanConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = VulkanConfig.xcconfig; sourceTree = ""; }; 05422E5C2140CFC500F09961 /* Metal.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Metal.xcconfig; sourceTree = ""; }; 0548E2B220F976E10094A083 /* driver.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = driver.c; path = ../../driver.c; sourceTree = ""; }; @@ -516,7 +545,6 @@ 05F2873F20F2BEEA00632D47 /* task_content.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_content.c; sourceTree = ""; }; 05F2874020F2BEEA00632D47 /* task_http.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_http.c; sourceTree = ""; }; 05F2874120F2BEEA00632D47 /* task_patch.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = task_patch.c; sourceTree = ""; }; - 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 = ""; }; 1DDD58150DA1D0A300B32029 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = MainMenu.xib; path = OSX/en.lproj/MainMenu.xib; sourceTree = ""; }; 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; @@ -543,6 +571,11 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 053FC272214341E000D98D46 /* QtConcurrent.framework in Frameworks */, + 053FC275214341F000D98D46 /* QtCore.framework in Frameworks */, + 053FC270214340F500D98D46 /* QtGui.framework in Frameworks */, + 053FC271214340F500D98D46 /* QtNetwork.framework in Frameworks */, + 053FC26521433F2200D98D46 /* QtWidgets.framework in Frameworks */, 05422E4A2140C8DB00F09961 /* QuartzCore.framework in Frameworks */, 05422E4B2140C8DB00F09961 /* IOSurface.framework in Frameworks */, 05422E4C2140C8DB00F09961 /* Metal.framework in Frameworks */, @@ -1415,7 +1448,6 @@ 29B97317FDCFA39411CA2CEA /* Resources */, 29B97323FDCFA39411CA2CEA /* Frameworks */, 19C28FACFE9D520D11CA2CBB /* Products */, - 05422E5A2140C8DC00F09961 /* RetroArch copy-Info.plist */, ); indentWidth = 3; name = RetroArch; @@ -1437,7 +1469,11 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( - 05FA11A120CC6684008C5D0A /* MetalRenderer.framework */, + 053FC25521433F1700D98D46 /* QtConcurrent.framework */, + 053FC25421433F1700D98D46 /* QtCore.framework */, + 053FC25321433F1700D98D46 /* QtGui.framework */, + 053FC25621433F1800D98D46 /* QtNetwork.framework */, + 053FC25721433F1800D98D46 /* QtWidgets.framework */, 05269A6120ABF20500C29F1E /* MetalKit.framework */, 05A8E23B20A63CF50084ABDA /* QuartzCore.framework */, 05A8E23920A63CED0084ABDA /* IOSurface.framework */, @@ -1478,6 +1514,8 @@ 05422E422140C8DB00F09961 /* Sources */, 05422E492140C8DB00F09961 /* Frameworks */, 05422E552140C8DB00F09961 /* Embed Libraries */, + 053FC26721433F2200D98D46 /* Embed Frameworks */, + 053FC27621434B7700D98D46 /* ShellScript */, ); buildRules = ( ); @@ -1556,6 +1594,23 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 053FC27621434B7700D98D46 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/zsh; + shellScript = "BINARY=${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}\nVER=Versions/${QT_VERSION}\nfor name in {QtConcurrent,QtCore,QtWidgets,QtNetwork,QtGui}; do\n echo updating install path for ${name}.framework\n install_name_tool -change ${QT_FRAMEWORK_PATH}/${name}.framework/${VER}/${name} @executable_path/../Frameworks/${name}.framework/${VER}/${name} ${BINARY}\ndone"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 05422E422140C8DB00F09961 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -1616,8 +1671,12 @@ GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_MODEL_TUNING = G5; GCC_OPTIMIZATION_LEVEL = 0; - INFOPLIST_FILE = "RetroArch copy-Info.plist"; - INSTALL_PATH = "$(HOME)/Applications"; + INFOPLIST_FILE = "$(SRCROOT)/OSX/Info.plist"; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES; PRODUCT_BUNDLE_IDENTIFIER = libretro.RetroArch; @@ -1634,8 +1693,12 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = YES; - INFOPLIST_FILE = "RetroArch copy-Info.plist"; - INSTALL_PATH = "$(HOME)/Applications"; + INFOPLIST_FILE = "$(SRCROOT)/OSX/Info.plist"; + INSTALL_PATH = "@rpath"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = YES; PRODUCT_BUNDLE_IDENTIFIER = libretro.RetroArch; PRODUCT_NAME = "$(TARGET_NAME)"; From 61d56e07fabb2eac252bdf49d102b36703c97a38 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sat, 8 Sep 2018 03:15:12 +0200 Subject: [PATCH 029/335] Don't excessively log --- dynamic.c | 1 - 1 file changed, 1 deletion(-) diff --git a/dynamic.c b/dynamic.c index 3a70ddf884..462628eb5d 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1855,7 +1855,6 @@ bool rarch_environment_cb(unsigned cmd, void *data) case RETRO_ENVIRONMENT_GET_FASTFORWARDING: { extern bool runloop_fastmotion; - RARCH_LOG("RETRO_ENVIRONMENT_GET_FASTFORWARDING %d\n", runloop_fastmotion); *(bool *)data = runloop_fastmotion; } break; From 1de3aaadeb184b695bb25ad4456bd953434c207d Mon Sep 17 00:00:00 2001 From: Stuart Carnie Date: Fri, 7 Sep 2018 20:32:57 -0700 Subject: [PATCH 030/335] chore: Call Makefile.app to generate Qt moc files --- Makefile.apple | 4 ++-- .../RetroArch_Metal.xcodeproj/project.pbxproj | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Makefile.apple b/Makefile.apple index e7f76d96e0..8e7ae5f49a 100644 --- a/Makefile.apple +++ b/Makefile.apple @@ -6,14 +6,14 @@ ifneq ($(MOC_HEADERS),) MOC_SRC := $(join $(addsuffix moc_,$(dir $(MOC_HEADERS))), $(notdir $(MOC_HEADERS:.h=.cpp))) endif -Q ?= $(error missing moc) +MOC ?= $(error missing moc path) .PHONY: generate $(MOC_SRC): @$(if $(Q), $(shell echo echo MOC $<),) $(eval MOC_TMP := $(patsubst %.h,%_moc.cpp,$@)) - $(Q)$(MOC) -o $(MOC_TMP) $< + $(MOC) -o $(MOC_TMP) $< $(foreach x,$(join $(addsuffix :,$(MOC_SRC)),$(MOC_HEADERS)),$(eval $x)) diff --git a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj index 449099d9e3..0fc5f86384 100644 --- a/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj +++ b/pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj @@ -1510,6 +1510,7 @@ isa = PBXNativeTarget; buildConfigurationList = 05422E562140C8DB00F09961 /* Build configuration list for PBXNativeTarget "RetroArchQT" */; buildPhases = ( + 053FC2782143764B00D98D46 /* ShellScript */, 05422E3D2140C8DB00F09961 /* Resources */, 05422E422140C8DB00F09961 /* Sources */, 05422E492140C8DB00F09961 /* Frameworks */, @@ -1609,6 +1610,19 @@ shellScript = "BINARY=${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}\nVER=Versions/${QT_VERSION}\nfor name in {QtConcurrent,QtCore,QtWidgets,QtNetwork,QtGui}; do\n echo updating install path for ${name}.framework\n install_name_tool -change ${QT_FRAMEWORK_PATH}/${name}.framework/${VER}/${name} @executable_path/../Frameworks/${name}.framework/${VER}/${name} ${BINARY}\ndone"; showEnvVarsInLog = 0; }; + 053FC2782143764B00D98D46 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "make -C ${SRCBASE} -f Makefile.apple HAVE_QT=1 MOC=${QT_INSTALL}/bin/moc generate"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ From af534f0fa8e77dd6dea40e797594a31ec31f9301 Mon Sep 17 00:00:00 2001 From: Themaister Date: Sun, 2 Sep 2018 16:05:45 +0200 Subject: [PATCH 031/335] Vulkan maintenance fixes. - Use VkBuffer instead of linear VkImage for staging uploads. Not guaranteed to be supported, and desktop IHVs recommend using buffers. - Fix validation error where swapchain recreation with reuse of the old VkSwapchainKHR does not create a fence properly, leading to validation error next time that swapchain index is observed. --- gfx/common/vulkan_common.c | 140 +++++++++++++++++++++++-------------- gfx/common/vulkan_common.h | 1 + gfx/drivers/vulkan.c | 44 +++++------- 3 files changed, 108 insertions(+), 77 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 7c92a96643..6dff280ce9 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -184,13 +184,12 @@ void vulkan_copy_staging_to_dynamic(vk_t *vk, VkCommandBuffer cmd, struct vk_texture *dynamic, struct vk_texture *staging) { - VkImageCopy region; + VkBufferImageCopy region; retro_assert(dynamic->type == VULKAN_TEXTURE_DYNAMIC); retro_assert(staging->type == VULKAN_TEXTURE_STAGING); vulkan_sync_texture_to_gpu(vk, staging); - vulkan_transition_texture(vk, cmd, staging); /* We don't have to sync against previous TRANSFER, * since we observed the completion by fences. @@ -208,15 +207,14 @@ void vulkan_copy_staging_to_dynamic(vk_t *vk, VkCommandBuffer cmd, VK_PIPELINE_STAGE_TRANSFER_BIT); memset(®ion, 0, sizeof(region)); - region.extent.width = dynamic->width; - region.extent.height = dynamic->height; - region.extent.depth = 1; - region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.srcSubresource.layerCount = 1; - region.dstSubresource = region.srcSubresource; + region.imageExtent.width = dynamic->width; + region.imageExtent.height = dynamic->height; + region.imageExtent.depth = 1; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; - vkCmdCopyImage(cmd, - staging->image, VK_IMAGE_LAYOUT_GENERAL, + vkCmdCopyBufferToImage(cmd, + staging->buffer, dynamic->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); @@ -323,6 +321,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk, VkSubresourceLayout layout; VkDevice device = vk->context->device; VkImageCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkBufferCreateInfo buffer_info = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; VkImageViewCreateInfo view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; VkImageSubresource subresource = { VK_IMAGE_ASPECT_COLOR_BIT }; @@ -338,6 +337,10 @@ struct vk_texture vulkan_create_texture(vk_t *vk, info.extent.height = height; info.extent.depth = 1; info.arrayLayers = 1; + info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + buffer_info.size = width * height * vulkan_format_to_bpp(format); + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; /* For simplicity, always build mipmaps for * static textures, samplers can be used to enable it dynamically. @@ -355,7 +358,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk, if (type == VULKAN_TEXTURE_STREAMED) { VkFormatProperties format_properties; - VkFormatFeatureFlags required = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | + const VkFormatFeatureFlags required = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; vkGetPhysicalDeviceFormatProperties( @@ -396,23 +399,33 @@ struct vk_texture vulkan_create_texture(vk_t *vk, break; case VULKAN_TEXTURE_STAGING: - info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + info.initialLayout = VK_IMAGE_LAYOUT_GENERAL; info.tiling = VK_IMAGE_TILING_LINEAR; - info.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; break; case VULKAN_TEXTURE_READBACK: - info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + info.initialLayout = VK_IMAGE_LAYOUT_GENERAL; info.tiling = VK_IMAGE_TILING_LINEAR; - info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; break; } - vkCreateImage(device, &info, NULL, &tex.image); + if (type != VULKAN_TEXTURE_STAGING && type != VULKAN_TEXTURE_READBACK) + { + vkCreateImage(device, &info, NULL, &tex.image); #if 0 - vulkan_track_alloc(tex.image); + vulkan_track_alloc(tex.image); #endif - vkGetImageMemoryRequirements(device, tex.image, &mem_reqs); + vkGetImageMemoryRequirements(device, tex.image, &mem_reqs); + } + else + { + /* Linear staging textures are not guaranteed to be supported, + * use buffers instead. */ + vkCreateBuffer(device, &buffer_info, NULL, &tex.buffer); + vkGetBufferMemoryRequirements(device, tex.buffer, &mem_reqs); + } alloc.allocationSize = mem_reqs.size; switch (type) @@ -449,13 +462,14 @@ struct vk_texture vulkan_create_texture(vk_t *vk, { /* Recreate texture but for STAGING this time ... */ RARCH_LOG("[Vulkan]: GPU supports linear images as textures, but not DEVICE_LOCAL. Falling back to copy path.\n"); - type = VULKAN_TEXTURE_STAGING; + type = VULKAN_TEXTURE_STAGING; vkDestroyImage(device, tex.image, NULL); + tex.image = NULL; + info.initialLayout = VK_IMAGE_LAYOUT_GENERAL; - info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - vkCreateImage(device, &info, NULL, &tex.image); - - vkGetImageMemoryRequirements(device, tex.image, &mem_reqs); + buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + vkCreateBuffer(device, &buffer_info, NULL, &tex.buffer); + vkGetBufferMemoryRequirements(device, tex.buffer, &mem_reqs); alloc.allocationSize = mem_reqs.size; alloc.memoryTypeIndex = vulkan_find_memory_type_fallback( @@ -478,6 +492,8 @@ struct vk_texture vulkan_create_texture(vk_t *vk, vulkan_track_dealloc(old->image); #endif } + if (old && old->buffer != VK_NULL_HANDLE) + vkDestroyBuffer(vk->context->device, old->buffer, NULL); /* We can pilfer the old memory and move it over to the new texture. */ if (old && @@ -507,7 +523,10 @@ struct vk_texture vulkan_create_texture(vk_t *vk, memset(old, 0, sizeof(*old)); } - vkBindImageMemory(device, tex.image, tex.memory, 0); + if (tex.image) + vkBindImageMemory(device, tex.image, tex.memory, 0); + if (tex.buffer) + vkBindBufferMemory(device, tex.buffer, tex.memory, 0); if (type != VULKAN_TEXTURE_STAGING && type != VULKAN_TEXTURE_READBACK) { @@ -532,8 +551,14 @@ struct vk_texture vulkan_create_texture(vk_t *vk, else tex.view = VK_NULL_HANDLE; - if (info.tiling == VK_IMAGE_TILING_LINEAR) + if (tex.image && info.tiling == VK_IMAGE_TILING_LINEAR) vkGetImageSubresourceLayout(device, tex.image, &subresource, &layout); + else if (tex.buffer) + { + layout.offset = 0; + layout.size = buffer_info.size; + layout.rowPitch = width * vulkan_format_to_bpp(format); + } else memset(&layout, 0, sizeof(layout)); @@ -568,7 +593,7 @@ struct vk_texture vulkan_create_texture(vk_t *vk, } else if (initial && type == VULKAN_TEXTURE_STATIC) { - VkImageCopy region; + VkBufferImageCopy region; VkCommandBuffer staging; struct vk_texture tmp = vulkan_create_texture(vk, NULL, width, height, format, initial, NULL, VULKAN_TEXTURE_STAGING); @@ -583,12 +608,6 @@ struct vk_texture vulkan_create_texture(vk_t *vk, vkBeginCommandBuffer(staging, &begin_info); - vulkan_image_layout_transition(vk, staging, tmp.image, - VK_IMAGE_LAYOUT_PREINITIALIZED, VK_IMAGE_LAYOUT_GENERAL, - VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT); - /* If doing mipmapping on upload, keep in general so we can easily do transfers to * and transfers from the images without having to * mess around with lots of extra transitions at per-level granularity. @@ -603,16 +622,14 @@ struct vk_texture vulkan_create_texture(vk_t *vk, VK_PIPELINE_STAGE_TRANSFER_BIT); memset(®ion, 0, sizeof(region)); - region.extent.width = width; - region.extent.height = height; - region.extent.depth = 1; - region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.srcSubresource.layerCount = 1; - region.dstSubresource = region.srcSubresource; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.width = width; + region.imageExtent.height = height; + region.imageExtent.depth = 1; - vkCmdCopyImage(staging, - tmp.image, - VK_IMAGE_LAYOUT_GENERAL, + vkCmdCopyBufferToImage(staging, + tmp.buffer, tex.image, tex.mipmap ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); @@ -710,12 +727,18 @@ void vulkan_destroy_texture( { if (tex->mapped) vkUnmapMemory(device, tex->memory); - vkFreeMemory(device, tex->memory, NULL); if (tex->view) vkDestroyImageView(device, tex->view, NULL); - vkDestroyImage(device, tex->image, NULL); + if (tex->image) + vkDestroyImage(device, tex->image, NULL); + if (tex->buffer) + vkDestroyBuffer(device, tex->buffer, NULL); + if (tex->memory) + vkFreeMemory(device, tex->memory, NULL); + #ifdef VULKAN_DEBUG_TEXTURE_ALLOC - vulkan_track_dealloc(tex->image); + if (tex->image) + vulkan_track_dealloc(tex->image); #endif memset(tex, 0, sizeof(*tex)); } @@ -762,6 +785,9 @@ static void vulkan_write_quad_descriptors( void vulkan_transition_texture(vk_t *vk, VkCommandBuffer cmd, struct vk_texture *texture) { + if (!texture->image) + return; + /* Transition to GENERAL layout for linear streamed textures. * We're using linear textures here, so only * GENERAL layout is supported. @@ -782,14 +808,6 @@ void vulkan_transition_texture(vk_t *vk, VkCommandBuffer cmd, struct vk_texture VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); break; - case VULKAN_TEXTURE_STAGING: - vulkan_image_layout_transition(vk, cmd, texture->image, - texture->layout, VK_IMAGE_LAYOUT_GENERAL, - VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, - VK_PIPELINE_STAGE_HOST_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT); - break; - default: retro_assert(0 && "Attempting to transition invalid texture type.\n"); break; @@ -2455,6 +2473,22 @@ static void vulkan_acquire_wait_fences(gfx_ctx_vulkan_data_t *vk) vkCreateFence(vk->context.device, &fence_info, NULL, next_fence); } +static void vulkan_create_wait_fences(gfx_ctx_vulkan_data_t *vk) +{ + VkFenceCreateInfo fence_info = + { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; + + unsigned i; + for (i = 0; i < vk->context.num_swapchain_images; i++) + { + if (!vk->context.swapchain_fences[i]) + { + vkCreateFence(vk->context.device, &fence_info, NULL, + &vk->context.swapchain_fences[i]); + } + } +} + void vulkan_acquire_next_image(gfx_ctx_vulkan_data_t *vk) { unsigned index; @@ -2577,6 +2611,7 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, /* Do not bother creating a swapchain redundantly. */ RARCH_LOG("[Vulkan]: Do not need to re-create swapchain.\n"); vk->created_new_swapchain = false; + vulkan_create_wait_fences(vk); return true; } @@ -2814,5 +2849,6 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, /* Force driver to reset swapchain image handles. */ vk->context.invalid_swapchain = true; + vulkan_create_wait_fences(vk); return true; } diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 99be52e88e..db94a08b63 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -179,6 +179,7 @@ struct vk_texture VkImage image; VkImageView view; VkDeviceMemory memory; + VkBuffer buffer; VkFormat format; diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 3d162d0118..c83254eadd 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -854,6 +854,8 @@ static void vulkan_init_static_resources(vk_t *vk) uint32_t blank[4 * 4]; VkCommandPoolCreateInfo pool_info = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO }; + pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + /* Create the pipeline cache. */ VkPipelineCacheCreateInfo cache = { VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO }; @@ -1509,23 +1511,22 @@ static void vulkan_set_viewport(void *data, unsigned viewport_width, static void vulkan_readback(vk_t *vk) { - VkImageCopy region; + VkBufferImageCopy region; struct vk_texture *staging; struct video_viewport vp; + VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER }; vulkan_viewport_info(vk, &vp); memset(®ion, 0, sizeof(region)); - region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.srcSubresource.layerCount = 1; - region.dstSubresource = region.srcSubresource; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageOffset.x = vp.x; + region.imageOffset.y = vp.y; + region.imageExtent.width = vp.width; + region.imageExtent.height = vp.height; + region.imageExtent.depth = 1; - region.srcOffset.x = vp.x; - region.srcOffset.y = vp.y; - region.extent.width = vp.width; - region.extent.height = vp.height; - region.extent.depth = 1; - - /* FIXME: We won't actually get format conversion with vkCmdCopyImage, so have to check + /* FIXME: We won't actually get format conversion with vkCmdCopyImageToBuffer, so have to check * properly for this. BGRA seems to be the default for all swapchains. */ if (vk->context->swapchain_format != VK_FORMAT_B8G8R8A8_UNORM) RARCH_WARN("[Vulkan]: Backbuffer is not BGRA8888, readbacks might not work properly.\n"); @@ -1537,25 +1538,18 @@ static void vulkan_readback(vk_t *vk) VK_FORMAT_B8G8R8A8_UNORM, NULL, NULL, VULKAN_TEXTURE_READBACK); - /* Go through the long-winded dance of remapping image layouts. */ - vulkan_image_layout_transition(vk, vk->cmd, staging->image, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, - 0, VK_ACCESS_TRANSFER_WRITE_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_TRANSFER_BIT); - - vkCmdCopyImage(vk->cmd, vk->chain->backbuffer.image, + vkCmdCopyImageToBuffer(vk->cmd, vk->chain->backbuffer.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - staging->image, - VK_IMAGE_LAYOUT_GENERAL, + staging->buffer, 1, ®ion); /* Make the data visible to host. */ - vulkan_image_layout_transition(vk, vk->cmd, staging->image, - VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, - VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT; + vkCmdPipelineBarrier(vk->cmd, VK_PIPELINE_STAGE_TRANSFER_BIT, - VK_PIPELINE_STAGE_HOST_BIT); + VK_PIPELINE_STAGE_HOST_BIT, 0, + 1, &barrier, 0, NULL, 0, NULL); } static void vulkan_inject_black_frame(vk_t *vk, video_frame_info_t *video_info) From 9ebac876385e3f521188f0e307206b0b2eda79cb Mon Sep 17 00:00:00 2001 From: Themaister Date: Sun, 2 Sep 2018 17:52:06 +0200 Subject: [PATCH 032/335] Vulkan: Emulate mailbox on Windows. --- gfx/common/vulkan_common.c | 60 +++++++++++++++++++++++++++++++++----- gfx/common/vulkan_common.h | 3 ++ gfx/drivers/vulkan.c | 3 +- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 6dff280ce9..cca8008b5c 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -38,6 +38,12 @@ #include "../../libretro-common/include/retro_math.h" #include "../../libretro-common/include/string/stdstring.h" +// Windows is not particularly good at recreating swapchains. +// Emulate vsync toggling by using vkAcquireNextImageKHR timeouts. +#if defined(_WIN32) +#define VULKAN_EMULATE_MAILBOX +#endif + static dylib_t vulkan_library; static VkInstance cached_instance_vk; static VkDevice cached_device_vk; @@ -1494,6 +1500,10 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) "VK_KHR_sampler_mirror_clamp_to_edge", }; +#ifdef VULKAN_EMULATE_MAILBOX + vk->emulate_mailbox = true; +#endif + #ifdef VULKAN_DEBUG static const char *device_layers[] = { "VK_LAYER_LUNARG_standard_validation" }; #endif @@ -2333,6 +2343,7 @@ static void vulkan_destroy_swapchain(gfx_ctx_vulkan_data_t *vk) vkDestroySwapchainKHR(vk->context.device, vk->swapchain, NULL); memset(vk->context.swapchain_images, 0, sizeof(vk->context.swapchain_images)); vk->swapchain = VK_NULL_HANDLE; + vk->context.has_acquired_swapchain = false; } for (i = 0; i < VULKAN_MAX_SWAPCHAIN_IMAGES; i++) @@ -2351,9 +2362,13 @@ static void vulkan_destroy_swapchain(gfx_ctx_vulkan_data_t *vk) void vulkan_present(gfx_ctx_vulkan_data_t *vk, unsigned index) { - VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; - VkResult result = VK_SUCCESS; - VkResult err = VK_SUCCESS; + VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR }; + VkResult result = VK_SUCCESS; + VkResult err = VK_SUCCESS; + + if (!vk->context.has_acquired_swapchain) + return; + vk->context.has_acquired_swapchain = false; /* We're still waiting for a proper swapchain, so just fake it. */ if (vk->swapchain == VK_NULL_HANDLE) @@ -2525,12 +2540,29 @@ retry: vkCreateFence(vk->context.device, &fence_info, NULL, &fence); - err = vkAcquireNextImageKHR(vk->context.device, - vk->swapchain, UINT64_MAX, - VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index); + if (vk->emulating_mailbox) + { + /* Non-blocking acquire. If we don't get a swapchain frame right away, + * just skip rendering to the swapchain this frame, similar to what + * MAILBOX would do. */ + err = vkAcquireNextImageKHR(vk->context.device, + vk->swapchain, 0, + VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index); + } + else + { + err = vkAcquireNextImageKHR(vk->context.device, + vk->swapchain, UINT64_MAX, + VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index); + } if (err == VK_SUCCESS) + { vkWaitForFences(vk->context.device, 1, &fence, true, UINT64_MAX); + vk->context.has_acquired_swapchain = true; + } + else + vk->context.has_acquired_swapchain = false; #ifdef WSI_HARDENING_TEST trigger_spurious_error_vkresult(&err); @@ -2538,7 +2570,13 @@ retry: vkDestroyFence(vk->context.device, fence, NULL); - if (err == VK_ERROR_OUT_OF_DATE_KHR) + if (err == VK_NOT_READY || err == VK_TIMEOUT) + { + /* Just pretend we have a swapchain index, round-robin style. */ + vk->context.current_swapchain_index = + (vk->context.current_swapchain_index + 1) % vk->context.num_swapchain_images; + } + else if (err == VK_ERROR_OUT_OF_DATE_KHR) { /* Throw away the old swapchain and try again. */ vulkan_destroy_swapchain(vk); @@ -2601,6 +2639,14 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, vkDeviceWaitIdle(vk->context.device); vulkan_acquire_clear_fences(vk); + if (swap_interval == 0 && vk->emulate_mailbox) + { + swap_interval = 1; + vk->emulating_mailbox = true; + } + else + vk->emulating_mailbox = false; + vk->created_new_swapchain = true; if (vk->swapchain != VK_NULL_HANDLE && !vk->context.invalid_swapchain && diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index db94a08b63..8fe426776f 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -96,6 +96,7 @@ typedef struct vulkan_context /* Used by screenshot to get blits with correct colorspace. */ bool swapchain_is_srgb; bool swap_interval_emulation_lock; + bool has_acquired_swapchain; unsigned swapchain_width; unsigned swapchain_height; @@ -131,6 +132,8 @@ typedef struct gfx_ctx_vulkan_data { bool need_new_swapchain; bool created_new_swapchain; + bool emulate_mailbox; + bool emulating_mailbox; vulkan_context_t context; VkSurfaceKHR vk_surface; VkSwapchainKHR swapchain; diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index c83254eadd..86cb84d982 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -1778,7 +1778,7 @@ static bool vulkan_frame(void *data, const void *frame, (vulkan_filter_chain_t*)vk->filter_chain, vk->cmd, &vk->vk_vp); /* Render to backbuffer. */ - if (chain->backbuffer.image != VK_NULL_HANDLE) + if (chain->backbuffer.image != VK_NULL_HANDLE && vk->context->has_acquired_swapchain) { rp_info.renderPass = vk->render_pass; rp_info.framebuffer = chain->backbuffer.framebuffer; @@ -1874,6 +1874,7 @@ static bool vulkan_frame(void *data, const void *frame, vulkan_filter_chain_end_frame((vulkan_filter_chain_t*)vk->filter_chain, vk->cmd); if (chain->backbuffer.image != VK_NULL_HANDLE && + vk->context->has_acquired_swapchain && (vk->readback.pending || vk->readback.streamed)) { /* We cannot safely read back from an image which From 66c4f8fd35c4f06a3ef255a50a09a2e10480c76a Mon Sep 17 00:00:00 2001 From: Themaister Date: Sat, 8 Sep 2018 10:52:42 +0200 Subject: [PATCH 033/335] Make sure to always clear out swapchain_fence_signalled. --- gfx/common/vulkan_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index cca8008b5c..b7565a3e9b 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -2464,8 +2464,8 @@ static void vulkan_acquire_clear_fences(gfx_ctx_vulkan_data_t *vk) vkDestroyFence(vk->context.device, vk->context.swapchain_fences[i], NULL); vk->context.swapchain_fences[i] = VK_NULL_HANDLE; - vk->context.swapchain_fences_signalled[i] = false; } + vk->context.swapchain_fences_signalled[i] = false; } } @@ -2482,10 +2482,10 @@ static void vulkan_acquire_wait_fences(gfx_ctx_vulkan_data_t *vk) if (vk->context.swapchain_fences_signalled[index]) vkWaitForFences(vk->context.device, 1, next_fence, true, UINT64_MAX); vkResetFences(vk->context.device, 1, next_fence); - vk->context.swapchain_fences_signalled[index] = false; } else vkCreateFence(vk->context.device, &fence_info, NULL, next_fence); + vk->context.swapchain_fences_signalled[index] = false; } static void vulkan_create_wait_fences(gfx_ctx_vulkan_data_t *vk) From 157d1e7e63f14f5162c4a1f3161c9f8e98786c70 Mon Sep 17 00:00:00 2001 From: Themaister Date: Sat, 8 Sep 2018 11:47:09 +0200 Subject: [PATCH 034/335] Only use mailbox emulation on AMD. --- gfx/common/vulkan_common.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index b7565a3e9b..fff238103d 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -38,6 +38,10 @@ #include "../../libretro-common/include/retro_math.h" #include "../../libretro-common/include/string/stdstring.h" +#define VENDOR_ID_AMD 0x1002 +#define VENDOR_ID_NV 0x10DE +#define VENDOR_ID_INTEL 0x8086 + // Windows is not particularly good at recreating swapchains. // Emulate vsync toggling by using vkAcquireNextImageKHR timeouts. #if defined(_WIN32) @@ -1500,10 +1504,6 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) "VK_KHR_sampler_mirror_clamp_to_edge", }; -#ifdef VULKAN_EMULATE_MAILBOX - vk->emulate_mailbox = true; -#endif - #ifdef VULKAN_DEBUG static const char *device_layers[] = { "VK_LAYER_LUNARG_standard_validation" }; #endif @@ -1578,6 +1578,13 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) vkGetPhysicalDeviceMemoryProperties(vk->context.gpu, &vk->context.memory_properties); +#ifdef VULKAN_EMULATE_MAILBOX + // AMD can emulate Mailbox on Windows, but not NV. + // Not tested on Intel. + if (vk->context.gpu_properties.vendorID == VENDOR_ID_AMD) + vk->emulate_mailbox = true; +#endif + RARCH_LOG("[Vulkan]: Using GPU: %s\n", vk->context.gpu_properties.deviceName); if (vk->context.device == VK_NULL_HANDLE) From d39f66a73827aad848c3475dd3631ea3c0bb4bf7 Mon Sep 17 00:00:00 2001 From: Themaister Date: Sat, 8 Sep 2018 15:56:49 +0200 Subject: [PATCH 035/335] Emulate mailbox by wrapping acquire in a thread. Needed on nVidia Windows since they don't support timeout == 0 ... --- gfx/common/vulkan_common.c | 153 ++++++++++++++++++++++++++++++++++--- gfx/common/vulkan_common.h | 23 ++++++ gfx/drivers/vulkan.c | 12 ++- 3 files changed, 175 insertions(+), 13 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index fff238103d..20d8ac64e0 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -42,9 +42,7 @@ #define VENDOR_ID_NV 0x10DE #define VENDOR_ID_INTEL 0x8086 -// Windows is not particularly good at recreating swapchains. -// Emulate vsync toggling by using vkAcquireNextImageKHR timeouts. -#if defined(_WIN32) +#ifdef _WIN32 #define VULKAN_EMULATE_MAILBOX #endif @@ -118,6 +116,126 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_cb( } #endif +void vulkan_emulated_mailbox_deinit(struct vulkan_emulated_mailbox *mailbox) +{ + if (mailbox->thread) + { + slock_lock(mailbox->lock); + mailbox->dead = true; + scond_signal(mailbox->cond); + slock_unlock(mailbox->lock); + sthread_join(mailbox->thread); + } + + if (mailbox->lock) + slock_free(mailbox->lock); + if (mailbox->cond) + scond_free(mailbox->cond); + + memset(mailbox, 0, sizeof(*mailbox)); +} + +VkResult vulkan_emulated_mailbox_acquire_next_image(struct vulkan_emulated_mailbox *mailbox, + unsigned *index) +{ + VkResult res; + if (mailbox->swapchain == VK_NULL_HANDLE) + return VK_ERROR_OUT_OF_DATE_KHR; + + slock_lock(mailbox->lock); + + if (!mailbox->has_pending_request) + { + mailbox->request_acquire = true; + mailbox->has_pending_request = true; + scond_signal(mailbox->cond); + } + + if (!mailbox->acquired) + { + /* Wait some arbitrary time here for good measure. + * This lets us grab the index from mailbox_begin_acquire early. */ + scond_wait_timeout(mailbox->cond, mailbox->lock, 1000); + } + + if (mailbox->acquired) + { + res = mailbox->result; + *index = mailbox->index; + mailbox->has_pending_request = false; + } + else + res = VK_TIMEOUT; + + mailbox->acquired = false; + slock_unlock(mailbox->lock); + return res; +} + +static void vulkan_emulated_mailbox_loop(void *userdata) +{ + VkResult res; + VkFence fence; + VkFenceCreateInfo info = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO }; + struct vulkan_emulated_mailbox *mailbox = + (struct vulkan_emulated_mailbox *)userdata; + + vkCreateFence(mailbox->device, &info, NULL, &fence); + + for (;;) + { + slock_lock(mailbox->lock); + while (!mailbox->dead && !mailbox->request_acquire) + scond_wait(mailbox->cond, mailbox->lock); + + if (mailbox->dead) + { + slock_unlock(mailbox->lock); + break; + } + + mailbox->request_acquire = false; + slock_unlock(mailbox->lock); + + mailbox->result = vkAcquireNextImageKHR(mailbox->device, mailbox->swapchain, UINT64_MAX, + VK_NULL_HANDLE, fence, &mailbox->index); + + if (mailbox->result == VK_SUCCESS) + vkWaitForFences(mailbox->device, 1, &fence, true, UINT64_MAX); + vkResetFences(mailbox->device, 1, &fence); + + if (mailbox->result == VK_SUCCESS) + { + slock_lock(mailbox->lock); + mailbox->acquired = true; + scond_signal(mailbox->cond); + slock_unlock(mailbox->lock); + } + } + + vkDestroyFence(mailbox->device, fence, NULL); +} + +bool vulkan_emulated_mailbox_init(struct vulkan_emulated_mailbox *mailbox, + VkDevice device, + VkSwapchainKHR swapchain) +{ + memset(mailbox, 0, sizeof(*mailbox)); + mailbox->device = device; + mailbox->swapchain = swapchain; + + mailbox->cond = scond_new(); + if (!mailbox->cond) + return false; + mailbox->lock = slock_new(); + if (!mailbox->lock) + return false; + mailbox->thread = sthread_create(vulkan_emulated_mailbox_loop, mailbox); + if (!mailbox->thread) + return false; + return true; +} + uint32_t vulkan_find_memory_type( const VkPhysicalDeviceMemoryProperties *mem_props, uint32_t device_reqs, uint32_t host_reqs) @@ -1579,10 +1697,13 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) &vk->context.memory_properties); #ifdef VULKAN_EMULATE_MAILBOX + /* // AMD can emulate Mailbox on Windows, but not NV. // Not tested on Intel. if (vk->context.gpu_properties.vendorID == VENDOR_ID_AMD) vk->emulate_mailbox = true; + */ + vk->emulate_mailbox = true; #endif RARCH_LOG("[Vulkan]: Using GPU: %s\n", vk->context.gpu_properties.deviceName); @@ -2344,6 +2465,7 @@ static void vulkan_destroy_swapchain(gfx_ctx_vulkan_data_t *vk) { unsigned i; + vulkan_emulated_mailbox_deinit(&vk->mailbox); if (vk->swapchain != VK_NULL_HANDLE) { vkDeviceWaitIdle(vk->context.device); @@ -2545,19 +2667,17 @@ retry: } } - vkCreateFence(vk->context.device, &fence_info, NULL, &fence); - if (vk->emulating_mailbox) { /* Non-blocking acquire. If we don't get a swapchain frame right away, * just skip rendering to the swapchain this frame, similar to what * MAILBOX would do. */ - err = vkAcquireNextImageKHR(vk->context.device, - vk->swapchain, 0, - VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index); + err = vulkan_emulated_mailbox_acquire_next_image(&vk->mailbox, &vk->context.current_swapchain_index); + fence = VK_NULL_HANDLE; } else { + vkCreateFence(vk->context.device, &fence_info, NULL, &fence); err = vkAcquireNextImageKHR(vk->context.device, vk->swapchain, UINT64_MAX, VK_NULL_HANDLE, fence, &vk->context.current_swapchain_index); @@ -2565,7 +2685,8 @@ retry: if (err == VK_SUCCESS) { - vkWaitForFences(vk->context.device, 1, &fence, true, UINT64_MAX); + if (fence != VK_NULL_HANDLE) + vkWaitForFences(vk->context.device, 1, &fence, true, UINT64_MAX); vk->context.has_acquired_swapchain = true; } else @@ -2575,7 +2696,8 @@ retry: trigger_spurious_error_vkresult(&err); #endif - vkDestroyFence(vk->context.device, fence, NULL); + if (fence != VK_NULL_HANDLE) + vkDestroyFence(vk->context.device, fence, NULL); if (err == VK_NOT_READY || err == VK_TIMEOUT) { @@ -2665,9 +2787,16 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, RARCH_LOG("[Vulkan]: Do not need to re-create swapchain.\n"); vk->created_new_swapchain = false; vulkan_create_wait_fences(vk); + + if (vk->emulating_mailbox && vk->mailbox.swapchain == VK_NULL_HANDLE) + vulkan_emulated_mailbox_init(&vk->mailbox, vk->context.device, vk->swapchain); + else if (!vk->emulating_mailbox && vk->mailbox.swapchain != VK_NULL_HANDLE) + vulkan_emulated_mailbox_deinit(&vk->mailbox); return true; } + vulkan_emulated_mailbox_deinit(&vk->mailbox); + present_mode_count = 0; vkGetPhysicalDeviceSurfacePresentModesKHR( vk->context.gpu, vk->vk_surface, @@ -2903,5 +3032,9 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, /* Force driver to reset swapchain image handles. */ vk->context.invalid_swapchain = true; vulkan_create_wait_fences(vk); + + if (vk->emulating_mailbox) + vulkan_emulated_mailbox_init(&vk->mailbox, vk->context.device, vk->swapchain); + return true; } diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 8fe426776f..5e340abbcb 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -128,6 +128,27 @@ typedef struct vulkan_context #endif } vulkan_context_t; +struct vulkan_emulated_mailbox +{ + sthread_t *thread; + VkDevice device; + VkSwapchainKHR swapchain; + slock_t *lock; + scond_t *cond; + + unsigned index; + bool acquired; + bool request_acquire; + bool dead; + bool has_pending_request; + VkResult result; +}; + +bool vulkan_emulated_mailbox_init(struct vulkan_emulated_mailbox *mailbox, + VkDevice device, VkSwapchainKHR swapchain); +void vulkan_emulated_mailbox_deinit(struct vulkan_emulated_mailbox *mailbox); +VkResult vulkan_emulated_mailbox_acquire_next_image(struct vulkan_emulated_mailbox *mailbox, unsigned *index); + typedef struct gfx_ctx_vulkan_data { bool need_new_swapchain; @@ -137,6 +158,8 @@ typedef struct gfx_ctx_vulkan_data vulkan_context_t context; VkSurfaceKHR vk_surface; VkSwapchainKHR swapchain; + + struct vulkan_emulated_mailbox mailbox; } gfx_ctx_vulkan_data_t; struct vulkan_display_surface_info diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 86cb84d982..1a16453420 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -1906,7 +1906,8 @@ static bool vulkan_frame(void *data, const void *frame, vk->readback.pending = false; } - else if (chain->backbuffer.image != VK_NULL_HANDLE) + else if (chain->backbuffer.image != VK_NULL_HANDLE && + vk->context->has_acquired_swapchain) { /* Prepare backbuffer for presentation. */ vulkan_image_layout_transition(vk, vk->cmd, @@ -1966,8 +1967,11 @@ static bool vulkan_frame(void *data, const void *frame, submit_info.signalSemaphoreCount = 0; - if (vk->context->swapchain_semaphores[frame_index] != VK_NULL_HANDLE) + if (vk->context->swapchain_semaphores[frame_index] != VK_NULL_HANDLE && + vk->context->has_acquired_swapchain) + { signal_semaphores[submit_info.signalSemaphoreCount++] = vk->context->swapchain_semaphores[frame_index]; + } if (vk->hw.signal_semaphore != VK_NULL_HANDLE) { @@ -2009,7 +2013,9 @@ static bool vulkan_frame(void *data, const void *frame, /* Disable BFI during fast forward, slow-motion, * and pause to prevent flicker. */ if ( - video_info->black_frame_insertion + chain->backbuffer.image != VK_NULL_HANDLE + && vk->context->has_acquired_swapchain + && video_info->black_frame_insertion && !video_info->input_driver_nonblock_state && !video_info->runloop_is_slowmotion && !video_info->runloop_is_paused) From d338dac2770c290a79bd1045d2da3b22d7a4596c Mon Sep 17 00:00:00 2001 From: Themaister Date: Sat, 8 Sep 2018 16:27:25 +0200 Subject: [PATCH 036/335] Only do mailbox emulation for fullscreen. Too large impact on performance in Windowed mode. --- gfx/common/vulkan_common.c | 22 +++++++--------------- gfx/common/vulkan_common.h | 3 +++ gfx/drivers_context/wgl_ctx.c | 2 ++ 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 20d8ac64e0..42779d75c8 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -96,6 +96,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_cb( RARCH_ERR("[Vulkan]: Error: %s: %s\n", pLayerPrefix, pMessage); } +#if 0 else if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { RARCH_WARN("[Vulkan]: Warning: %s: %s\n", @@ -111,6 +112,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL vulkan_debug_cb( RARCH_LOG("[Vulkan]: Information: %s: %s\n", pLayerPrefix, pMessage); } +#endif return VK_FALSE; } @@ -147,27 +149,21 @@ VkResult vulkan_emulated_mailbox_acquire_next_image(struct vulkan_emulated_mailb if (!mailbox->has_pending_request) { mailbox->request_acquire = true; - mailbox->has_pending_request = true; scond_signal(mailbox->cond); } - if (!mailbox->acquired) - { - /* Wait some arbitrary time here for good measure. - * This lets us grab the index from mailbox_begin_acquire early. */ - scond_wait_timeout(mailbox->cond, mailbox->lock, 1000); - } + mailbox->has_pending_request = true; if (mailbox->acquired) { res = mailbox->result; *index = mailbox->index; mailbox->has_pending_request = false; + mailbox->acquired = false; } else res = VK_TIMEOUT; - mailbox->acquired = false; slock_unlock(mailbox->lock); return res; } @@ -1697,13 +1693,9 @@ static bool vulkan_context_init_device(gfx_ctx_vulkan_data_t *vk) &vk->context.memory_properties); #ifdef VULKAN_EMULATE_MAILBOX - /* - // AMD can emulate Mailbox on Windows, but not NV. - // Not tested on Intel. - if (vk->context.gpu_properties.vendorID == VENDOR_ID_AMD) - vk->emulate_mailbox = true; - */ - vk->emulate_mailbox = true; + /* Win32 windowed mode seems to deal just fine with toggling VSync. + * Fullscreen however ... */ + vk->emulate_mailbox = vk->fullscreen; #endif RARCH_LOG("[Vulkan]: Using GPU: %s\n", vk->context.gpu_properties.deviceName); diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 5e340abbcb..e42d137fec 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -160,6 +160,9 @@ typedef struct gfx_ctx_vulkan_data VkSwapchainKHR swapchain; struct vulkan_emulated_mailbox mailbox; + /* Used to check if we need to use mailbox emulation or not. + * Only relevant on Windows for now. */ + bool fullscreen; } gfx_ctx_vulkan_data_t; struct vulkan_display_surface_info diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index 88341b70ab..6a1db88800 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -584,6 +584,8 @@ static bool gfx_ctx_wgl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { + win32_vk.fullscreen = fullscreen; + if (!win32_set_video_mode(NULL, width, height, fullscreen)) { RARCH_ERR("[WGL]: win32_set_video_mode failed.\n"); From 18e249e85e6dfff659b0da809051fe7766187e5c Mon Sep 17 00:00:00 2001 From: bparker06 Date: Sat, 8 Sep 2018 12:04:05 -0400 Subject: [PATCH 037/335] travis: install Qt for OSX --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8cce088599..ebf6c88258 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,7 @@ matrix: osx_image: xcode9.3 script: - cd ~/ + - brew install --force-bottle qt5 - git clone --depth=50 https://github.com/libretro/libretro-super - cd libretro-super/travis - ./build-retroarch-metal.sh From 952b46f2c18859973e78bca102d864d02b69cbd5 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Sat, 8 Sep 2018 22:09:30 +0100 Subject: [PATCH 038/335] Fix for crt interlaced bug --- gfx/video_driver.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 37efe7b01a..fad1e5b3a5 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -3232,14 +3232,26 @@ bool video_context_driver_get_metrics(gfx_ctx_metrics_t *metrics) bool video_context_driver_get_refresh_rate(float *refresh_rate) { + float refresh_holder = 0; + if (!current_video_context.get_refresh_rate || !refresh_rate) return false; if (!video_context_data) return false; - - if (refresh_rate) - *refresh_rate = - current_video_context.get_refresh_rate(video_context_data); + + if (!video_driver_crt_switching_active) + if (refresh_rate) + *refresh_rate = + current_video_context.get_refresh_rate(video_context_data); + + if (video_driver_crt_switching_active) + { + if (refresh_rate) + refresh_holder = + current_video_context.get_refresh_rate(video_context_data); + if (refresh_holder != video_driver_core_hz) /* Fix for incorrect interlace detsction -- HARD SET VSNC TO REQUIRED REFRESH FOR CRT*/ + *refresh_rate = video_driver_core_hz; + } return true; } From 5c6fc6db7e7fa61ce82ca0afc928b0b5a6914f69 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Sat, 8 Sep 2018 22:11:31 +0100 Subject: [PATCH 039/335] New Porch Calc, Matched against an oscilloscope --- gfx/display_servers/dispserv_x11.c | 104 +++++++++++++++++++---------- 1 file changed, 67 insertions(+), 37 deletions(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index dbc22ece98..9506dc8d07 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -23,8 +23,13 @@ #include "../video_driver.h" /* needed to set refresh rate in set resolution */ #include "../video_crt_switch.h" /* needed to set aspect for low res in linux */ +static unsigned orig_width = 0; +static unsigned orig_height = 0; static char old_mode[150]; static char new_mode[150]; +static char xrandr[250]; +static char fbset[150]; +static char output[250]; static bool crt_en = false; typedef struct @@ -45,10 +50,28 @@ static void* x11_display_server_init(void) static void x11_display_server_destroy(void *data) { - dispserv_x11_t *dispserv = (dispserv_x11_t*)data; - + dispserv_x11_t *dispserv = (dispserv_x11_t*)data; + int i = 0; if (crt_en == true) - system("xrandr -s 704x480"); + { + sprintf(output,"xrandr -s %dx%d", orig_width, orig_height); + system(output); + } + for (i =0; i < 3; i++) + { + sprintf(output,"xrandr --delmode %s%d %s", "VGA",i ,old_mode); + system(output); + sprintf(output,"xrandr --delmode %s-%d %s", "VGA",i ,old_mode); + system(output); + + sprintf(output,"xrandr --delmode %s%d %s", "DVI",i ,old_mode); + system(output); + sprintf(output,"xrandr --delmode %s-%d %s", "DVI",i ,old_mode); + system(output); + + } + sprintf(output,"xrandr --rmmode %s", old_mode); + system(output); if (dispserv) free(dispserv); @@ -95,22 +118,41 @@ static bool x11_set_resolution(void *data, int vbp = 0; int hmax = 0; int vmax = 0; + int pdefault = 8; + int pwidth = 0; + float roundw = 0.0f; + float roundh = 0.0f; float pixel_clock = 0; - char xrandr[250]; - char fbset[150]; - char output[250]; crt_en = true; - - hsp = width*1.16; /* set core refresh from hz */ video_monitor_set_refresh_rate(hz); - /* following code is the mode line genorator */ + /* following code is the mode line genorator */ - hfp = width+8; - hbp = width*1.32; + hsp = width*1.145; + hfp = width*1.025; + + pwidth = width; + + if (height < 400 && width > 400 ) + pwidth = width/2; + + + roundw = roundf((float)pwidth/(float)height * 100)/100; + + if (height > width ) { + roundw = roundf((float)height/(float)width * 100)/100; + } + + if (roundw > 1.35) + roundw = 1.25; + + if (roundw < 1.20) + roundw = 1.34; + + hbp = width*roundw-8; hmax = hbp; if (height < 241) @@ -133,22 +175,18 @@ static bool x11_set_resolution(void *data, { vmax = 285; } - if (height > 240 && height < 260 && hz < 52) - { - vmax = 265; - } if (height > 250 && height < 260 && hz < 52) { vmax = 313; } if (height > 260 && height < 300) { - vmax = 313; + vmax = 318; } if (height > 400 && hz > 56) { - vmax = 523; + vmax = 533; } if (height > 520 && hz < 57) { @@ -157,35 +195,27 @@ static bool x11_set_resolution(void *data, if (height > 300 && hz < 56) { - vmax = 627; + vmax = 615; } - - if (hz < 53) - { - vfp = height+((vmax-height)*0.38); + if (height > 500 && hz < 56) + { + vmax = 624; } - if (hz > 56) - { - vfp = height+((vmax-height)*0.15); - } - if (hz > 53 && hz < 56) - { - vfp = height+((vmax-height)*0.35); + if (height > 300) + { + pdefault = pdefault*2; } - - if ( vfp < 1 ) - { - vfp = height+2; - - } + + vfp = height+((vmax-height)/2)-pdefault; if (height < 300) { vsp = vfp+3; /* needs to me 3 for progressive */ - } if (height > 300) + } + if (height > 300) { - vsp = vfp+6; /* needs to me 6 for interlaced */ + vsp = vfp+6; /* needs to me 6 for interlaced */ } vbp = vmax; From bfdb75a30ea22bc8ef717225118cdd65077e4615 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 9 Sep 2018 01:28:09 +0200 Subject: [PATCH 040/335] Add ifdef --- gfx/drivers_context/wgl_ctx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index 6a1db88800..bf991fd8c6 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -584,7 +584,9 @@ static bool gfx_ctx_wgl_set_video_mode(void *data, unsigned width, unsigned height, bool fullscreen) { +#ifdef HAVE_VULKAN win32_vk.fullscreen = fullscreen; +#endif if (!win32_set_video_mode(NULL, width, height, fullscreen)) { From 9344391bfadc5b3fd43b823acd1c7a8df43f16d4 Mon Sep 17 00:00:00 2001 From: Ash Date: Sun, 9 Sep 2018 18:22:48 +1000 Subject: [PATCH 041/335] WiiU: Fix missing "#include " in sd_fat_devoptab --- wiiu/fs/sd_fat_devoptab.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wiiu/fs/sd_fat_devoptab.c b/wiiu/fs/sd_fat_devoptab.c index 27d1647906..9bc16f8e20 100644 --- a/wiiu/fs/sd_fat_devoptab.c +++ b/wiiu/fs/sd_fat_devoptab.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include From 751ad68c501b17abfefefdcec11db71f99bcf906 Mon Sep 17 00:00:00 2001 From: Ash Date: Sun, 9 Sep 2018 18:29:42 +1000 Subject: [PATCH 042/335] deps/libiosuhax: Fix missing "#include " --- deps/libiosuhax/iosuhax_devoptab.c | 1 + 1 file changed, 1 insertion(+) diff --git a/deps/libiosuhax/iosuhax_devoptab.c b/deps/libiosuhax/iosuhax_devoptab.c index b468e118fe..4d59d6ae73 100644 --- a/deps/libiosuhax/iosuhax_devoptab.c +++ b/deps/libiosuhax/iosuhax_devoptab.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include From cf4fff8d31761e7bfdcaf7e7317b76dace22c5fe Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Sun, 9 Sep 2018 11:51:37 +0100 Subject: [PATCH 043/335] snprintf broke switching --- gfx/display_servers/dispserv_x11.c | 72 ++++++++++++++++++------------ 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 9506dc8d07..d049d63d66 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -25,8 +25,8 @@ static unsigned orig_width = 0; static unsigned orig_height = 0; -static char old_mode[150]; -static char new_mode[150]; +static char old_mode[250]; +static char new_mode[250]; static char xrandr[250]; static char fbset[150]; static char output[250]; @@ -234,58 +234,74 @@ static bool x11_set_resolution(void *data, /* create progressive newmode from modline variables */ if (height < 300) { - snprintf(xrandr, sizeof(xrandr), "xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); + sprintf(xrandr,"xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); system(xrandr); } /* create interlaced newmode from modline variables */ if (height > 300) { - snprintf(xrandr, sizeof(xrandr), "xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d interlace -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); + sprintf(xrandr,"xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d interlace -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); system(xrandr); } /* variable for new mode */ - snprintf(new_mode, sizeof(new_mode), "%dx%d_%0.2f", width, height, hz); + sprintf(new_mode,"%dx%d_%0.2f", width, height, hz); /* need to run loops for DVI0 - DVI-2 and VGA0 - VGA-2 outputs to add and delete modes */ for (i =0; i < 3; i++) { - snprintf(output, sizeof(output), "xrandr --addmode %s%d %s", "DVI",i ,new_mode); + sprintf(output,"xrandr --addmode %s%d %s", "HDMI",i ,new_mode); system(output); - snprintf(output, sizeof(output), "xrandr --delmode %s%d %s", "DVI",i ,old_mode); + sprintf(output,"xrandr --output %s%d --mode %s", "HDMI", i, new_mode); + system(output); + sprintf(output,"xrandr --delmode %s%d %s", "HDMI",i ,old_mode); system(output); - } - for (i =0; i < 3; i++) - { - snprintf(output, sizeof(output), "xrandr --addmode %s-%d %s", "DVI",i ,new_mode); - system(output); - snprintf(output, sizeof(output), "xrandr --delmode %s-%d %s", "DVI",i ,old_mode); + + sprintf(output,"xrandr --addmode %s-%d %s", "HDMI",i ,new_mode); system(output); - } - for (i =0; i < 3; i++) - { - snprintf(output, sizeof(output), "xrandr --addmode %s%d %s", "VGA",i ,new_mode); - system(output); - snprintf(output, sizeof(output), "xrandr --delmode %s%d %s", "VGA",i ,old_mode); + sprintf(output,"xrandr --output %s-%d --mode %s", "HDMI", i, new_mode); + system(output); + sprintf(output,"xrandr --delmode %s-%d %s", "HDMI",i ,old_mode); + system(output); + + sprintf(output,"xrandr --addmode %s%d %s", "DVI",i ,new_mode); system(output); - } - for (i =0; i < 3; i++) - { - snprintf(output, sizeof(output), "xrandr --addmode %s-%d %s", "VGA",i ,new_mode); + sprintf(output,"xrandr --output %s%d --mode %s", "DVI", i, new_mode); + system(output); + sprintf(output,"xrandr --delmode %s%d %s", "DVI",i ,old_mode); system(output); - snprintf(output, sizeof(output), "xrandr --delmode %s-%d %s", "VGA",i ,old_mode); + + sprintf(output,"xrandr --addmode %s-%d %s", "DVI",i ,new_mode); system(output); + sprintf(output,"xrandr --output %s-%d --mode %s", "DVI", i, new_mode); + system(output); + sprintf(output,"xrandr --delmode %s-%d %s", "DVI",i ,old_mode); + system(output); + + sprintf(output,"xrandr --addmode %s%d %s", "VGA",i ,new_mode); + system(output); + sprintf(output,"xrandr --output %s%d --mode %s", "VGA", i, new_mode); + system(output); + sprintf(output,"xrandr --delmode %s%d %s", "VGA",i ,old_mode); + system(output); + + sprintf(output,"xrandr --addmode %s-%d %s", "VGA",i ,new_mode); + system(output); + sprintf(output,"xrandr --output %s-%d --mode %s", "VGA", i, new_mode); + system(output); + sprintf(output,"xrandr --delmode %s-%d %s", "VGA",i ,old_mode); + system(output); + } - snprintf(output, sizeof(output), "xrandr -s %s", new_mode); - system(output); + /* remove old mode */ - snprintf(output, sizeof(output), "xrandr --rmmode %s", old_mode); + sprintf(output,"xrandr --rmmode %s", old_mode); system(output); system("xdotool windowactivate $(xdotool search --class RetroArch)"); /* needs xdotool installed. needed to recaputure window. */ /* variable for old mode */ - snprintf(old_mode, sizeof(old_mode), "%s", new_mode); + sprintf(old_mode,"%s", new_mode); system("xdotool windowactivate $(xdotool search --class RetroArch)"); /* needs xdotool installed. needed to recaputure window. */ /* Second run needed as some times it runs to fast to capture first time */ From 1b4439413caa5473a082773e466f1484a21d2b34 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Sun, 9 Sep 2018 12:50:28 +0100 Subject: [PATCH 044/335] Update dispserv_x11.c --- gfx/display_servers/dispserv_x11.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index d049d63d66..045479b485 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -131,8 +131,8 @@ static bool x11_set_resolution(void *data, /* following code is the mode line genorator */ - hsp = width*1.145; - hfp = width*1.025; + hsp = width*1.140; + hfp = width*1.045; pwidth = width; From 0576c516c4ea6a61792362f5cb89ac38b65185a1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 9 Sep 2018 17:44:03 -0700 Subject: [PATCH 045/335] camera: Fix v4l2 driver that broke years ago --- camera/drivers/video4linux2.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/camera/drivers/video4linux2.c b/camera/drivers/video4linux2.c index 1fa94fcfa6..4ec06dcd5f 100644 --- a/camera/drivers/video4linux2.c +++ b/camera/drivers/video4linux2.c @@ -70,7 +70,7 @@ typedef struct video4linux char dev_name[255]; } video4linux_t; -static int xioctl(int fd, int request, void *args) +static int xioctl(int fd, unsigned long request, void *args) { int r; @@ -91,7 +91,7 @@ static bool init_mmap(void *data) req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; req.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l->fd, (uint8_t)VIDIOC_REQBUFS, &req) == -1) + if (xioctl(v4l->fd, VIDIOC_REQBUFS, &req) == -1) { if (errno == EINVAL) RARCH_ERR("[V4L2]: %s does not support memory mapping.\n", v4l->dev_name); @@ -122,7 +122,7 @@ static bool init_mmap(void *data) buf.memory = V4L2_MEMORY_MMAP; buf.index = v4l->n_buffers; - if (xioctl(v4l->fd, (uint8_t)VIDIOC_QUERYBUF, &buf) == -1) + if (xioctl(v4l->fd, VIDIOC_QUERYBUF, &buf) == -1) { RARCH_ERR("[V4L2]: Error - xioctl VIDIOC_QUERYBUF.\n"); return false; @@ -152,7 +152,7 @@ static bool init_device(void *data) struct v4l2_cropcap cropcap = {0}; video4linux_t *v4l = (video4linux_t*)data; - if (xioctl(v4l->fd, (uint8_t)VIDIOC_QUERYCAP, &cap) < 0) + if (xioctl(v4l->fd, VIDIOC_QUERYCAP, &cap) < 0) { if (errno == EINVAL) RARCH_ERR("[V4L2]: %s is no V4L2 device.\n", v4l->dev_name); @@ -176,7 +176,7 @@ static bool init_device(void *data) cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (xioctl(v4l->fd, (uint8_t)VIDIOC_CROPCAP, &cropcap) == 0) + if (xioctl(v4l->fd, VIDIOC_CROPCAP, &cropcap) == 0) { crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; crop.c = cropcap.defrect; @@ -190,7 +190,7 @@ static bool init_device(void *data) fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; fmt.fmt.pix.field = V4L2_FIELD_NONE; - if (xioctl(v4l->fd, (uint8_t)VIDIOC_S_FMT, &fmt) < 0) + if (xioctl(v4l->fd, VIDIOC_S_FMT, &fmt) < 0) { RARCH_ERR("[V4L2]: Error - VIDIOC_S_FMT\n"); return false; @@ -248,7 +248,7 @@ static bool v4l_start(void *data) buf.memory = V4L2_MEMORY_MMAP; buf.index = i; - if (xioctl(v4l->fd, (uint8_t)VIDIOC_QBUF, &buf) == -1) + if (xioctl(v4l->fd, VIDIOC_QBUF, &buf) == -1) { RARCH_ERR("[V4L2]: Error - VIDIOC_QBUF.\n"); return false; @@ -364,7 +364,7 @@ static bool preprocess_image(void *data) buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; - if (xioctl(v4l->fd, (uint8_t)VIDIOC_DQBUF, &buf) == -1) + if (xioctl(v4l->fd, VIDIOC_DQBUF, &buf) == -1) { switch (errno) { @@ -384,7 +384,7 @@ static bool preprocess_image(void *data) scaler_ctx_scale_direct(ctx, v4l->buffer_output, (const uint8_t*)v4l->buffers[buf.index].start); - if (xioctl(v4l->fd, (uint8_t)VIDIOC_QBUF, &buf) == -1) + if (xioctl(v4l->fd, VIDIOC_QBUF, &buf) == -1) RARCH_ERR("[V4L2]: VIDIOC_QBUF\n"); return true; From 3a0c450e7032774c2e057971f959c23c7b2a6d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Zumer?= Date: Sun, 9 Sep 2018 08:44:41 -0400 Subject: [PATCH 046/335] Support headerless NES hashing in cheevos.c --- cheevos/cheevos.c | 80 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 24 deletions(-) diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index 0e21e3687a..b61fe2ca5a 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -3001,16 +3001,11 @@ found: memcpy((void*)&coro->header, coro->data, sizeof(coro->header)); - - if ( coro->header.id[0] != 'N' - || coro->header.id[1] != 'E' - || coro->header.id[2] != 'S' - || coro->header.id[3] != 0x1a) - { - coro->gameid = 0; - CORO_RET(); - } - + + if (coro->header.id[0] == 'N' + && coro->header.id[1] == 'E' + && coro->header.id[2] == 'S' + && coro->header.id[3] == 0x1a) { size_t romsize = 256; /* from FCEU core - compute size using the cart mapper */ @@ -3026,24 +3021,61 @@ found: * we use FCEU_read. */ coro->round = mapper != 53 && mapper != 198 && mapper != 228; coro->bytes = coro->round ? romsize : coro->header.rom_size; - } - - /* from FCEU core - check if Trainer included in ROM data */ - MD5_Init(&coro->md5); - coro->offset = sizeof(coro->header) + (coro->header.rom_type & 4 + + coro->offset = sizeof(coro->header) + (coro->header.rom_type & 4 ? sizeof(coro->header) : 0); - coro->count = 0x4000 * coro->bytes; - CORO_GOSUB(EVAL_MD5); + + /* from FCEU core - check if Trainer included in ROM data */ + MD5_Init(&coro->md5); + coro->count = 0x4000 * coro->bytes; + CORO_GOSUB(EVAL_MD5); - if (coro->count < 0x4000 * coro->bytes) - { - coro->offset = 0xff; - coro->count = 0x4000 * coro->bytes - coro->count; - CORO_GOSUB(FILL_MD5); + if (coro->count < 0x4000 * coro->bytes) + { + coro->offset = 0xff; + coro->count = 0x4000 * coro->bytes - coro->count; + CORO_GOSUB(FILL_MD5); + } + + MD5_Final(coro->hash, &coro->md5); + CORO_GOTO(GET_GAMEID); } + else + { + // Fall back to headerless hashing + // PRG ROM size is unknown, so test by 16KB chunks + size_t chunks = coro->len >> 14; + size_t chunk_size = 0x4000; + coro->round = 0; + coro->offset = 0; + + for (int i = 0; i < chunks; i++) + { + MD5_Init(&coro->md5); + + coro->bytes = i + 1; + coro->count = coro->bytes * chunk_size; + + CORO_GOSUB(EVAL_MD5); - MD5_Final(coro->hash, &coro->md5); - CORO_GOTO(GET_GAMEID); + if (coro->count < 0x4000 * coro->bytes) + { + coro->offset = 0xff; + coro->count = 0x4000 * coro->bytes - coro->count; + CORO_GOSUB(FILL_MD5); + } + + MD5_Final(coro->hash, &coro->md5); + CORO_GOSUB(GET_GAMEID); + + if (coro->gameid > 0) + { + break; + } + } + + CORO_RET(); + } /************************************************************************** * Info Tries to identify a "generic" game From ab384b8afb3c8031225df8c0abd1f0900f8575aa Mon Sep 17 00:00:00 2001 From: Raphael Zumer Date: Mon, 10 Sep 2018 10:14:14 -0400 Subject: [PATCH 047/335] Update msg_hash_ja.h (#7203) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix some incorrect labels * Word some labels more naturally * Use RetroAchievements instead of レトロ実績 --- intl/msg_hash_ja.h | 50 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index 925f694afa..7911d839f5 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -33,7 +33,7 @@ MSG_HASH( ) MSG_HASH( MSG_PUBLIC_ADDRESS, - "公式IPアドレス" + "グローバルIPアドレス" ) MSG_HASH( MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN, @@ -65,7 +65,7 @@ MSG_HASH( ) MSG_HASH( MSG_NETPLAY_S_HAS_JOINED_AS_PLAYER_N, - "「%.*s」がプレヤー「%u」で接続しました" + "「%.*s」がプレヤー「%u」として接続しました" ) MSG_HASH( MSG_NETPLAY_S_HAS_JOINED_WITH_INPUT_DEVICES_S, @@ -77,7 +77,7 @@ MSG_HASH( ) MSG_HASH( MSG_NETPLAY_OUT_OF_DATE, - "相手のRetroArchバージョンは古いから接続できません。" + "相手のRetroArchバージョンは古いため、接続できません。" ) MSG_HASH( MSG_NETPLAY_DIFFERENT_VERSIONS, @@ -149,11 +149,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_SETTINGS, - "メニューの外観関係の設定を変更する。" + "メニューの外観に関係する設定を変更する。" ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_HARD_SYNC, - "CPUとGPUを強制に同期する。遅延が減るけどパフォーマンスも減る。" + "CPUとGPUを強制に同期する。遅延が減る代わりに性能が低下する。" ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_THREADED, @@ -173,7 +173,7 @@ MSG_HASH( ) MSG_HASH( MSG_CAPABILITIES, - "対応された機能" + "対応機能" ) MSG_HASH( MSG_CONNECTING_TO_NETPLAY_HOST, @@ -213,7 +213,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ACCOUNTS_RETRO_ACHIEVEMENTS, - "レトロ実績" + "RetroAchievements" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_LIST, @@ -221,11 +221,11 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_PAUSE, - "実績(ハードコア)を一時停止" + "実績ハードコアモードを一時停止" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_RESUME, - "実績(ハードコア)を再開" + "実績ハードコアモードを再開" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ACHIEVEMENT_LIST_HARDCORE, @@ -245,7 +245,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_NETPLAY_TAB, - "ネットプレイのルーム表" + "ネットプレイのロビー表" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_ASK_ARCHIVE, @@ -499,19 +499,19 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ACHIEVEMENTS, - "解除された実績:" + "未解除の実績:" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_LOCKED_ENTRY, - "ロックされている" + "未解除" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_SETTINGS, - "レトロ実績" + "RetroAchievements" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_TEST_UNOFFICIAL, - "非公式実績をテスト" + "非公式実績を試す" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_VERBOSE_ENABLE, @@ -523,15 +523,15 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ACHIEVEMENTS, - "解除可能の実績:" + "解除済みの実績:" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY, - "解除されている" + "解除済み" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CHEEVOS_UNLOCKED_ENTRY_HARDCORE, - "解除されている(ハードコア)" + "解除済み(ハードコア)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_CLOSE_CONTENT, @@ -1411,7 +1411,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROPAD, MSG_HASH(MENU_ENUM_LABEL_VALUE_RETROPAD_WITH_ANALOG, "レトロパッド(アナログ付)") MSG_HASH(MENU_ENUM_LABEL_VALUE_RETRO_ACHIEVEMENTS_SETTINGS, - "レトロ実績") + "実績") MSG_HASH(MENU_ENUM_LABEL_VALUE_REWIND_ENABLE, "巻き戻しを有効") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_APPLY_AFTER_TOGGLE, @@ -1997,7 +1997,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_HARDCORE_MODE_ENABLE, MSG_HASH(MENU_ENUM_SUBLABEL_DRIVER_SETTINGS, "システムのドライバを変更する。") MSG_HASH(MENU_ENUM_SUBLABEL_RETRO_ACHIEVEMENTS_SETTINGS, - "実績関係の設定を変更する。") + "実績に関係する設定を変更する。") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_SETTINGS, "コアの設定を変更する。") MSG_HASH(MENU_ENUM_SUBLABEL_RECORDING_SETTINGS, @@ -2007,7 +2007,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_ONSCREEN_DISPLAY_SETTINGS, MSG_HASH(MENU_ENUM_SUBLABEL_FRAME_THROTTLE_SETTINGS, "巻き戻し、早送り、スローモーションの設定を変更する。") MSG_HASH(MENU_ENUM_SUBLABEL_SAVING_SETTINGS, - "保存関係の設定を変更する。") + "保存に関係する設定を変更する。") MSG_HASH(MENU_ENUM_SUBLABEL_LOGGING_SETTINGS, "ログの設定を変更する。") MSG_HASH(MENU_ENUM_SUBLABEL_USER_INTERFACE_SETTINGS, @@ -2059,7 +2059,7 @@ MSG_HASH(MENU_ENUM_SUBLABEL_ONLINE_UPDATER, MSG_HASH(MENU_ENUM_SUBLABEL_SAMBA_ENABLE, "フォルダのネットワーク共有を有効する。") MSG_HASH(MENU_ENUM_SUBLABEL_SERVICES_SETTINGS, - "OS関係のサービスを管理する。") + "OSに関係するサービスを管理する。") MSG_HASH(MENU_ENUM_SUBLABEL_SHOW_HIDDEN_FILES, "ファイルブラウザーの中に隠しファイルとフォルダを表示する。") MSG_HASH(MENU_ENUM_SUBLABEL_SSH_ENABLE, @@ -2684,7 +2684,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_BOKEH, MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_PIPELINE_SNOWFLAKE, "スノーフレーク") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_REFRESH_ROOMS, - "ルーム表を更新") + "ロビー表を更新") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ROOM_NICKNAME, "ニックネーム: %s") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_ROOM_NICKNAME_LAN, @@ -2698,9 +2698,9 @@ MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SMOOTH, MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FILTER, "Apply a CPU-powered video filter. NOTE: Might come at a high performance cost. Some video filters might only work for cores that use 32bit or 16bit color.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_USERNAME, - "レトロ実績上のユーザー名") + "RetroAchievementsアカウントのユーザー名") MSG_HASH(MENU_ENUM_SUBLABEL_CHEEVOS_PASSWORD, - "レトロ実績上のパスワード") + "RetroAchievementsアカウントのパスワード") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_NICKNAME, "ネットプレイの使用するニックネーム") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_POST_FILTER_RECORD, @@ -3687,7 +3687,7 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_MIDI_VOLUME, MSG_HASH(MENU_ENUM_LABEL_VALUE_POWER_MANAGEMENT_SETTINGS, "電源管理") MSG_HASH(MENU_ENUM_SUBLABEL_POWER_MANAGEMENT_SETTINGS, - "電源関係設定を変更する。") + "電源に関係する設定を変更する。") MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "パフォーマンス維持モード") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, From d8b4d1fdffa496672650ad1e2ac7f17387c70271 Mon Sep 17 00:00:00 2001 From: bparker06 Date: Mon, 10 Sep 2018 10:15:06 -0400 Subject: [PATCH 048/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 106a225cdc..2885db4ca2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,6 @@ # 1.7.5 (future) - COMMON: Support for "OEM-102" key (usually '\' on Euro keyboards). +- LOCALIZATION: Update Japanese translation. - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. From 30d7ef898d7408f3672304dba56e6e488b23e3e0 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Mon, 10 Sep 2018 17:39:52 +0100 Subject: [PATCH 049/335] Xrandr sapmming fix --- gfx/display_servers/dispserv_x11.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 045479b485..b2c99cb224 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -56,20 +56,21 @@ static void x11_display_server_destroy(void *data) { sprintf(output,"xrandr -s %dx%d", orig_width, orig_height); system(output); - } - for (i =0; i < 3; i++) - { - sprintf(output,"xrandr --delmode %s%d %s", "VGA",i ,old_mode); - system(output); - sprintf(output,"xrandr --delmode %s-%d %s", "VGA",i ,old_mode); - system(output); + + for (i =0; i < 3; i++) + { + sprintf(output,"xrandr --delmode %s%d %s", "VGA",i ,old_mode); + system(output); + sprintf(output,"xrandr --delmode %s-%d %s", "VGA",i ,old_mode); + system(output); - sprintf(output,"xrandr --delmode %s%d %s", "DVI",i ,old_mode); - system(output); - sprintf(output,"xrandr --delmode %s-%d %s", "DVI",i ,old_mode); - system(output); + sprintf(output,"xrandr --delmode %s%d %s", "DVI",i ,old_mode); + system(output); + sprintf(output,"xrandr --delmode %s-%d %s", "DVI",i ,old_mode); + system(output); - } + } + } sprintf(output,"xrandr --rmmode %s", old_mode); system(output); From d8c36e5bb8d1735721e18d1b27ef198e7c6fd372 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Mon, 10 Sep 2018 17:42:33 +0100 Subject: [PATCH 050/335] xrandr spamming fix --- gfx/display_servers/dispserv_x11.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index b2c99cb224..4560407ba5 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -70,9 +70,10 @@ static void x11_display_server_destroy(void *data) system(output); } - } + sprintf(output,"xrandr --rmmode %s", old_mode); system(output); + } if (dispserv) free(dispserv); From 340515a9fa3219ff5f5030e5a7e11c901dca1595 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Mon, 10 Sep 2018 18:08:49 +0100 Subject: [PATCH 051/335] Update dispserv_x11.c --- gfx/display_servers/dispserv_x11.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 4560407ba5..6a52681b91 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -134,7 +134,7 @@ static bool x11_set_resolution(void *data, /* following code is the mode line genorator */ hsp = width*1.140; - hfp = width*1.045; + hfp = width*1.055; pwidth = width; From 7c05922d364819d50b6c49deaffbe660372be778 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Mon, 10 Sep 2018 18:09:42 +0100 Subject: [PATCH 052/335] xrandr spamming fix also re introduced snprintf --- gfx/display_servers/dispserv_x11.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 6a52681b91..758208cc93 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -68,7 +68,6 @@ static void x11_display_server_destroy(void *data) system(output); sprintf(output,"xrandr --delmode %s-%d %s", "DVI",i ,old_mode); system(output); - } sprintf(output,"xrandr --rmmode %s", old_mode); From 6c2d11b414310c527130f89edba87ab7c23a7b9c Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Mon, 10 Sep 2018 18:12:44 +0100 Subject: [PATCH 053/335] re introduced snprintf --- gfx/display_servers/dispserv_x11.c | 73 +++++++++++++----------------- 1 file changed, 32 insertions(+), 41 deletions(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 758208cc93..f1b243bf24 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -238,73 +238,64 @@ static bool x11_set_resolution(void *data, sprintf(xrandr,"xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); system(xrandr); + } + /* create interlaced newmode from modline variables */ + if (height < 300) + { + snprintf(xrandr, sizeof(xrandr), "xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); + system(xrandr); + } /* create interlaced newmode from modline variables */ if (height > 300) { - sprintf(xrandr,"xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d interlace -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); + snprintf(xrandr, sizeof(xrandr), "xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d interlace -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); system(xrandr); } /* variable for new mode */ - sprintf(new_mode,"%dx%d_%0.2f", width, height, hz); + snprintf(new_mode, sizeof(new_mode), "%dx%d_%0.2f", width, height, hz); /* need to run loops for DVI0 - DVI-2 and VGA0 - VGA-2 outputs to add and delete modes */ for (i =0; i < 3; i++) { - sprintf(output,"xrandr --addmode %s%d %s", "HDMI",i ,new_mode); + snprintf(output, sizeof(output), "xrandr --addmode %s%d %s", "DVI",i ,new_mode); system(output); - sprintf(output,"xrandr --output %s%d --mode %s", "HDMI", i, new_mode); - system(output); - sprintf(output,"xrandr --delmode %s%d %s", "HDMI",i ,old_mode); + snprintf(output, sizeof(output), "xrandr --delmode %s%d %s", "DVI",i ,old_mode); system(output); - - sprintf(output,"xrandr --addmode %s-%d %s", "HDMI",i ,new_mode); - system(output); - sprintf(output,"xrandr --output %s-%d --mode %s", "HDMI", i, new_mode); - system(output); - sprintf(output,"xrandr --delmode %s-%d %s", "HDMI",i ,old_mode); - system(output); - - sprintf(output,"xrandr --addmode %s%d %s", "DVI",i ,new_mode); + } + for (i =0; i < 3; i++) + { + snprintf(output, sizeof(output), "xrandr --addmode %s-%d %s", "DVI",i ,new_mode); system(output); - sprintf(output,"xrandr --output %s%d --mode %s", "DVI", i, new_mode); + snprintf(output, sizeof(output), "xrandr --delmode %s-%d %s", "DVI",i ,old_mode); system(output); - sprintf(output,"xrandr --delmode %s%d %s", "DVI",i ,old_mode); + } + for (i =0; i < 3; i++) + { + snprintf(output, sizeof(output), "xrandr --addmode %s%d %s", "VGA",i ,new_mode); + system(output); + snprintf(output, sizeof(output), "xrandr --delmode %s%d %s", "VGA",i ,old_mode); system(output); - - sprintf(output,"xrandr --addmode %s-%d %s", "DVI",i ,new_mode); + } + for (i =0; i < 3; i++) + { + snprintf(output, sizeof(output), "xrandr --addmode %s-%d %s", "VGA",i ,new_mode); system(output); - sprintf(output,"xrandr --output %s-%d --mode %s", "DVI", i, new_mode); - system(output); - sprintf(output,"xrandr --delmode %s-%d %s", "DVI",i ,old_mode); - system(output); - - sprintf(output,"xrandr --addmode %s%d %s", "VGA",i ,new_mode); + snprintf(output, sizeof(output), "xrandr --delmode %s-%d %s", "VGA",i ,old_mode); system(output); - sprintf(output,"xrandr --output %s%d --mode %s", "VGA", i, new_mode); - system(output); - sprintf(output,"xrandr --delmode %s%d %s", "VGA",i ,old_mode); - system(output); - - sprintf(output,"xrandr --addmode %s-%d %s", "VGA",i ,new_mode); - system(output); - sprintf(output,"xrandr --output %s-%d --mode %s", "VGA", i, new_mode); - system(output); - sprintf(output,"xrandr --delmode %s-%d %s", "VGA",i ,old_mode); - system(output); - } - + snprintf(output, sizeof(output), "xrandr -s %s", new_mode); + system(output); /* remove old mode */ - sprintf(output,"xrandr --rmmode %s", old_mode); + snprintf(output, sizeof(output), "xrandr --rmmode %s", old_mode); system(output); system("xdotool windowactivate $(xdotool search --class RetroArch)"); /* needs xdotool installed. needed to recaputure window. */ /* variable for old mode */ - sprintf(old_mode,"%s", new_mode); + snprintf(old_mode, sizeof(old_mode), "%s", new_mode); system("xdotool windowactivate $(xdotool search --class RetroArch)"); /* needs xdotool installed. needed to recaputure window. */ - /* Second run needed as some times it runs to fast to capture first time */ + /* Second run needed as some times it runs to fast to capture first time */ return true; } From 4328c075e8982fc65a03a72f5326aa9e45355741 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Mon, 10 Sep 2018 18:25:32 +0100 Subject: [PATCH 054/335] fixes --- gfx/display_servers/dispserv_x11.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index f1b243bf24..0d4ba81575 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -232,13 +232,6 @@ static bool x11_set_resolution(void *data, } /* above code is the modeline genorator */ - /* create progressive newmode from modline variables */ - if (height < 300) - { - sprintf(xrandr,"xrandr --newmode \"%dx%d_%0.2f\" %lf %d %d %d %d %d %d %d %d -hsync -vsync", width, height, hz, pixel_clock, width, hfp, hsp, hbp, height, vfp, vsp, vbp); - system(xrandr); - - } /* create interlaced newmode from modline variables */ if (height < 300) { From a1989afba9f87bbe82c897cfc3af012a0cc493c3 Mon Sep 17 00:00:00 2001 From: Themaister Date: Mon, 10 Sep 2018 19:20:50 +0200 Subject: [PATCH 055/335] Vulkan: Fix race condition in threaded mailbox emulation. --- gfx/common/vulkan_common.c | 71 ++++++++++++++++++++++++++++++++++++-- gfx/common/vulkan_common.h | 1 + 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 42779d75c8..b4e3c2e2f9 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -168,6 +168,37 @@ VkResult vulkan_emulated_mailbox_acquire_next_image(struct vulkan_emulated_mailb return res; } +VkResult vulkan_emulated_mailbox_acquire_next_image_blocking( + struct vulkan_emulated_mailbox *mailbox, + unsigned *index) +{ + VkResult res; + if (mailbox->swapchain == VK_NULL_HANDLE) + return VK_ERROR_OUT_OF_DATE_KHR; + + slock_lock(mailbox->lock); + + if (!mailbox->has_pending_request) + { + mailbox->request_acquire = true; + scond_signal(mailbox->cond); + } + + mailbox->has_pending_request = true; + + while (!mailbox->acquired) + scond_wait(mailbox->cond, mailbox->lock); + + res = mailbox->result; + if (res == VK_SUCCESS) + *index = mailbox->index; + mailbox->has_pending_request = false; + mailbox->acquired = false; + + slock_unlock(mailbox->lock); + return res; +} + static void vulkan_emulated_mailbox_loop(void *userdata) { VkResult res; @@ -2659,6 +2690,8 @@ retry: } } + retro_assert(!vk->context.has_acquired_swapchain); + if (vk->emulating_mailbox) { /* Non-blocking acquire. If we don't get a swapchain frame right away, @@ -2756,6 +2789,7 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, VkPresentModeKHR swapchain_present_mode = VK_PRESENT_MODE_FIFO_KHR; settings_t *settings = config_get_ptr(); VkCompositeAlphaFlagBitsKHR composite = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + VkResult res; vkDeviceWaitIdle(vk->context.device); vulkan_acquire_clear_fences(vk); @@ -2777,14 +2811,46 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, { /* Do not bother creating a swapchain redundantly. */ RARCH_LOG("[Vulkan]: Do not need to re-create swapchain.\n"); - vk->created_new_swapchain = false; vulkan_create_wait_fences(vk); if (vk->emulating_mailbox && vk->mailbox.swapchain == VK_NULL_HANDLE) + { vulkan_emulated_mailbox_init(&vk->mailbox, vk->context.device, vk->swapchain); + vk->created_new_swapchain = false; + return true; + } else if (!vk->emulating_mailbox && vk->mailbox.swapchain != VK_NULL_HANDLE) + { + /* We are tearing down, and entering a state where we are supposed to have + * acquired an image, so block until we have acquired. */ + if (!vk->context.has_acquired_swapchain) + { + res = vulkan_emulated_mailbox_acquire_next_image_blocking( + &vk->mailbox, + &vk->context.current_swapchain_index); + } + else + res = VK_SUCCESS; + vulkan_emulated_mailbox_deinit(&vk->mailbox); - return true; + + if (res == VK_SUCCESS) + { + vk->context.has_acquired_swapchain = true; + vk->created_new_swapchain = false; + return true; + } + else + { + vk->context.has_acquired_swapchain = false; + /* We failed for some reason, so create a new swapchain. */ + } + } + else + { + vk->created_new_swapchain = false; + return true; + } } vulkan_emulated_mailbox_deinit(&vk->mailbox); @@ -3023,6 +3089,7 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, /* Force driver to reset swapchain image handles. */ vk->context.invalid_swapchain = true; + vk->context.has_acquired_swapchain = false; vulkan_create_wait_fences(vk); if (vk->emulating_mailbox) diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index e42d137fec..e4e3a50570 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -148,6 +148,7 @@ bool vulkan_emulated_mailbox_init(struct vulkan_emulated_mailbox *mailbox, VkDevice device, VkSwapchainKHR swapchain); void vulkan_emulated_mailbox_deinit(struct vulkan_emulated_mailbox *mailbox); VkResult vulkan_emulated_mailbox_acquire_next_image(struct vulkan_emulated_mailbox *mailbox, unsigned *index); +VkResult vulkan_emulated_mailbox_acquire_next_image_blocking(struct vulkan_emulated_mailbox *mailbox, unsigned *index); typedef struct gfx_ctx_vulkan_data { From e403b8fb1e6ce43973d3f5c64b21ee0a05ca04a1 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Mon, 10 Sep 2018 20:35:30 +0200 Subject: [PATCH 056/335] C89 buildfixes --- cheevos/cheevos.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cheevos/cheevos.c b/cheevos/cheevos.c index b61fe2ca5a..2d2daab6d8 100644 --- a/cheevos/cheevos.c +++ b/cheevos/cheevos.c @@ -3042,14 +3042,17 @@ found: } else { - // Fall back to headerless hashing - // PRG ROM size is unknown, so test by 16KB chunks - size_t chunks = coro->len >> 14; + unsigned i; + size_t chunks = coro->len >> 14; size_t chunk_size = 0x4000; - coro->round = 0; - coro->offset = 0; + + /* Fall back to headerless hashing + * PRG ROM size is unknown, so test by 16KB chunks */ + + coro->round = 0; + coro->offset = 0; - for (int i = 0; i < chunks; i++) + for (i = 0; i < chunks; i++) { MD5_Init(&coro->md5); From f576266acebd85da1ea2b13130d4396b92938f44 Mon Sep 17 00:00:00 2001 From: alphanu1 <37101891+alphanu1@users.noreply.github.com> Date: Mon, 10 Sep 2018 19:36:57 +0100 Subject: [PATCH 057/335] Update dispserv_x11.c --- gfx/display_servers/dispserv_x11.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gfx/display_servers/dispserv_x11.c b/gfx/display_servers/dispserv_x11.c index 0d4ba81575..b9c27fd10d 100644 --- a/gfx/display_servers/dispserv_x11.c +++ b/gfx/display_servers/dispserv_x11.c @@ -25,12 +25,12 @@ static unsigned orig_width = 0; static unsigned orig_height = 0; -static char old_mode[250]; -static char new_mode[250]; -static char xrandr[250]; -static char fbset[150]; -static char output[250]; -static bool crt_en = false; +static char old_mode[250] = {0}; +static char new_mode[250] = {0}; +static char xrandr[250] = {0}; +static char fbset[150] = {0}; +static char output[250] = {0}; +static bool crt_en = false; typedef struct { From 7a76c6a4da502ae846de0756e46e600cbcd4ce75 Mon Sep 17 00:00:00 2001 From: Brad Parker Date: Mon, 10 Sep 2018 21:01:46 -0400 Subject: [PATCH 058/335] netplay: save lobby details received back from server after first announcement --- network/netplay/netplay_discovery.c | 7 +++ network/netplay/netplay_discovery.h | 4 ++ network/netplay/netplay_frontend.c | 94 ++++++++++++++++++++++++++--- 3 files changed, 98 insertions(+), 7 deletions(-) diff --git a/network/netplay/netplay_discovery.c b/network/netplay/netplay_discovery.c index 372a818b3d..67781977c0 100644 --- a/network/netplay/netplay_discovery.c +++ b/network/netplay/netplay_discovery.c @@ -87,6 +87,13 @@ static struct ad_packet ad_packet_buffer; static struct netplay_host_list discovered_hosts; static size_t discovered_hosts_allocated; +static struct netplay_room netplay_host_room = {0}; + +struct netplay_room* netplay_get_host_room(void) +{ + return &netplay_host_room; +} + /** Initialize Netplay discovery (client) */ bool init_netplay_discovery(void) { diff --git a/network/netplay/netplay_discovery.h b/network/netplay/netplay_discovery.h index 91153d3f46..27b910915c 100644 --- a/network/netplay/netplay_discovery.h +++ b/network/netplay/netplay_discovery.h @@ -54,6 +54,7 @@ struct netplay_host_list size_t size; }; +/* Keep these in order, they coincide with a server-side enum and must match. */ enum netplay_host_method { NETPLAY_HOST_METHOD_UNKNOWN = 0, @@ -64,6 +65,7 @@ enum netplay_host_method struct netplay_room { + int id; char nickname [PATH_MAX_LENGTH]; char address [PATH_MAX_LENGTH]; char mitm_address[PATH_MAX_LENGTH]; @@ -98,4 +100,6 @@ void deinit_netplay_discovery(void); /** Discovery control */ bool netplay_discovery_driver_ctl(enum rarch_netplay_discovery_ctl_state state, void *data); +struct netplay_room* netplay_get_host_room(void); + #endif diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 016f02232c..0919662210 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -28,6 +28,7 @@ #include +#include "netplay_discovery.h" #include "netplay_private.h" #include "../../configuration.h" @@ -57,7 +58,7 @@ static unsigned server_port_deferred = 0; static int reannounce = 0; static bool is_mitm = false; -bool netplay_disconnect(netplay_t *netplay); +static bool netplay_disconnect(netplay_t *netplay); /** * netplay_is_alive: @@ -635,6 +636,7 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er { http_transfer_data_t *data = (http_transfer_data_t*)task_data; struct string_list *lines; + struct netplay_room *host_room = netplay_get_host_room(); unsigned i, ip_len, port_len; const char *mitm_ip = NULL; const char *mitm_port = NULL; @@ -661,15 +663,88 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er return; } + memset(host_room, 0, sizeof(*host_room)); + for (i = 0; i < lines->size; i++) { const char *line = lines->elems[i].data; - if (!strncmp(line, "mitm_ip=", 8)) - mitm_ip = line + 8; + if (!string_is_empty(line)) + { + struct string_list *kv = string_split(line, "="); + const char *key = NULL; + const char *val = NULL; - if (!strncmp(line, "mitm_port=", 10)) - mitm_port = line + 10; + if (!kv) + continue; + + if (kv->size != 2) + { + string_list_free(kv); + continue; + } + + key = kv->elems[0].data; + val = kv->elems[1].data; + + if (string_is_equal(key, "id")) + sscanf(val, "%i", &host_room->id); + if (string_is_equal(key, "username")) + strlcpy(host_room->nickname, val, sizeof(host_room->nickname)); + if (string_is_equal(key, "ip")) + strlcpy(host_room->address, val, sizeof(host_room->address)); + if (string_is_equal(key, "mitm_ip")) + { + mitm_ip = strdup(val); + strlcpy(host_room->mitm_address, val, sizeof(host_room->mitm_address)); + } + if (string_is_equal(key, "port")) + sscanf(val, "%i", &host_room->port); + if (string_is_equal(key, "mitm_port")) + { + mitm_port = strdup(val); + sscanf(mitm_port, "%i", &host_room->mitm_port); + } + if (string_is_equal(key, "core_name")) + strlcpy(host_room->corename, val, sizeof(host_room->corename)); + if (string_is_equal(key, "frontend")) + strlcpy(host_room->frontend, val, sizeof(host_room->frontend)); + if (string_is_equal(key, "core_version")) + strlcpy(host_room->coreversion, val, sizeof(host_room->coreversion)); + if (string_is_equal(key, "game_name")) + strlcpy(host_room->gamename, val, sizeof(host_room->gamename)); + if (string_is_equal(key, "game_crc")) + sscanf(val, "%08X", &host_room->gamecrc); + if (string_is_equal(key, "host_method")) + sscanf(val, "%i", &host_room->host_method); + if (string_is_equal(key, "has_password")) + { + if (string_is_equal_noncase(val, "true") || string_is_equal(val, "1")) + host_room->has_password = true; + else + host_room->has_password = false; + } + if (string_is_equal(key, "has_spectate_password")) + { + if (string_is_equal_noncase(val, "true") || string_is_equal(val, "1")) + host_room->has_spectate_password = true; + else + host_room->has_spectate_password = false; + } + if (string_is_equal(key, "fixed")) + { + if (string_is_equal_noncase(val, "true") || string_is_equal(val, "1")) + host_room->fixed = true; + else + host_room->fixed = false; + } + if (string_is_equal(key, "retroarch_version")) + strlcpy(host_room->retroarch_version, val, sizeof(host_room->retroarch_version)); + if (string_is_equal(key, "country")) + strlcpy(host_room->country, val, sizeof(host_room->country)); + + string_list_free(kv); + } } if (mitm_ip && mitm_port) @@ -684,6 +759,7 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er { command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); is_mitm = true; + host_room->host_method = NETPLAY_HOST_METHOD_MITM; } netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); @@ -704,6 +780,10 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er string_list_free(lines); free(buf); free(task_data); + if (mitm_ip) + free(mitm_ip); + if (mitm_port) + free(mitm_port); } return; @@ -755,7 +835,7 @@ void netplay_get_architecture(char *frontend_architecture, size_t size) static void netplay_announce(void) { char buf [2048]; - char url [2048] = "http://newlobby.libretro.com/add/"; + char url [2048] = "http://lobby.libretro.com/add/"; char *username = NULL; char *corename = NULL; char *gamename = NULL; @@ -1275,7 +1355,7 @@ static void netplay_toggle_play_spectate(netplay_t *netplay) * * Returns: true (1) if successful. At present, cannot fail. **/ -bool netplay_disconnect(netplay_t *netplay) +static bool netplay_disconnect(netplay_t *netplay) { size_t i; From 3a6290887ae6ff8a8ea10104e439b75bc2c5b9d3 Mon Sep 17 00:00:00 2001 From: altiereslima Date: Tue, 11 Sep 2018 01:21:42 -0300 Subject: [PATCH 059/335] Update brazilian portuguese translation --- intl/msg_hash_pt_br.h | 96 ++++++++++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 25 deletions(-) diff --git a/intl/msg_hash_pt_br.h b/intl/msg_hash_pt_br.h index 7b8204db0a..96d3f2dc6e 100644 --- a/intl/msg_hash_pt_br.h +++ b/intl/msg_hash_pt_br.h @@ -1000,7 +1000,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_AUTODETECT_ENABLE, - "Habilitar Autoconfiguração" + "Habilitar Auto Configuração" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_AXIS_THRESHOLD, @@ -1372,7 +1372,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_SAVE_AUTOCONFIG, - "Salvar Autoconfiguração" + "Salvar Auto Configuração" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_INPUT_SETTINGS, @@ -1408,7 +1408,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_JOYPAD_AUTOCONFIG_DIR, - "Autoconfiguração de Entrada" + "Auto Configuração de Entrada" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_JOYPAD_DRIVER, @@ -2520,7 +2520,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SUPPORTED_CORES, - "Núcleos Sugeridos" + "Núcleos sugeridos" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SUSPEND_SCREENSAVER_ENABLE, @@ -2548,7 +2548,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_BUILD_DATE, - "Data de Compilação" + "Data de compilação" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CG_SUPPORT, @@ -2560,7 +2560,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_COMMAND_IFACE_SUPPORT, - "Suporte à Interface de Comando" + "Suporte à interface de comando" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_CORETEXT_SUPPORT, @@ -2572,15 +2572,15 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_DPI, - "Métrica DPI da Tela" + "Métrica DPI da tela" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_HEIGHT, - "Métrica de Altura da Tela (mm)" + "Métrica de altura da tela (mm)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DISPLAY_METRIC_MM_WIDTH, - "Métrica de Largura da Tela (mm)" + "Métrica de largura da tela (mm)" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_DSOUND_SUPPORT, @@ -2916,7 +2916,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_UPDATE_AUTOCONFIG_PROFILES, - "Atualizar Perfis de Autoconfiguração" + "Atualizar Perfis de Auto Configuração" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_UPDATE_CG_SHADERS, @@ -3676,7 +3676,7 @@ MSG_HASH( ) MSG_HASH( MSG_AUTOCONFIG_FILE_ERROR_SAVING, - "Erro em salvar o arquivo de autoconfiguração." + "Erro em salvar o arquivo de auto configuração." ) MSG_HASH( MSG_AUTOCONFIG_FILE_SAVED_SUCCESSFULLY, @@ -5044,7 +5044,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL, - "Troca de botões para OK/Cancelar. Desabilitado é o estilo de botão japonês, habilitada é oestilo ocidental." + "Troca de botões para OK/Cancelar. Desabilitado é o estilo de botão japonês, habilitada é o estilo ocidental." ) MSG_HASH( MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO, @@ -5576,7 +5576,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_SUBLABEL_JOYPAD_AUTOCONFIG_DIR, - "Se um Joypad estiver conectado, o mesmo será autoconfigurado se um arquivo de configuração correspondente estiver presente dento deste diretório." + "Se um Joypad estiver conectado, o mesmo será configurado automaticamente se um arquivo de configuração correspondente estiver presente dento deste diretório." ) MSG_HASH( MENU_ENUM_SUBLABEL_PLAYLIST_DIRECTORY, @@ -6211,7 +6211,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_SHOW_DECORATIONS, - "Exibir Decorações da Janela" + "Exibir Botões em Janela" ) MSG_HASH( MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, @@ -6275,7 +6275,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU, - "Ativar áudio de menu" + "Ativar Áudio de Menu" ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_ENABLE_MENU, @@ -7265,6 +7265,18 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE, "Banco de Dados:" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_EXTENSIONS, + "Extensões:" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_EXTENSIONS_PLACEHOLDER, + "(separado por espaço; inclui tudo por padrão)" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_FILTER_INSIDE_ARCHIVES, + "Filtrar dentro dos arquivos" + ) MSG_HASH( MENU_ENUM_LABEL_VALUE_QT_FOR_THUMBNAILS, "(usado para encontrar miniaturas)" @@ -7385,13 +7397,47 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_QT_RESET_PARAMETER, "Restaurar Parâmetro" ) -MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_THUMBNAIL, - "Baixar miniaturas") -MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALREADY_IN_PROGRESS, - "Um download já está em progresso.") -MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST, - "Iniciar na lista de reprodução:") -MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS, - "Baixar Todas as Miniaturas") -MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY, - "Miniaturas baixadas com sucesso.") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_THUMBNAIL, + "Baixar miniaturas" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALREADY_IN_PROGRESS, + "Um download já está em progresso." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_STARTUP_PLAYLIST, + "Iniciar na lista de reprodução:" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS, + "Baixar Todas as Miniaturas" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS_ENTIRE_SYSTEM, + "Sistema Inteiro" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_ALL_THUMBNAILS_THIS_PLAYLIST, + "Esta Lista de Reprodução" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_PACK_DOWNLOADED_SUCCESSFULLY, + "Miniaturas baixadas com sucesso." + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_PLAYLIST_THUMBNAIL_PROGRESS, + "Sucedido: %1 Falhou: %2" + ) +MSG_HASH( + MSG_DEVICE_CONFIGURED_IN_PORT, + "Configurado na porta:" + ) +MSG_HASH( + MSG_FAILED_TO_SET_DISK, + "Falha ao definir o disco" + ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS, + "Opções de Núcleo" + ) From 21684a80adca4e297e7b81b4fbdb494a79d9a9a5 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Tue, 11 Sep 2018 06:35:43 +0200 Subject: [PATCH 060/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 2885db4ca2..9b551dbab0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ - LOCALIZATION: Update Japanese translation. - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. +- NETPLAY: Save lobby details received back from server after first announcement. # 1.7.4 - ANDROID: Add sustained performance mode, can be turned on/off in Power Management settings menu. From 83c3bd31c6e3973611cfe27e821d9037f0aba0b4 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Tue, 11 Sep 2018 06:36:12 +0200 Subject: [PATCH 061/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 9b551dbab0..784847d802 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. - NETPLAY: Save lobby details received back from server after first announcement. +- VULKAN: Fix race condition in threaded mailbox emulation. # 1.7.4 - ANDROID: Add sustained performance mode, can be turned on/off in Power Management settings menu. From f96db78b3deb94d92cdb4b035d23e2071f2aca8a Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Tue, 11 Sep 2018 06:36:45 +0200 Subject: [PATCH 062/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 784847d802..1687b1f121 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,5 @@ # 1.7.5 (future) +- CAMERA: Fix Video4Linux2 driver that broke years ago. - COMMON: Support for "OEM-102" key (usually '\' on Euro keyboards). - LOCALIZATION: Update Japanese translation. - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. From 91b945e52940517373b6c86f5f6690e71c94d540 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Tue, 11 Sep 2018 06:37:56 +0200 Subject: [PATCH 063/335] Update CHANGES.md --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 1687b1f121..eb0e09c1b3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,11 +1,13 @@ # 1.7.5 (future) - CAMERA: Fix Video4Linux2 driver that broke years ago. +- CRT: New porches and interlaced bug fix. - COMMON: Support for "OEM-102" key (usually '\' on Euro keyboards). - LOCALIZATION: Update Japanese translation. - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. - NETPLAY: Save lobby details received back from server after first announcement. - VULKAN: Fix race condition in threaded mailbox emulation. +- VULKAN: Maintenance fixes. # 1.7.4 - ANDROID: Add sustained performance mode, can be turned on/off in Power Management settings menu. From c876342057437c2d87b166df0a0d89d7e1cc1cf0 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Tue, 11 Sep 2018 06:38:22 +0200 Subject: [PATCH 064/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index eb0e09c1b3..fcbcab40c9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ - CAMERA: Fix Video4Linux2 driver that broke years ago. - CRT: New porches and interlaced bug fix. - COMMON: Support for "OEM-102" key (usually '\' on Euro keyboards). +- LOCALIZATION: Update Portuguese / Brazilian translation. - LOCALIZATION: Update Japanese translation. - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. From 5d8c268afc4e0efbacf4aac2abb0df84a29f8807 Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Tue, 11 Sep 2018 06:39:07 +0200 Subject: [PATCH 065/335] Update CHANGES.md --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index fcbcab40c9..ab9128cc8c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,6 @@ # 1.7.5 (future) - CAMERA: Fix Video4Linux2 driver that broke years ago. +- CHEEVOS: Support headerless NES hashing. - CRT: New porches and interlaced bug fix. - COMMON: Support for "OEM-102" key (usually '\' on Euro keyboards). - LOCALIZATION: Update Portuguese / Brazilian translation. From d8796732aabf5a966a2413ce6f66eb8a440d0141 Mon Sep 17 00:00:00 2001 From: Sven <40953353+RetroSven@users.noreply.github.com> Date: Tue, 11 Sep 2018 13:29:20 -0400 Subject: [PATCH 066/335] provide a means for cores to coordinate with the frontend when shutting down multiple threads gracefully --- dynamic.c | 21 ++++++++++++++++++--- libretro-common/include/libretro.h | 14 ++++++++++++++ retroarch.h | 2 -- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/dynamic.c b/dynamic.c index 462628eb5d..73e593298d 100644 --- a/dynamic.c +++ b/dynamic.c @@ -1042,6 +1042,16 @@ static void core_performance_counter_stop(struct retro_perf_counter *perf) perf->total += cpu_features_get_perf_counter() - perf->start; } +bool rarch_clear_all_thread_waits(unsigned clear_threads, void *data) +{ + if ( clear_threads > 0) + audio_driver_start(false) ; + else + audio_driver_stop() ; + + return true ; +} + /** * rarch_environment_cb: * @cmd : Identifier of command. @@ -1833,8 +1843,8 @@ bool rarch_environment_cb(unsigned cmd, void *data) int* result_p = (int*)data; *result_p = result; } + break; } - break; case RETRO_ENVIRONMENT_GET_MIDI_INTERFACE: { @@ -1849,16 +1859,21 @@ bool rarch_environment_cb(unsigned cmd, void *data) midi_interface->write = midi_driver_write; midi_interface->flush = midi_driver_flush; } + break; } - break; case RETRO_ENVIRONMENT_GET_FASTFORWARDING: { extern bool runloop_fastmotion; *(bool *)data = runloop_fastmotion; + break; } - break; + case RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB: + { + *(retro_environment_t *)data = rarch_clear_all_thread_waits; + break; + } default: RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd); diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index 78e67a0781..bd95d508f6 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1195,6 +1195,20 @@ struct retro_led_interface * fastforwarding mode. */ +#define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND (50 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that tells the front end to save states in the + * background or not. + */ + +#define RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB (51 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* retro_environment_t * -- + * Provides the callback to the frontend method which will cancel + * all currently waiting threads. Used when coordination is needed + * between the core and the frontend to gracefully stop all threads. + */ + + /* Retrieves the current state of the MIDI input. * Returns true if it's enabled, false otherwise. */ typedef bool (RETRO_CALLCONV *retro_midi_input_enabled_t)(void); diff --git a/retroarch.h b/retroarch.h index dda1628c29..46d882deed 100644 --- a/retroarch.h +++ b/retroarch.h @@ -33,8 +33,6 @@ RETRO_BEGIN_DECLS -#define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND RETRO_ENVIRONMENT_PRIVATE+1 - enum rarch_ctl_state { RARCH_CTL_NONE = 0, From 4738ef545c610c45c0ba5316db7ec04359db03ce Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 00:07:43 +0200 Subject: [PATCH 067/335] Change interval type to signed int --- gfx/common/egl_common.c | 2 +- gfx/common/egl_common.h | 4 ++-- gfx/drivers/d3d8.c | 6 ++++-- gfx/drivers/d3d9.c | 7 ++++++- gfx/drivers/gl.c | 5 +++-- gfx/drivers/vg.c | 15 ++++++++------- gfx/drivers/vulkan.c | 11 +++++++---- gfx/drivers_context/android_ctx.c | 4 ++-- gfx/drivers_context/cgl_ctx.c | 2 +- gfx/drivers_context/drm_ctx.c | 4 ++-- gfx/drivers_context/emscriptenegl_ctx.c | 4 ++-- gfx/drivers_context/gdi_ctx.c | 4 ++-- gfx/drivers_context/gfx_null_ctx.c | 2 +- gfx/drivers_context/khr_display_ctx.c | 9 ++++++--- gfx/drivers_context/macos_ctx.m | 18 ++++++++++-------- gfx/drivers_context/mali_fbdev_ctx.c | 3 ++- gfx/drivers_context/opendingux_fbdev_ctx.c | 2 +- gfx/drivers_context/osmesa_ctx.c | 2 +- gfx/drivers_context/ps3_ctx.c | 4 ++-- gfx/drivers_context/qnx_ctx.c | 2 +- gfx/drivers_context/sdl_gl_ctx.c | 2 +- gfx/drivers_context/sixel_ctx.c | 2 +- gfx/drivers_context/vc_egl_ctx.c | 2 +- gfx/drivers_context/vivante_fbdev_ctx.c | 2 +- gfx/drivers_context/wayland_ctx.c | 4 ++-- gfx/drivers_context/wgl_ctx.c | 4 ++-- gfx/drivers_context/x_ctx.c | 4 ++-- gfx/drivers_context/xegl_ctx.c | 4 ++-- gfx/video_driver.c | 2 +- gfx/video_driver.h | 6 +++--- 30 files changed, 80 insertions(+), 62 deletions(-) diff --git a/gfx/common/egl_common.c b/gfx/common/egl_common.c index a0dd747c24..f3c579af21 100644 --- a/gfx/common/egl_common.c +++ b/gfx/common/egl_common.c @@ -171,7 +171,7 @@ void egl_swap_buffers(void *data) eglSwapBuffers(egl->dpy, egl->surf); } -void egl_set_swap_interval(egl_ctx_data_t *egl, unsigned interval) +void egl_set_swap_interval(egl_ctx_data_t *egl, int interval) { /* Can be called before initialization. * Some contexts require that swap interval diff --git a/gfx/common/egl_common.h b/gfx/common/egl_common.h index e82f889567..5481efc937 100644 --- a/gfx/common/egl_common.h +++ b/gfx/common/egl_common.h @@ -58,7 +58,7 @@ typedef struct EGLSurface surf; EGLDisplay dpy; EGLConfig config; - unsigned interval; + int interval; unsigned major; unsigned minor; @@ -84,7 +84,7 @@ void egl_bind_hw_render(egl_ctx_data_t *egl, bool enable); void egl_swap_buffers(void *data); -void egl_set_swap_interval(egl_ctx_data_t *egl, unsigned interval); +void egl_set_swap_interval(egl_ctx_data_t *egl, int interval); void egl_get_video_size(egl_ctx_data_t *egl, unsigned *width, unsigned *height); diff --git a/gfx/drivers/d3d8.c b/gfx/drivers/d3d8.c index 028f014659..a5dcf1b2a1 100644 --- a/gfx/drivers/d3d8.c +++ b/gfx/drivers/d3d8.c @@ -1006,13 +1006,15 @@ static bool d3d8_restore(void *data) static void d3d8_set_nonblock_state(void *data, bool state) { - unsigned interval = state ? 0 : 1; + int interval = 0; d3d8_video_t *d3d = (d3d8_video_t*)data; if (!d3d) return; - d3d->video_info.vsync = !state; + if (!state) + interval = 1; + d3d->video_info.vsync = !state; #ifdef _XBOX d3d8_set_render_state(d3d->dev, D3D8_PRESENTATIONINTERVAL, diff --git a/gfx/drivers/d3d9.c b/gfx/drivers/d3d9.c index 290bfe3af0..a383190b48 100644 --- a/gfx/drivers/d3d9.c +++ b/gfx/drivers/d3d9.c @@ -1059,14 +1059,19 @@ static bool d3d9_restore(void *data) static void d3d9_set_nonblock_state(void *data, bool state) { - unsigned interval = state ? 0 : 1; + int interval = 0; d3d9_video_t *d3d = (d3d9_video_t*)data; if (!d3d) return; + if (!state) + interval = 1; + d3d->video_info.vsync = !state; + (void)interval; + #ifdef _XBOX d3d9_set_render_state(d3d->dev, D3D9_PRESENTATIONINTERVAL, diff --git a/gfx/drivers/gl.c b/gfx/drivers/gl.c index b6a919108c..fd9870b645 100644 --- a/gfx/drivers/gl.c +++ b/gfx/drivers/gl.c @@ -1318,7 +1318,7 @@ static void gl_free(void *data) static void gl_set_nonblock_state(void *data, bool state) { - unsigned interval = 0; + int interval = 0; gl_t *gl = (gl_t*)data; settings_t *settings = config_get_ptr(); @@ -1696,13 +1696,14 @@ static void *gl_init(const video_info_t *video, { gfx_ctx_mode_t mode; gfx_ctx_input_t inp; - unsigned interval, mip_level; unsigned full_x, full_y; video_shader_ctx_filter_t shader_filter; video_shader_ctx_info_t shader_info; video_shader_ctx_ident_t ident_info; settings_t *settings = config_get_ptr(); video_shader_ctx_wrap_t wrap_info = {0}; + int interval = 0; + unsigned mip_level = 0; unsigned win_width = 0; unsigned win_height = 0; unsigned temp_width = 0; diff --git a/gfx/drivers/vg.c b/gfx/drivers/vg.c index 16bcf23b5f..7f9c383d3e 100644 --- a/gfx/drivers/vg.c +++ b/gfx/drivers/vg.c @@ -77,7 +77,7 @@ static PFNVGCREATEEGLIMAGETARGETKHRPROC pvgCreateEGLImageTargetKHR; static void vg_set_nonblock_state(void *data, bool state) { - unsigned interval = state ? 0 : 1; + int interval = state ? 0 : 1; video_context_driver_swap_interval(&interval); } @@ -97,13 +97,14 @@ static void *vg_init(const video_info_t *video, gfx_ctx_mode_t mode; gfx_ctx_input_t inp; gfx_ctx_aspect_t aspect_data; - unsigned interval; - unsigned temp_width = 0, temp_height = 0; unsigned win_width, win_height; - VGfloat clearColor[4] = {0, 0, 0, 1}; - settings_t *settings = config_get_ptr(); - vg_t *vg = (vg_t*)calloc(1, sizeof(vg_t)); - const gfx_ctx_driver_t *ctx = video_context_driver_init_first( + VGfloat clearColor[4] = {0, 0, 0, 1}; + int interval = 0; + unsigned temp_width = 0; + unsigned temp_height = 0; + settings_t *settings = config_get_ptr(); + vg_t *vg = (vg_t*)calloc(1, sizeof(vg_t)); + const gfx_ctx_driver_t *ctx = video_context_driver_init_first( vg, settings->arrays.video_context_driver, GFX_CTX_OPENVG_API, 0, 0, false); diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 1a16453420..7339143515 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -1121,10 +1121,10 @@ static void *vulkan_init(const video_info_t *video, { gfx_ctx_mode_t mode; gfx_ctx_input_t inp; - unsigned interval; unsigned full_x, full_y; unsigned win_width; unsigned win_height; + int interval = 0; unsigned temp_width = 0; unsigned temp_height = 0; const gfx_ctx_driver_t *ctx_driver = NULL; @@ -1259,7 +1259,7 @@ static void vulkan_check_swapchain(vk_t *vk) static void vulkan_set_nonblock_state(void *data, bool state) { - unsigned interval; + int interval = 0; vk_t *vk = (vk_t*)data; settings_t *settings = config_get_ptr(); @@ -1268,7 +1268,9 @@ static void vulkan_set_nonblock_state(void *data, bool state) RARCH_LOG("[Vulkan]: VSync => %s\n", state ? "off" : "on"); - interval = state ? 0 : settings->uints.video_swap_interval; + if (!state) + interval = settings->uints.video_swap_interval; + video_context_driver_swap_interval(&interval); /* Changing vsync might require recreating the swapchain, which means new VkImages @@ -2024,7 +2026,8 @@ static bool vulkan_frame(void *data, const void *frame, } /* Vulkan doesn't directly support swap_interval > 1, so we fake it by duping out more frames. */ - if (vk->context->swap_interval > 1 && !vk->context->swap_interval_emulation_lock) + if ( vk->context->swap_interval > 1 + && !vk->context->swap_interval_emulation_lock) { unsigned i; vk->context->swap_interval_emulation_lock = true; diff --git a/gfx/drivers_context/android_ctx.c b/gfx/drivers_context/android_ctx.c index cd80688420..69b9c2a389 100644 --- a/gfx/drivers_context/android_ctx.c +++ b/gfx/drivers_context/android_ctx.c @@ -60,7 +60,7 @@ typedef struct gfx_ctx_vulkan_data_t vk; unsigned width; unsigned height; - unsigned swap_interval; + int swap_interval; #endif } android_ctx_data_t; @@ -507,7 +507,7 @@ static void android_gfx_ctx_swap_buffers(void *data, void *data2) } } -static void android_gfx_ctx_set_swap_interval(void *data, unsigned swap_interval) +static void android_gfx_ctx_set_swap_interval(void *data, int swap_interval) { android_ctx_data_t *and = (android_ctx_data_t*)data; diff --git a/gfx/drivers_context/cgl_ctx.c b/gfx/drivers_context/cgl_ctx.c index fb26355304..2c981aafee 100644 --- a/gfx/drivers_context/cgl_ctx.c +++ b/gfx/drivers_context/cgl_ctx.c @@ -63,7 +63,7 @@ typedef struct gfx_ctx_cgl_data int width, height; } gfx_ctx_cgl_data_t; -static void gfx_ctx_cgl_swap_interval(void *data, unsigned interval) +static void gfx_ctx_cgl_swap_interval(void *data, int interval) { gfx_ctx_cgl_data_t *cgl = (gfx_ctx_cgl_data_t*)data; GLint params = interval; diff --git a/gfx/drivers_context/drm_ctx.c b/gfx/drivers_context/drm_ctx.c index 434c79502b..bd81479792 100644 --- a/gfx/drivers_context/drm_ctx.c +++ b/gfx/drivers_context/drm_ctx.c @@ -81,7 +81,7 @@ typedef struct gfx_ctx_drm_data egl_ctx_data_t egl; #endif int fd; - unsigned interval; + int interval; unsigned fb_width; unsigned fb_height; @@ -134,7 +134,7 @@ error: return NULL; } -static void gfx_ctx_drm_swap_interval(void *data, unsigned interval) +static void gfx_ctx_drm_swap_interval(void *data, int interval) { gfx_ctx_drm_data_t *drm = (gfx_ctx_drm_data_t*)data; drm->interval = interval; diff --git a/gfx/drivers_context/emscriptenegl_ctx.c b/gfx/drivers_context/emscriptenegl_ctx.c index 9e3234d86f..b2eb2b7100 100644 --- a/gfx/drivers_context/emscriptenegl_ctx.c +++ b/gfx/drivers_context/emscriptenegl_ctx.c @@ -49,14 +49,14 @@ static int emscripten_initial_width; static int emscripten_initial_height; static enum gfx_ctx_api emscripten_api = GFX_CTX_NONE; -static void gfx_ctx_emscripten_swap_interval(void *data, unsigned interval) +static void gfx_ctx_emscripten_swap_interval(void *data, int interval) { (void)data; if (interval == 0) emscripten_set_main_loop_timing(EM_TIMING_SETIMMEDIATE, 0); else - emscripten_set_main_loop_timing(EM_TIMING_RAF, (int)interval); + emscripten_set_main_loop_timing(EM_TIMING_RAF, interval); } static void gfx_ctx_emscripten_get_canvas_size(int *width, int *height) diff --git a/gfx/drivers_context/gdi_ctx.c b/gfx/drivers_context/gdi_ctx.c index 84349f0da1..e59a480601 100644 --- a/gfx/drivers_context/gdi_ctx.c +++ b/gfx/drivers_context/gdi_ctx.c @@ -45,7 +45,7 @@ static HDC win32_gdi_hdc; static unsigned win32_gdi_major = 0; static unsigned win32_gdi_minor = 0; -static unsigned win32_gdi_interval = 0; +static int win32_gdi_interval = 0; static enum gfx_ctx_api win32_gdi_api = GFX_CTX_NONE; typedef struct gfx_ctx_gdi_data @@ -308,7 +308,7 @@ static void gfx_ctx_gdi_show_mouse(void *data, bool state) win32_show_cursor(state); } -static void gfx_ctx_gdi_swap_interval(void *data, unsigned interval) +static void gfx_ctx_gdi_swap_interval(void *data, int interval) { (void)data; (void)interval; diff --git a/gfx/drivers_context/gfx_null_ctx.c b/gfx/drivers_context/gfx_null_ctx.c index cf0c2cc742..8303547e2d 100644 --- a/gfx/drivers_context/gfx_null_ctx.c +++ b/gfx/drivers_context/gfx_null_ctx.c @@ -18,7 +18,7 @@ #include "../video_driver.h" -static void gfx_ctx_null_swap_interval(void *data, unsigned interval) +static void gfx_ctx_null_swap_interval(void *data, int interval) { (void)data; (void)interval; diff --git a/gfx/drivers_context/khr_display_ctx.c b/gfx/drivers_context/khr_display_ctx.c index 6aa9c13f60..194597645b 100644 --- a/gfx/drivers_context/khr_display_ctx.c +++ b/gfx/drivers_context/khr_display_ctx.c @@ -23,7 +23,7 @@ typedef struct { gfx_ctx_vulkan_data_t vk; - unsigned swap_interval; + int swap_interval; unsigned width; unsigned height; } khr_display_ctx_data_t; @@ -99,7 +99,8 @@ static bool gfx_ctx_khr_display_set_resize(void *data, khr->width = width; khr->height = height; - if (!vulkan_create_swapchain(&khr->vk, khr->width, khr->height, khr->swap_interval)) + if (!vulkan_create_swapchain(&khr->vk, khr->width, khr->height, + khr->swap_interval)) { RARCH_ERR("[Vulkan]: Failed to update swapchain.\n"); return false; @@ -189,9 +190,11 @@ static bool gfx_ctx_khr_display_suppress_screensaver(void *data, bool enable) return false; } -static void gfx_ctx_khr_display_set_swap_interval(void *data, unsigned swap_interval) +static void gfx_ctx_khr_display_set_swap_interval(void *data, + int swap_interval) { khr_display_ctx_data_t *khr = (khr_display_ctx_data_t*)data; + if (khr->swap_interval != swap_interval) { khr->swap_interval = swap_interval; diff --git a/gfx/drivers_context/macos_ctx.m b/gfx/drivers_context/macos_ctx.m index 21c2cbda3e..c69301a4f9 100644 --- a/gfx/drivers_context/macos_ctx.m +++ b/gfx/drivers_context/macos_ctx.m @@ -88,7 +88,7 @@ typedef struct cocoa_ctx_data bool core_hw_context_enable; #ifdef HAVE_VULKAN gfx_ctx_vulkan_data_t vk; - unsigned swap_interval; + int swap_interval; #endif unsigned width; unsigned height; @@ -360,7 +360,7 @@ static bool cocoagl_gfx_ctx_bind_api(void *data, enum gfx_ctx_api api, unsigned return true; } -static void cocoagl_gfx_ctx_swap_interval(void *data, unsigned interval) +static void cocoagl_gfx_ctx_swap_interval(void *data, int interval) { #ifdef HAVE_VULKAN cocoa_ctx_data_t *cocoa_ctx = (cocoa_ctx_data_t*)data; @@ -373,10 +373,10 @@ static void cocoagl_gfx_ctx_swap_interval(void *data, unsigned interval) { #if defined(HAVE_COCOATOUCH) // < No way to disable Vsync on iOS? // Just skip presents so fast forward still works. - g_is_syncing = interval ? true : false; + g_is_syncing = interval ? true : false; g_fast_forward_skips = interval ? 0 : 3; #elif defined(HAVE_COCOA) - GLint value = interval ? 1 : 0; + GLint value = interval ? 1 : 0; [g_context setValues:&value forParameter:NSOpenGLCPSwapInterval]; #endif break; @@ -491,9 +491,10 @@ static bool cocoagl_gfx_ctx_set_video_mode(void *data, case GFX_CTX_VULKAN_API: #ifdef HAVE_VULKAN RARCH_LOG("[macOS]: Native window size: %u x %u.\n", cocoa_ctx->width, cocoa_ctx->height); - if (!vulkan_surface_create(&cocoa_ctx->vk, VULKAN_WSI_MVK_MACOS, NULL, - (BRIDGE void *)g_view, cocoa_ctx->width, cocoa_ctx->height, - cocoa_ctx->swap_interval)) + if (!vulkan_surface_create(&cocoa_ctx->vk, + VULKAN_WSI_MVK_MACOS, NULL, + (BRIDGE void *)g_view, cocoa_ctx->width, cocoa_ctx->height, + cocoa_ctx->swap_interval)) { RARCH_ERR("[macOS]: Failed to create surface.\n"); return false; @@ -772,7 +773,8 @@ static bool cocoagl_gfx_ctx_set_resize(void *data, unsigned width, unsigned heig cocoa_ctx->width = width; cocoa_ctx->height = height; - if (vulkan_create_swapchain(&cocoa_ctx->vk, width, height, cocoa_ctx->swap_interval)) + if (vulkan_create_swapchain(&cocoa_ctx->vk, + width, height, cocoa_ctx->swap_interval)) { cocoa_ctx->vk.context.invalid_swapchain = true; if (cocoa_ctx->vk.created_new_swapchain) diff --git a/gfx/drivers_context/mali_fbdev_ctx.c b/gfx/drivers_context/mali_fbdev_ctx.c index 3ffd90aedf..cb86849d95 100644 --- a/gfx/drivers_context/mali_fbdev_ctx.c +++ b/gfx/drivers_context/mali_fbdev_ctx.c @@ -244,7 +244,8 @@ static bool gfx_ctx_mali_fbdev_suppress_screensaver(void *data, bool enable) return false; } -static void gfx_ctx_mali_fbdev_set_swap_interval(void *data, unsigned swap_interval) +static void gfx_ctx_mali_fbdev_set_swap_interval(void *data, + int swap_interval) { mali_ctx_data_t *mali = (mali_ctx_data_t*)data; diff --git a/gfx/drivers_context/opendingux_fbdev_ctx.c b/gfx/drivers_context/opendingux_fbdev_ctx.c index 69ff6a58c6..41d6e34aae 100644 --- a/gfx/drivers_context/opendingux_fbdev_ctx.c +++ b/gfx/drivers_context/opendingux_fbdev_ctx.c @@ -225,7 +225,7 @@ static void gfx_ctx_opendingux_swap_buffers(void *data, void *data2) } static void gfx_ctx_opendingux_set_swap_interval( - void *data, unsigned swap_interval) + void *data, int swap_interval) { opendingux_ctx_data_t *viv = (opendingux_ctx_data_t*)data; diff --git a/gfx/drivers_context/osmesa_ctx.c b/gfx/drivers_context/osmesa_ctx.c index a3ffaf5957..d78e7ec6c3 100644 --- a/gfx/drivers_context/osmesa_ctx.c +++ b/gfx/drivers_context/osmesa_ctx.c @@ -240,7 +240,7 @@ static bool osmesa_ctx_bind_api(void *data, return true; } -static void osmesa_ctx_swap_interval(void *data, unsigned interval) +static void osmesa_ctx_swap_interval(void *data, int interval) { (void)data; (void)interval; diff --git a/gfx/drivers_context/ps3_ctx.c b/gfx/drivers_context/ps3_ctx.c index 72d1587cb6..f934d3a2aa 100644 --- a/gfx/drivers_context/ps3_ctx.c +++ b/gfx/drivers_context/ps3_ctx.c @@ -140,10 +140,10 @@ static void gfx_ctx_ps3_get_available_resolutions(void) global->console.screen.resolutions.check = true; } -static void gfx_ctx_ps3_set_swap_interval(void *data, unsigned interval) +static void gfx_ctx_ps3_set_swap_interval(void *data, int interval) { #if defined(HAVE_PSGL) - if (interval) + if (interval == 1) glEnable(GL_VSYNC_SCE); else glDisable(GL_VSYNC_SCE); diff --git a/gfx/drivers_context/qnx_ctx.c b/gfx/drivers_context/qnx_ctx.c index 2ce96ac7aa..7ce06b5f28 100644 --- a/gfx/drivers_context/qnx_ctx.c +++ b/gfx/drivers_context/qnx_ctx.c @@ -417,7 +417,7 @@ dpi_fallback: return true; } -static void gfx_ctx_qnx_set_swap_interval(void *data, unsigned swap_interval) +static void gfx_ctx_qnx_set_swap_interval(void *data, int swap_interval) { qnx_ctx_data_t *qnx = (qnx_ctx_data_t*)data; diff --git a/gfx/drivers_context/sdl_gl_ctx.c b/gfx/drivers_context/sdl_gl_ctx.c index aedb29e5dc..f51315b47e 100644 --- a/gfx/drivers_context/sdl_gl_ctx.c +++ b/gfx/drivers_context/sdl_gl_ctx.c @@ -156,7 +156,7 @@ static bool sdl_ctx_bind_api(void *data, return true; } -static void sdl_ctx_swap_interval(void *data, unsigned interval) +static void sdl_ctx_swap_interval(void *data, int interval) { (void)data; #ifdef HAVE_SDL2 diff --git a/gfx/drivers_context/sixel_ctx.c b/gfx/drivers_context/sixel_ctx.c index cee11e0027..968f067dd3 100644 --- a/gfx/drivers_context/sixel_ctx.c +++ b/gfx/drivers_context/sixel_ctx.c @@ -151,7 +151,7 @@ static void gfx_ctx_sixel_show_mouse(void *data, bool state) (void)data; } -static void gfx_ctx_sixel_swap_interval(void *data, unsigned interval) +static void gfx_ctx_sixel_swap_interval(void *data, int interval) { (void)data; (void)interval; diff --git a/gfx/drivers_context/vc_egl_ctx.c b/gfx/drivers_context/vc_egl_ctx.c index 56b8ba8933..04aaf3ee1f 100644 --- a/gfx/drivers_context/vc_egl_ctx.c +++ b/gfx/drivers_context/vc_egl_ctx.c @@ -330,7 +330,7 @@ error: return NULL; } -static void gfx_ctx_vc_set_swap_interval(void *data, unsigned swap_interval) +static void gfx_ctx_vc_set_swap_interval(void *data, int swap_interval) { #ifdef HAVE_EGL vc_ctx_data_t *vc = (vc_ctx_data_t*)data; diff --git a/gfx/drivers_context/vivante_fbdev_ctx.c b/gfx/drivers_context/vivante_fbdev_ctx.c index 512e740add..2270ee003c 100644 --- a/gfx/drivers_context/vivante_fbdev_ctx.c +++ b/gfx/drivers_context/vivante_fbdev_ctx.c @@ -221,7 +221,7 @@ static bool gfx_ctx_vivante_suppress_screensaver(void *data, bool enable) return false; } -static void gfx_ctx_vivante_set_swap_interval(void *data, unsigned swap_interval) +static void gfx_ctx_vivante_set_swap_interval(void *data, int swap_interval) { vivante_ctx_data_t *viv = (vivante_ctx_data_t*)data; diff --git a/gfx/drivers_context/wayland_ctx.c b/gfx/drivers_context/wayland_ctx.c index cbd5418a7a..f22d184849 100644 --- a/gfx/drivers_context/wayland_ctx.c +++ b/gfx/drivers_context/wayland_ctx.c @@ -86,7 +86,7 @@ typedef struct gfx_ctx_wayland_data struct wl_touch *wl_touch; struct wl_seat *seat; struct wl_shm *shm; - unsigned swap_interval; + int swap_interval; bool core_hw_context_enable; unsigned buffer_scale; @@ -1232,7 +1232,7 @@ static void gfx_ctx_wl_destroy(void *data) free(wl); } -static void gfx_ctx_wl_set_swap_interval(void *data, unsigned swap_interval) +static void gfx_ctx_wl_set_swap_interval(void *data, int swap_interval) { gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data; diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index bf991fd8c6..959182ac7e 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -97,7 +97,7 @@ static gfx_ctx_vulkan_data_t win32_vk; static unsigned win32_major = 0; static unsigned win32_minor = 0; -static unsigned win32_interval = 0; +static int win32_interval = 0; static enum gfx_ctx_api win32_api = GFX_CTX_NONE; #ifdef HAVE_DYNAMIC @@ -308,7 +308,7 @@ void create_graphics_context(HWND hwnd, bool *quit) void *dinput_wgl; -static void gfx_ctx_wgl_swap_interval(void *data, unsigned interval) +static void gfx_ctx_wgl_swap_interval(void *data, int interval) { (void)data; diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index 45c2d04c72..15f0e6b04e 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -100,7 +100,7 @@ typedef struct gfx_ctx_x_data unsigned swap_mode; #endif - unsigned g_interval; + int g_interval; #ifdef HAVE_VULKAN gfx_ctx_vulkan_data_t vk; @@ -320,7 +320,7 @@ static void gfx_ctx_x_destroy(void *data) free(data); } -static void gfx_ctx_x_swap_interval(void *data, unsigned interval) +static void gfx_ctx_x_swap_interval(void *data, int interval) { gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data; diff --git a/gfx/drivers_context/xegl_ctx.c b/gfx/drivers_context/xegl_ctx.c index 45df7e35c1..ad21ce4644 100644 --- a/gfx/drivers_context/xegl_ctx.c +++ b/gfx/drivers_context/xegl_ctx.c @@ -255,7 +255,7 @@ static EGLint *xegl_fill_attribs(xegl_ctx_data_t *xegl, EGLint *attr) } /* forward declaration */ -static void gfx_ctx_xegl_set_swap_interval(void *data, unsigned swap_interval); +static void gfx_ctx_xegl_set_swap_interval(void *data, int swap_interval); static bool gfx_ctx_xegl_set_video_mode(void *data, video_frame_info_t *video_info, @@ -561,7 +561,7 @@ static void gfx_ctx_xegl_bind_hw_render(void *data, bool enable) } } -static void gfx_ctx_xegl_set_swap_interval(void *data, unsigned swap_interval) +static void gfx_ctx_xegl_set_swap_interval(void *data, int swap_interval) { xegl_ctx_data_t *xegl = (xegl_ctx_data_t*)data; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index fad1e5b3a5..f3af9a5661 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -3202,7 +3202,7 @@ bool video_context_driver_get_video_output_size(gfx_ctx_size_t *size_data) return true; } -bool video_context_driver_swap_interval(unsigned *interval) +bool video_context_driver_swap_interval(int *interval) { if (!current_video_context.swap_interval) return false; diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 4dd35f110b..3d9a099213 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -354,7 +354,7 @@ typedef struct video_info */ unsigned height; - unsigned swap_interval; + int swap_interval; #ifdef GEKKO bool vfilter; @@ -522,7 +522,7 @@ typedef struct gfx_ctx_driver unsigned major, unsigned minor); /* Sets the swap interval. */ - void (*swap_interval)(void *data, unsigned); + void (*swap_interval)(void *data, int); /* Sets video mode. Creates a window, etc. */ bool (*set_video_mode)(void*, video_frame_info_t *video_info, unsigned, unsigned, bool); @@ -1166,7 +1166,7 @@ void video_context_driver_destroy(void); bool video_context_driver_get_video_output_size(gfx_ctx_size_t *size_data); -bool video_context_driver_swap_interval(unsigned *interval); +bool video_context_driver_swap_interval(int *interval); bool video_context_driver_get_proc_address(gfx_ctx_proc_address_t *proc); From b771a3e0f58e786833f941e14d64a11dd062833f Mon Sep 17 00:00:00 2001 From: Sven <40953353+RetroSven@users.noreply.github.com> Date: Tue, 11 Sep 2018 18:45:01 -0400 Subject: [PATCH 068/335] move libretro.h defines to retroarch.h --- libretro-common/include/libretro.h | 18 ------------------ retroarch.h | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index bd95d508f6..a0966bf3d1 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1189,24 +1189,6 @@ struct retro_led_interface * Returns a MIDI interface that can be used for raw data I/O. */ -#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* bool * -- - * Boolean value that indicates whether or not the frontend is in - * fastforwarding mode. - */ - -#define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND (50 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* bool * -- - * Boolean value that tells the front end to save states in the - * background or not. - */ - -#define RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB (51 | RETRO_ENVIRONMENT_EXPERIMENTAL) - /* retro_environment_t * -- - * Provides the callback to the frontend method which will cancel - * all currently waiting threads. Used when coordination is needed - * between the core and the frontend to gracefully stop all threads. - */ /* Retrieves the current state of the MIDI input. diff --git a/retroarch.h b/retroarch.h index 46d882deed..9d8823ea26 100644 --- a/retroarch.h +++ b/retroarch.h @@ -33,6 +33,27 @@ RETRO_BEGIN_DECLS +#define RETRO_ENVIRONMENT_RETROARCH_START_BLOCK 0x800000 + +#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (1 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) + /* bool * -- + * Boolean value that indicates whether or not the frontend is in + * fastforwarding mode. + */ + +#define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND (2 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) + /* bool * -- + * Boolean value that tells the front end to save states in the + * background or not. + */ + +#define RETRO_ENVIRONMENT_GET_CLEAR_ALL_THREAD_WAITS_CB (3 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) + /* retro_environment_t * -- + * Provides the callback to the frontend method which will cancel + * all currently waiting threads. Used when coordination is needed + * between the core and the frontend to gracefully stop all threads. + */ + enum rarch_ctl_state { RARCH_CTL_NONE = 0, From 3c0eadbdf2ea96ba3f0150d1ee43622e9733e8b4 Mon Sep 17 00:00:00 2001 From: Sven <40953353+RetroSven@users.noreply.github.com> Date: Tue, 11 Sep 2018 18:52:51 -0400 Subject: [PATCH 069/335] per request --- libretro-common/include/libretro.h | 6 ++++++ retroarch.h | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index a0966bf3d1..dd015e9a75 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1189,6 +1189,12 @@ struct retro_led_interface * Returns a MIDI interface that can be used for raw data I/O. */ +#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (49 | RETRO_ENVIRONMENT_EXPERIMENTAL) + /* bool * -- + * Boolean value that indicates whether or not the frontend is in + * fastforwarding mode. + */ + /* Retrieves the current state of the MIDI input. diff --git a/retroarch.h b/retroarch.h index 9d8823ea26..596dce7d54 100644 --- a/retroarch.h +++ b/retroarch.h @@ -35,11 +35,6 @@ RETRO_BEGIN_DECLS #define RETRO_ENVIRONMENT_RETROARCH_START_BLOCK 0x800000 -#define RETRO_ENVIRONMENT_GET_FASTFORWARDING (1 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) - /* bool * -- - * Boolean value that indicates whether or not the frontend is in - * fastforwarding mode. - */ #define RETRO_ENVIRONMENT_SET_SAVE_STATE_IN_BACKGROUND (2 | RETRO_ENVIRONMENT_RETROARCH_START_BLOCK) /* bool * -- From 98b20d4e5d16f74f0bbf7b12e99f30d549c89850 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 02:41:45 +0200 Subject: [PATCH 070/335] (GLX/WGL) Start implementing adaptive VSync (swap_control_tear) for GLX/WGL pt. 1 --- gfx/drivers_context/wgl_ctx.c | 62 +++++++++++++++++++++++++++++------ gfx/drivers_context/x_ctx.c | 59 ++++++++++++++++++++++++--------- gfx/video_driver.h | 3 +- 3 files changed, 98 insertions(+), 26 deletions(-) diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index 959182ac7e..ed646ff1ea 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -47,6 +47,7 @@ #ifdef HAVE_OPENGL #include "../common/gl_common.h" +#include #endif #ifdef HAVE_VULKAN @@ -106,7 +107,7 @@ static dylib_t dll_handle = NULL; /* Handle to OpenGL32.dll */ typedef struct gfx_ctx_cgl_data { - void *empty; + bool adaptive_vsync; } gfx_ctx_wgl_data_t; static gfx_ctx_proc_t gfx_ctx_wgl_get_proc_address(const char *symbol) @@ -725,22 +726,63 @@ static void *gfx_ctx_wgl_get_context_data(void *data) static uint32_t gfx_ctx_wgl_get_flags(void *data) { - uint32_t flags = 0; - if (win32_core_hw_context_enable) + uint32_t flags = 0; + gfx_ctx_wgl_data_t *wgl = (gfx_ctx_wgl_data_t*)data; + + (void)wgl; + + BIT32_SET(flags, GFX_CTX_FLAGS_NONE); + + switch (win32_api) { - BIT32_SET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT); - } - else - { - BIT32_SET(flags, GFX_CTX_FLAGS_NONE); + case GFX_CTX_OPENGL_API: + if (wgl) + { + if (wgl->adaptive_vsync) + { + BIT32_SET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC); + } + } + + if (win32_core_hw_context_enable) + { + BIT32_SET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT); + } + break; + case GFX_CTX_NONE: + default: + break; } + return flags; } static void gfx_ctx_wgl_set_flags(void *data, uint32_t flags) { - if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) - win32_core_hw_context_enable = true; + gfx_ctx_wgl_data_t *wgl = (gfx_ctx_wgl_data_t*)data; + + (void)wgl; + + switch (win32_api) + { + case GFX_CTX_OPENGL_API: +#ifdef HAVE_OPENGL + if (wgl) + { + if (BIT32_GET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) + if (gl_query_extension("WGL_EXT_swap_control_tear")) + wgl->adaptive_vsync = true; + } + + if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) + win32_core_hw_context_enable = true; +#endif + break; + case GFX_CTX_NONE: + default: + break; + } + } static void gfx_ctx_wgl_get_video_output_size(void *data, diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index 15f0e6b04e..3d921777fa 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -25,6 +25,7 @@ #ifdef HAVE_OPENGL #include +#include #ifndef GLX_SAMPLE_BUFFERS #define GLX_SAMPLE_BUFFERS 100000 @@ -91,6 +92,7 @@ typedef struct gfx_ctx_x_data bool g_debug; bool g_should_reset_mode; bool g_is_double; + bool adaptive_vsync; bool core_hw_context_enable; #ifdef HAVE_OPENGL @@ -1167,30 +1169,57 @@ static void *gfx_ctx_x_get_context_data(void *data) static uint32_t gfx_ctx_x_get_flags(void *data) { - uint32_t flags = 0; + uint32_t flags = 0; gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data; - if (x->core_hw_context_enable || x->g_core_es) + + BIT32_SET(flags, GFX_CTX_FLAGS_NONE); + + switch (x_api) { - BIT32_SET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT); - } - else - { - BIT32_SET(flags, GFX_CTX_FLAGS_NONE); - } - if (x_enable_msaa) - { - BIT32_SET(flags, GFX_CTX_FLAGS_MULTISAMPLING); + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: + if (x->adaptive_vsync) + { + BIT32_SET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC); + } + + if (x->core_hw_context_enable || x->g_core_es) + { + BIT32_SET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT); + } + if (x_enable_msaa) + { + BIT32_SET(flags, GFX_CTX_FLAGS_MULTISAMPLING); + } + break; + case GFX_CTX_NONE: + default: + break; } + return flags; } static void gfx_ctx_x_set_flags(void *data, uint32_t flags) { gfx_ctx_x_data_t *x = (gfx_ctx_x_data_t*)data; - if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) - x->core_hw_context_enable = true; - if (BIT32_GET(flags, GFX_CTX_FLAGS_MULTISAMPLING)) - x_enable_msaa = true; + + switch (x_api) + { + case GFX_CTX_OPENGL_API: + case GFX_CTX_OPENGL_ES_API: + if (BIT32_GET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) + if (gl_query_extension("GLX_EXT_swap_control_tear")) + x->adaptive_vsync = true; + if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) + x->core_hw_context_enable = true; + if (BIT32_GET(flags, GFX_CTX_FLAGS_MULTISAMPLING)) + x_enable_msaa = true; + break; + case GFX_CTX_NONE: + default: + break; + } } static void gfx_ctx_x_make_current(bool release) diff --git a/gfx/video_driver.h b/gfx/video_driver.h index 3d9a099213..f2fe5675dd 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -118,7 +118,8 @@ enum display_flags GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES, GFX_CTX_FLAGS_HARD_SYNC, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION, - GFX_CTX_FLAGS_MENU_FRAME_FILTERING + GFX_CTX_FLAGS_MENU_FRAME_FILTERING, + GFX_CTX_FLAGS_ADAPTIVE_VSYNC }; enum shader_uniform_type From 914df58d2e5604130dabbedbf8b29f7570370430 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 03:59:25 +0200 Subject: [PATCH 071/335] (WGL) Adaptive Vsync should work now for WGL --- configuration.c | 1 + configuration.h | 1 + gfx/drivers_context/wgl_ctx.c | 76 ++++++++++++++++++++++++++--------- gfx/drivers_context/x_ctx.c | 2 +- gfx/video_driver.c | 7 +++- intl/msg_hash_ar.h | 8 ++++ intl/msg_hash_chs.h | 8 ++++ intl/msg_hash_cht.h | 8 ++++ intl/msg_hash_de.h | 8 ++++ intl/msg_hash_eo.h | 8 ++++ intl/msg_hash_es.h | 8 ++++ intl/msg_hash_fr.h | 8 ++++ intl/msg_hash_it.h | 8 ++++ intl/msg_hash_ja.h | 8 ++++ intl/msg_hash_ko.h | 8 ++++ intl/msg_hash_lbl.h | 2 + intl/msg_hash_nl.h | 8 ++++ intl/msg_hash_pl.h | 8 ++++ intl/msg_hash_pt_br.h | 8 ++++ intl/msg_hash_pt_pt.h | 8 ++++ intl/msg_hash_ru.h | 8 ++++ intl/msg_hash_us.h | 8 ++++ intl/msg_hash_vn.h | 8 ++++ menu/cbs/menu_cbs_sublabel.c | 4 ++ menu/menu_displaylist.c | 3 ++ menu/menu_setting.c | 34 ++++++++++++++++ msg_hash.h | 1 + 27 files changed, 247 insertions(+), 20 deletions(-) diff --git a/configuration.c b/configuration.c index cd33faec0d..4c8b373ff3 100644 --- a/configuration.c +++ b/configuration.c @@ -1306,6 +1306,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings, SETTING_BOOL("video_fullscreen", &settings->bools.video_fullscreen, true, fullscreen, false); SETTING_BOOL("bundle_assets_extract_enable", &settings->bools.bundle_assets_extract_enable, true, bundle_assets_extract_enable, false); SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, vsync, false); + SETTING_BOOL("video_adaptive_vsync", &settings->bools.video_adaptive_vsync, true, false, false); SETTING_BOOL("video_hard_sync", &settings->bools.video_hard_sync, true, hard_sync, false); SETTING_BOOL("video_black_frame_insertion", &settings->bools.video_black_frame_insertion, true, black_frame_insertion, false); SETTING_BOOL("crt_switch_resolution", &settings->bools.crt_switch_resolution, true, crt_switch_resolution, false); diff --git a/configuration.h b/configuration.h index 5405104055..c3a4c9c539 100644 --- a/configuration.h +++ b/configuration.h @@ -73,6 +73,7 @@ typedef struct settings bool video_fullscreen; bool video_windowed_fullscreen; bool video_vsync; + bool video_adaptive_vsync; bool video_hard_sync; bool video_black_frame_insertion; bool video_vfilter; diff --git a/gfx/drivers_context/wgl_ctx.c b/gfx/drivers_context/wgl_ctx.c index ed646ff1ea..b90a8e40c3 100644 --- a/gfx/drivers_context/wgl_ctx.c +++ b/gfx/drivers_context/wgl_ctx.c @@ -91,6 +91,7 @@ static HGLRC win32_hw_hrc; static HDC win32_hdc; static bool win32_use_hw_ctx = false; static bool win32_core_hw_context_enable = false; +static bool wgl_adaptive_vsync = false; #ifdef HAVE_VULKAN static gfx_ctx_vulkan_data_t win32_vk; @@ -105,9 +106,41 @@ static enum gfx_ctx_api win32_api = GFX_CTX_NONE; static dylib_t dll_handle = NULL; /* Handle to OpenGL32.dll */ #endif +#ifdef HAVE_OPENGL +static bool wgl_has_extension(const char *extension, const char *extensions) +{ + const char *start = NULL; + const char *terminator = NULL; + const char *where = strchr(extension, ' '); + + if (where || *extension == '\0') + return false; + + if (!extensions) + return false; + + start = extensions; + + for (;;) + { + where = strstr(start, extension); + if (!where) + break; + + terminator = where + strlen(extension); + if (where == start || *(where - 1) == ' ') + if (*terminator == ' ' || *terminator == '\0') + return true; + + start = terminator; + } + return false; +} +#endif + typedef struct gfx_ctx_cgl_data { - bool adaptive_vsync; + void *empty; } gfx_ctx_wgl_data_t; static gfx_ctx_proc_t gfx_ctx_wgl_get_proc_address(const char *symbol) @@ -264,6 +297,23 @@ static void create_gl_context(HWND hwnd, bool *quit) else RARCH_ERR("[WGL]: wglCreateContextAttribsARB not supported.\n"); } + + { + + const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0; + const char *extensions = NULL; + + wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC)) + gfx_ctx_wgl_get_proc_address("wglGetExtensionsStringARB"); + if (wglGetExtensionsStringARB) + extensions = wglGetExtensionsStringARB(win32_hdc); + RARCH_LOG("[WGL] extensions: %s\n", extensions); + if (wgl_has_extension("WGL_EXT_swap_control_tear", extensions)) + { + RARCH_LOG("[WGL]: Adaptive VSync supported.\n"); + wgl_adaptive_vsync = true; + } + } } #endif @@ -323,7 +373,7 @@ static void gfx_ctx_wgl_swap_interval(void *data, int interval) if (!p_swap_interval) return; - RARCH_LOG("[WGL]: wglSwapInterval(%u)\n", win32_interval); + RARCH_LOG("[WGL]: wglSwapInterval(%i)\n", win32_interval); if (!p_swap_interval(win32_interval)) RARCH_WARN("[WGL]: wglSwapInterval() failed.\n"); #endif @@ -479,6 +529,7 @@ static void *gfx_ctx_wgl_init(video_frame_info_t *video_info, void *video_driver #ifdef HAVE_DYNAMIC dll_handle = dylib_load("OpenGL32.dll"); #endif + win32_window_reset(); win32_monitor_init(); @@ -573,6 +624,7 @@ static void gfx_ctx_wgl_destroy(void *data) if (wgl) free(wgl); + wgl_adaptive_vsync = false; win32_core_hw_context_enable = false; g_win32_inited = false; win32_major = 0; @@ -727,21 +779,15 @@ static void *gfx_ctx_wgl_get_context_data(void *data) static uint32_t gfx_ctx_wgl_get_flags(void *data) { uint32_t flags = 0; - gfx_ctx_wgl_data_t *wgl = (gfx_ctx_wgl_data_t*)data; - - (void)wgl; BIT32_SET(flags, GFX_CTX_FLAGS_NONE); switch (win32_api) { case GFX_CTX_OPENGL_API: - if (wgl) + if (wgl_adaptive_vsync) { - if (wgl->adaptive_vsync) - { - BIT32_SET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC); - } + BIT32_SET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC); } if (win32_core_hw_context_enable) @@ -759,19 +805,13 @@ static uint32_t gfx_ctx_wgl_get_flags(void *data) static void gfx_ctx_wgl_set_flags(void *data, uint32_t flags) { - gfx_ctx_wgl_data_t *wgl = (gfx_ctx_wgl_data_t*)data; - - (void)wgl; - switch (win32_api) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL - if (wgl) + if (BIT32_GET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) { - if (BIT32_GET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) - if (gl_query_extension("WGL_EXT_swap_control_tear")) - wgl->adaptive_vsync = true; + wgl_adaptive_vsync = true; } if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index 3d921777fa..bd3e1a7600 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -1209,7 +1209,7 @@ static void gfx_ctx_x_set_flags(void *data, uint32_t flags) case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: if (BIT32_GET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) - if (gl_query_extension("GLX_EXT_swap_control_tear")) + if (GLXExtensionSupported(g_x11_dpy, "GLX_EXT_swap_control_tear")) x->adaptive_vsync = true; if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) x->core_hw_context_enable = true; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index f3af9a5661..1459dfb9f2 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -3204,9 +3204,14 @@ bool video_context_driver_get_video_output_size(gfx_ctx_size_t *size_data) bool video_context_driver_swap_interval(int *interval) { + int current_interval = *interval; + settings_t *settings = config_get_ptr(); + bool adaptive_vsync_enabled = settings->bools.video_adaptive_vsync; if (!current_video_context.swap_interval) return false; - current_video_context.swap_interval(video_context_data, *interval); + if (adaptive_vsync_enabled && current_interval == 1) + current_interval = -1; + current_video_context.swap_interval(video_context_data, current_interval); return true; } diff --git a/intl/msg_hash_ar.h b/intl/msg_hash_ar.h index 881210a828..d9f60eac47 100644 --- a/intl/msg_hash_ar.h +++ b/intl/msg_hash_ar.h @@ -3541,3 +3541,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_chs.h b/intl/msg_hash_chs.h index c8ff8960de..2f0bb64b8e 100644 --- a/intl/msg_hash_chs.h +++ b/intl/msg_hash_chs.h @@ -3325,3 +3325,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_cht.h b/intl/msg_hash_cht.h index dcc7565720..9c42ab1356 100644 --- a/intl/msg_hash_cht.h +++ b/intl/msg_hash_cht.h @@ -3317,3 +3317,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_de.h b/intl/msg_hash_de.h index 239899abab..21043221fc 100644 --- a/intl/msg_hash_de.h +++ b/intl/msg_hash_de.h @@ -3427,3 +3427,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_eo.h b/intl/msg_hash_eo.h index e157edfc74..fede89901c 100644 --- a/intl/msg_hash_eo.h +++ b/intl/msg_hash_eo.h @@ -3192,3 +3192,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_es.h b/intl/msg_hash_es.h index 34ede5266d..dadcb3b461 100644 --- a/intl/msg_hash_es.h +++ b/intl/msg_hash_es.h @@ -7422,3 +7422,11 @@ MSG_HASH( MSG_FAILED_TO_SET_DISK, "Fallo al establecer disco" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_fr.h b/intl/msg_hash_fr.h index b5d3ab766a..24d45b77ee 100644 --- a/intl/msg_hash_fr.h +++ b/intl/msg_hash_fr.h @@ -3351,3 +3351,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_it.h b/intl/msg_hash_it.h index ec334aef13..11074b5ab2 100644 --- a/intl/msg_hash_it.h +++ b/intl/msg_hash_it.h @@ -3411,3 +3411,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Modalità delle Prestazioni Sostenute") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "supporto mpv ") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_ja.h b/intl/msg_hash_ja.h index 7911d839f5..bfbb911e3a 100644 --- a/intl/msg_hash_ja.h +++ b/intl/msg_hash_ja.h @@ -3812,3 +3812,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DOWNLOAD_PLAYLIST_THUMBNAIL_PROGRESS, "成功した数: %1 失敗した数: %2") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS, "コア設定") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_ko.h b/intl/msg_hash_ko.h index f867b18e6c..a36c182ecd 100644 --- a/intl/msg_hash_ko.h +++ b/intl/msg_hash_ko.h @@ -3312,3 +3312,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index 1dac8eef33..2272899afd 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -1257,6 +1257,8 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_VI_WIDTH, "video_vi_width") MSG_HASH(MENU_ENUM_LABEL_VIDEO_VSYNC, "video_vsync") +MSG_HASH(MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC, + "video_adaptive_vsync") MSG_HASH(MENU_ENUM_LABEL_VIDEO_WINDOWED_FULLSCREEN, "video_windowed_fullscreen") MSG_HASH(MENU_ENUM_LABEL_VIDEO_WINDOW_WIDTH, diff --git a/intl/msg_hash_nl.h b/intl/msg_hash_nl.h index 63f5d9db7a..e34bf9b3e3 100644 --- a/intl/msg_hash_nl.h +++ b/intl/msg_hash_nl.h @@ -3194,3 +3194,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_pl.h b/intl/msg_hash_pl.h index a5f446850f..635f78986e 100644 --- a/intl/msg_hash_pl.h +++ b/intl/msg_hash_pl.h @@ -3622,3 +3622,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Trwały tryb wydajności") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "Wsparcie dla MPV") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_pt_br.h b/intl/msg_hash_pt_br.h index 96d3f2dc6e..651740f6da 100644 --- a/intl/msg_hash_pt_br.h +++ b/intl/msg_hash_pt_br.h @@ -7441,3 +7441,11 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS, "Opções de Núcleo" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_pt_pt.h b/intl/msg_hash_pt_pt.h index c20eaff54a..b153480cfc 100644 --- a/intl/msg_hash_pt_pt.h +++ b/intl/msg_hash_pt_pt.h @@ -3286,3 +3286,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_ru.h b/intl/msg_hash_ru.h index d18c31f741..b1ccf90a49 100644 --- a/intl/msg_hash_ru.h +++ b/intl/msg_hash_ru.h @@ -3482,3 +3482,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index be02410a94..b254dd85af 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -7442,3 +7442,11 @@ MSG_HASH( MENU_ENUM_LABEL_VALUE_QT_CORE_OPTIONS, "Core Options" ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/intl/msg_hash_vn.h b/intl/msg_hash_vn.h index 9cd2329191..dcc872ed5e 100644 --- a/intl/msg_hash_vn.h +++ b/intl/msg_hash_vn.h @@ -3349,3 +3349,11 @@ MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Sustained Performance Mode") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "mpv support") +MSG_HASH( + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + "Adaptive Vsync" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC, + "V-Sync is enabled until performance falls below the target refresh rate. Can minimize stuttering when performance falls below realtime, and can be more energy efficient." + ) diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 2c292437f0..70727956c8 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -154,6 +154,7 @@ default_sublabel_macro(action_bind_sublabel_axis_threshold, MENU_ default_sublabel_macro(action_bind_sublabel_input_turbo_period, MENU_ENUM_SUBLABEL_INPUT_TURBO_PERIOD) default_sublabel_macro(action_bind_sublabel_input_duty_cycle, MENU_ENUM_SUBLABEL_INPUT_DUTY_CYCLE) default_sublabel_macro(action_bind_sublabel_video_vertical_sync, MENU_ENUM_SUBLABEL_VIDEO_VSYNC) +default_sublabel_macro(action_bind_sublabel_video_adaptive_vsync, MENU_ENUM_SUBLABEL_VIDEO_ADAPTIVE_VSYNC) default_sublabel_macro(action_bind_sublabel_core_allow_rotate, MENU_ENUM_SUBLABEL_VIDEO_ALLOW_ROTATE) default_sublabel_macro(action_bind_sublabel_dummy_on_core_shutdown, MENU_ENUM_SUBLABEL_DUMMY_ON_CORE_SHUTDOWN) default_sublabel_macro(action_bind_sublabel_dummy_check_missing_firmware, MENU_ENUM_SUBLABEL_CHECK_FOR_MISSING_FIRMWARE) @@ -1625,6 +1626,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_VIDEO_VSYNC: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_vertical_sync); break; + case MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_video_adaptive_vsync); + break; case MENU_ENUM_LABEL_INPUT_DUTY_CYCLE: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_duty_cycle); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 1801b78e16..5d2e3377be 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -6394,6 +6394,9 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data) menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_SWAP_INTERVAL, PARSE_ONLY_UINT, false); + menu_displaylist_parse_settings_enum(menu, info, + MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC, + PARSE_ONLY_BOOL, false); if (menu_displaylist_parse_settings_enum(menu, info, MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES, PARSE_ONLY_UINT, false) == 0) diff --git a/menu/menu_setting.c b/menu/menu_setting.c index a83667cd68..decb1c23f9 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -4415,6 +4415,40 @@ static bool setting_append_list( } } + { + gfx_ctx_flags_t flags; + bool adaptive_vsync_supported = false; + + if (video_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) + adaptive_vsync_supported = true; + + flags.flags = 0; + + if (video_context_driver_get_flags(&flags)) + if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) + adaptive_vsync_supported = true; + + if (adaptive_vsync_supported) + { + CONFIG_BOOL( + list, list_info, + &settings->bools.video_adaptive_vsync, + MENU_ENUM_LABEL_VIDEO_ADAPTIVE_VSYNC, + MENU_ENUM_LABEL_VALUE_VIDEO_ADAPTIVE_VSYNC, + false, + MENU_ENUM_LABEL_VALUE_OFF, + MENU_ENUM_LABEL_VALUE_ON, + &group_info, + &subgroup_info, + parent_group, + general_write_handler, + general_read_handler, + SD_FLAG_NONE + ); + } + } + CONFIG_UINT( list, list_info, &settings->uints.video_frame_delay, diff --git a/msg_hash.h b/msg_hash.h index 33b1719565..4287dffeb4 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -715,6 +715,7 @@ enum msg_hash_enums MENU_LABEL(VIDEO_BLACK_FRAME_INSERTION), MENU_LABEL(VIDEO_FRAME_DELAY), MENU_LABEL(VIDEO_VSYNC), + MENU_LABEL(VIDEO_ADAPTIVE_VSYNC), MENU_LABEL(VIDEO_HARD_SYNC), MENU_LABEL(VIDEO_HARD_SYNC_FRAMES), MENU_LABEL(VIDEO_WINDOWED_FULLSCREEN), From 58472cb696ffe2661ec53f87126f0470f366def0 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 04:09:19 +0200 Subject: [PATCH 072/335] Silence some warnings --- network/netplay/netplay_frontend.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 0919662210..19775f5f0e 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -634,14 +634,14 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er if (task_data) { - http_transfer_data_t *data = (http_transfer_data_t*)task_data; - struct string_list *lines; - struct netplay_room *host_room = netplay_get_host_room(); unsigned i, ip_len, port_len; - const char *mitm_ip = NULL; - const char *mitm_port = NULL; - char *buf; - char *host_string; + http_transfer_data_t *data = (http_transfer_data_t*)task_data; + struct netplay_room *host_room = netplay_get_host_room(); + struct string_list *lines = NULL; + char *mitm_ip = NULL; + char *mitm_port = NULL; + char *buf = NULL; + char *host_string = NULL; if (data->len == 0) { From 3f8e3547f4d60758e889b89029a11ec2784c7dc3 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 04:17:41 +0200 Subject: [PATCH 073/335] (GLX) swap_control_tear should now be implemented and working --- gfx/drivers_context/x_ctx.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/gfx/drivers_context/x_ctx.c b/gfx/drivers_context/x_ctx.c index bd3e1a7600..f04d6d850d 100644 --- a/gfx/drivers_context/x_ctx.c +++ b/gfx/drivers_context/x_ctx.c @@ -92,7 +92,6 @@ typedef struct gfx_ctx_x_data bool g_debug; bool g_should_reset_mode; bool g_is_double; - bool adaptive_vsync; bool core_hw_context_enable; #ifdef HAVE_OPENGL @@ -109,6 +108,7 @@ typedef struct gfx_ctx_x_data #endif } gfx_ctx_x_data_t; +static bool x_adaptive_vsync = false; static bool x_enable_msaa = false; static unsigned g_major = 0; static unsigned g_minor = 0; @@ -335,18 +335,18 @@ static void gfx_ctx_x_swap_interval(void *data, int interval) if (g_pglSwapIntervalEXT) { - RARCH_LOG("[GLX]: glXSwapIntervalEXT(%u)\n", x->g_interval); + RARCH_LOG("[GLX]: glXSwapIntervalEXT(%i)\n", x->g_interval); g_pglSwapIntervalEXT(g_x11_dpy, x->g_glx_win, x->g_interval); } else if (g_pglSwapInterval) { - RARCH_LOG("[GLX]: glXSwapInterval(%u)\n", x->g_interval); + RARCH_LOG("[GLX]: glXSwapInterval(%i)\n", x->g_interval); if (g_pglSwapInterval(x->g_interval) != 0) RARCH_WARN("[GLX]: glXSwapInterval() failed.\n"); } else if (g_pglSwapIntervalSGI) { - RARCH_LOG("[GLX]: glXSwapIntervalSGI(%u)\n", x->g_interval); + RARCH_LOG("[GLX]: glXSwapIntervalSGI(%i)\n", x->g_interval); if (g_pglSwapIntervalSGI(x->g_interval) != 0) RARCH_WARN("[GLX]: glXSwapIntervalSGI() failed.\n"); } @@ -583,6 +583,11 @@ static void *gfx_ctx_x_init(video_frame_info_t *video_info, void *data) { case GFX_CTX_OPENGL_API: #ifdef HAVE_OPENGL + if (GLXExtensionSupported(g_x11_dpy, "GLX_EXT_swap_control_tear")) + { + RARCH_LOG("[GLX]: GLX_EXT_swap_control_tear supported.\n"); + x_adaptive_vsync = true; + } if (GLXExtensionSupported(g_x11_dpy, "GLX_OML_sync_control") && GLXExtensionSupported(g_x11_dpy, "GLX_MESA_swap_control") ) @@ -1178,7 +1183,7 @@ static uint32_t gfx_ctx_x_get_flags(void *data) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: - if (x->adaptive_vsync) + if (x_adaptive_vsync) { BIT32_SET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC); } @@ -1209,8 +1214,7 @@ static void gfx_ctx_x_set_flags(void *data, uint32_t flags) case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: if (BIT32_GET(flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) - if (GLXExtensionSupported(g_x11_dpy, "GLX_EXT_swap_control_tear")) - x->adaptive_vsync = true; + x_adaptive_vsync = true; if (BIT32_GET(flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT)) x->core_hw_context_enable = true; if (BIT32_GET(flags, GFX_CTX_FLAGS_MULTISAMPLING)) From 3c160a6eb40dad8afe633c7b00d1306bb40e7b8e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 06:31:41 +0200 Subject: [PATCH 074/335] Create video_driver_get_all_flags --- gfx/video_driver.c | 15 +++++++++++ gfx/video_driver.h | 3 +++ menu/menu_setting.c | 65 ++++----------------------------------------- 3 files changed, 23 insertions(+), 60 deletions(-) diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 1459dfb9f2..22e16e66d3 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -3339,6 +3339,21 @@ void video_context_driver_set_data(void *data) video_context_data = data; } +bool video_driver_get_all_flags(gfx_ctx_flags_t *flags, enum display_flags flag) +{ + if (video_driver_get_flags(flags)) + if (BIT32_GET(flags->flags, flag)) + return true; + + flags->flags = 0; + + if (video_context_driver_get_flags(flags)) + if (BIT32_GET(flags->flags, flag)) + return true; + + return false; +} + bool video_driver_get_flags(gfx_ctx_flags_t *flags) { if (!flags || !video_driver_poke || !video_driver_poke->get_flags) diff --git a/gfx/video_driver.h b/gfx/video_driver.h index f2fe5675dd..c83d15fbc4 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -1249,6 +1249,9 @@ bool video_driver_started_fullscreen(void); bool video_driver_is_threaded(void); +bool video_driver_get_all_flags(gfx_ctx_flags_t *flags, + enum display_flags flag); + extern video_driver_t video_gl; extern video_driver_t video_vulkan; extern video_driver_t video_metal; diff --git a/menu/menu_setting.c b/menu/menu_setting.c index decb1c23f9..298208640c 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -4338,19 +4338,8 @@ static bool setting_append_list( { gfx_ctx_flags_t flags; - bool customizable_swapchain_set = false; - if (video_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES)) - customizable_swapchain_set = true; - - flags.flags = 0; - - if (video_context_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES)) - customizable_swapchain_set = true; - - if (customizable_swapchain_set) + if (video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_CUSTOMIZABLE_SWAPCHAIN_IMAGES)) { CONFIG_UINT( list, list_info, @@ -4370,19 +4359,8 @@ static bool setting_append_list( { gfx_ctx_flags_t flags; - bool hard_sync_supported = false; - if (video_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_HARD_SYNC)) - hard_sync_supported = true; - - flags.flags = 0; - - if (video_context_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_HARD_SYNC)) - hard_sync_supported = true; - - if (hard_sync_supported) + if (video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_HARD_SYNC)) { CONFIG_BOOL( list, list_info, @@ -4417,19 +4395,8 @@ static bool setting_append_list( { gfx_ctx_flags_t flags; - bool adaptive_vsync_supported = false; - if (video_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) - adaptive_vsync_supported = true; - - flags.flags = 0; - - if (video_context_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) - adaptive_vsync_supported = true; - - if (adaptive_vsync_supported) + if (video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC)) { CONFIG_BOOL( list, list_info, @@ -4466,19 +4433,8 @@ static bool setting_append_list( #if !defined(RARCH_MOBILE) { gfx_ctx_flags_t flags; - bool black_frame_insertion_supported = false; - if (video_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION)) - black_frame_insertion_supported = true; - - flags.flags = 0; - - if (video_context_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION)) - black_frame_insertion_supported = true; - - if (black_frame_insertion_supported) + if (video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_BLACK_FRAME_INSERTION)) { CONFIG_BOOL( list, list_info, @@ -6019,17 +5975,6 @@ static bool setting_append_list( if (string_is_equal(settings->arrays.menu_driver, "rgui")) { gfx_ctx_flags_t flags; - bool setting_set = false; - - if (video_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING)) - setting_set = true; - - flags.flags = 0; - - if (video_context_driver_get_flags(&flags)) - if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING)) - setting_set = true; CONFIG_BOOL( list, list_info, @@ -6079,7 +6024,7 @@ static bool setting_append_list( SD_FLAG_NONE ); - if (setting_set) + if (video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_MENU_FRAME_FILTERING)) CONFIG_BOOL( list, list_info, &settings->bools.menu_linear_filter, From 650c17312515d31f23f8a27caf44169ebb84f18e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 06:39:07 +0200 Subject: [PATCH 075/335] Turn public functions into static functions --- gfx/video_driver.c | 50 +++++++++++++++++++++++----------------------- gfx/video_driver.h | 6 ------ 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 22e16e66d3..9f9f72ba78 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -3028,7 +3028,7 @@ static const gfx_ctx_driver_t *video_context_driver_init( ctx->bind_hw_render(ctx_data, video_info.shared_context && hw_render_ctx); - video_context_driver_set_data(ctx_data); + video_context_data = ctx_data; return ctx; } @@ -3334,13 +3334,35 @@ bool video_context_driver_show_mouse(bool *bool_data) return true; } -void video_context_driver_set_data(void *data) +static bool video_context_driver_get_flags(gfx_ctx_flags_t *flags) { - video_context_data = data; + if (!current_video_context.get_flags) + return false; + + if (deferred_video_context_driver_set_flags) + { + flags->flags = deferred_flag_data.flags; + deferred_video_context_driver_set_flags = false; + return true; + } + + flags->flags = current_video_context.get_flags(video_context_data); + return true; +} + +static bool video_driver_get_flags(gfx_ctx_flags_t *flags) +{ + if (!video_driver_poke || !video_driver_poke->get_flags) + return false; + flags->flags = video_driver_poke->get_flags(video_driver_data); + return true; } bool video_driver_get_all_flags(gfx_ctx_flags_t *flags, enum display_flags flag) { + if (!flags) + return false; + if (video_driver_get_flags(flags)) if (BIT32_GET(flags->flags, flag)) return true; @@ -3354,29 +3376,7 @@ bool video_driver_get_all_flags(gfx_ctx_flags_t *flags, enum display_flags flag) return false; } -bool video_driver_get_flags(gfx_ctx_flags_t *flags) -{ - if (!flags || !video_driver_poke || !video_driver_poke->get_flags) - return false; - flags->flags = video_driver_poke->get_flags(video_driver_data); - return true; -} -bool video_context_driver_get_flags(gfx_ctx_flags_t *flags) -{ - if (!flags || !current_video_context.get_flags) - return false; - - if (deferred_video_context_driver_set_flags) - { - flags->flags = deferred_flag_data.flags; - deferred_video_context_driver_set_flags = false; - return true; - } - - flags->flags = current_video_context.get_flags(video_context_data); - return true; -} bool video_context_driver_set_flags(gfx_ctx_flags_t *flags) { diff --git a/gfx/video_driver.h b/gfx/video_driver.h index c83d15fbc4..85573d230e 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -1185,12 +1185,6 @@ bool video_context_driver_get_context_data(void *data); bool video_context_driver_show_mouse(bool *bool_data); -void video_context_driver_set_data(void *data); - -bool video_driver_get_flags(gfx_ctx_flags_t *flags); - -bool video_context_driver_get_flags(gfx_ctx_flags_t *flags); - bool video_context_driver_set_flags(gfx_ctx_flags_t *flags); bool video_context_driver_get_metrics(gfx_ctx_metrics_t *metrics); From d52f5cc0d466ab81671f458852fb378a42b1255b Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Wed, 12 Sep 2018 06:43:33 +0200 Subject: [PATCH 076/335] Update CHANGES.md --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index ab9128cc8c..a91cc35d7c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,8 @@ - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. - NETPLAY: Save lobby details received back from server after first announcement. +- OPENGL/GLX: Implement Adaptive VSync - XGL_EXT_swap_control_tear. +- OPENGL/WGL: Implement Adaptive VSync - WGL_EXT_swap_control_tear. - VULKAN: Fix race condition in threaded mailbox emulation. - VULKAN: Maintenance fixes. From 9017e209e846b1b8a9f0f7316bedf5bdb6ea45af Mon Sep 17 00:00:00 2001 From: Twinaphex Date: Wed, 12 Sep 2018 06:44:53 +0200 Subject: [PATCH 077/335] Update CHANGES.md --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index a91cc35d7c..574c314c8f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,7 +8,7 @@ - MENU/QT/WIMP: Add option to filter extensions inside archives when adding to a playlist. - METAL: Add screenshot support. - NETPLAY: Save lobby details received back from server after first announcement. -- OPENGL/GLX: Implement Adaptive VSync - XGL_EXT_swap_control_tear. +- OPENGL/GLX: Implement Adaptive VSync - GLX_EXT_swap_control_tear. - OPENGL/WGL: Implement Adaptive VSync - WGL_EXT_swap_control_tear. - VULKAN: Fix race condition in threaded mailbox emulation. - VULKAN: Maintenance fixes. From bf75e6b9d790d2c0613fd9075b036e7a0460802e Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 07:16:08 +0200 Subject: [PATCH 078/335] video_context_driver_swap_interval - add in safeguard --- gfx/video_driver.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gfx/video_driver.c b/gfx/video_driver.c index 9f9f72ba78..4ae7d2d5e2 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -3204,9 +3204,11 @@ bool video_context_driver_get_video_output_size(gfx_ctx_size_t *size_data) bool video_context_driver_swap_interval(int *interval) { + gfx_ctx_flags_t flags; int current_interval = *interval; settings_t *settings = config_get_ptr(); - bool adaptive_vsync_enabled = settings->bools.video_adaptive_vsync; + bool adaptive_vsync_enabled = video_driver_get_all_flags(&flags, GFX_CTX_FLAGS_ADAPTIVE_VSYNC) && settings->bools.video_adaptive_vsync; + if (!current_video_context.swap_interval) return false; if (adaptive_vsync_enabled && current_interval == 1) From 9cbd7ec6f37637e83e8f26cb761dc907a43bdc97 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 08:01:19 +0200 Subject: [PATCH 079/335] (RGUI) Add some Switch ifdefs to RGUI --- menu/drivers/rgui.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index 4c7beca70b..44ba76e40f 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -95,6 +95,10 @@ static uint16_t rgui_gray_filler(rgui_t *rgui, unsigned x, unsigned y) unsigned col = (((x >> shft) + (y >> shft)) & 1) + 1; #if defined(GEKKO) || defined(PSP) return (6 << 12) | (col << 8) | (col << 4) | (col << 0); +#elif defined(SWITCH) + return (((31 * (54)) / 255) << 11) | + (((63 * (54)) / 255) << 5) | + ((31 * (54)) / 255); #else return (col << 13) | (col << 9) | (col << 5) | (12 << 0); #endif @@ -106,6 +110,10 @@ static uint16_t rgui_green_filler(rgui_t *rgui, unsigned x, unsigned y) unsigned col = (((x >> shft) + (y >> shft)) & 1) + 1; #if defined(GEKKO) || defined(PSP) return (6 << 12) | (col << 8) | (col << 5) | (col << 0); +#elif defined(SWITCH) + return (((31 * (54)) / 255) << 11) | + (((63 * (109)) / 255) << 5) | + ((31 * (54)) / 255); #else return (col << 13) | (col << 10) | (col << 5) | (12 << 0); #endif From 2a7a2e7dee9ea01e35982dc5837ebbd13008456c Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 08:14:17 +0200 Subject: [PATCH 080/335] (LIBNX) Start backporting libnx code; beginning with audio drivers --- audio/audio_driver.c | 3 + audio/audio_driver.h | 1 + audio/drivers/switch_audio.c | 9 +- audio/drivers/switch_nx_audio.c | 284 ++++++++++++++++++++ audio/drivers/switch_nx_thread_audio.c | 355 +++++++++++++++++++++++++ 5 files changed, 648 insertions(+), 4 deletions(-) create mode 100644 audio/drivers/switch_nx_audio.c create mode 100644 audio/drivers/switch_nx_thread_audio.c diff --git a/audio/audio_driver.c b/audio/audio_driver.c index b7eb32aa69..161b5989b4 100644 --- a/audio/audio_driver.c +++ b/audio/audio_driver.c @@ -125,6 +125,9 @@ static const audio_driver_t *audio_drivers[] = { #endif #ifdef SWITCH &audio_switch, +#ifdef HAVE_LIBNX + &audio_switch_thread, +#endif #endif &audio_null, NULL, diff --git a/audio/audio_driver.h b/audio/audio_driver.h index a2cdad4f41..1d67fa0768 100644 --- a/audio/audio_driver.h +++ b/audio/audio_driver.h @@ -338,6 +338,7 @@ extern audio_driver_t audio_psp; extern audio_driver_t audio_ctr_csnd; extern audio_driver_t audio_ctr_dsp; extern audio_driver_t audio_switch; +extern audio_driver_t audio_switch_thread; extern audio_driver_t audio_rwebaudio; extern audio_driver_t audio_null; diff --git a/audio/drivers/switch_audio.c b/audio/drivers/switch_audio.c index 3a06cc7398..322750bba0 100644 --- a/audio/drivers/switch_audio.c +++ b/audio/drivers/switch_audio.c @@ -30,14 +30,15 @@ static const size_t sample_buffer_size = ((max_num_samples * num_channels * size typedef struct { - audio_output_t output; - handle_t event; - audio_output_buffer_t buffers[3]; - audio_output_buffer_t *current_buffer; bool blocking; bool is_paused; uint64_t last_append; unsigned latency; + audio_output_buffer_t buffers[3]; + audio_output_buffer_t *current_buffer; + + audio_output_t output; + handle_t event; } switch_audio_t; static ssize_t switch_audio_write(void *data, const void *buf, size_t size) diff --git a/audio/drivers/switch_nx_audio.c b/audio/drivers/switch_nx_audio.c new file mode 100644 index 0000000000..9a31eb9211 --- /dev/null +++ b/audio/drivers/switch_nx_audio.c @@ -0,0 +1,284 @@ +/* RetroArch - A frontend for libretro. + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include + +#include + +#include "../audio_driver.h" +#include "../../verbosity.h" + +#include "../../tasks/tasks_internal.h" + +typedef struct +{ + bool blocking; + bool is_paused; + uint64_t last_append; + unsigned latency; + AudioOutBuffer buffers[5]; + AudioOutBuffer *current_buffer; +} switch_audio_t; + +static bool switch_tasks_finder(retro_task_t *task, void *userdata) +{ + return task; +} +task_finder_data_t switch_tasks_finder_data = {switch_tasks_finder, NULL}; + +#define SAMPLERATE 48000 +#define CHANNELCOUNT 2 +#define FRAMERATE (1000 / 30) +#define SAMPLECOUNT SAMPLERATE / FRAMERATE +#define BYTESPERSAMPLE sizeof(uint16_t) + +static uint32_t switch_audio_data_size(void) +{ + return (SAMPLECOUNT * CHANNELCOUNT * BYTESPERSAMPLE); +} + +static size_t switch_audio_buffer_size(void *data) +{ + (void)data; + return (switch_audio_data_size() + 0xfff) & ~0xfff; +} + +static ssize_t switch_audio_write(void *data, const void *buf, size_t size) +{ + size_t to_write = size; + switch_audio_t *swa = (switch_audio_t *)data; + + if (!swa) + { + return -1; + } + + if (!swa->current_buffer) + { + uint32_t num; + if (R_FAILED(audoutGetReleasedAudioOutBuffer(&swa->current_buffer, &num))) + return -1; + + if (num < 1) + { + swa->current_buffer = NULL; + + if (swa->blocking) + { + /* No buffer, blocking... */ + + while (swa->current_buffer == NULL) + { + num = 0; + if (R_FAILED(audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX))) + { +#if 0 + if (task_queue_find(&switch_tasks_finder_data)) + task_queue_check(); +#endif + } + } + } + else + return 0; + } + + swa->current_buffer->data_size = 0; + } + + if (to_write > switch_audio_buffer_size(NULL) - swa->current_buffer->data_size) + to_write = switch_audio_buffer_size(NULL) - swa->current_buffer->data_size; + + memcpy(((uint8_t *)swa->current_buffer->buffer) + swa->current_buffer->data_size, buf, to_write); + swa->current_buffer->data_size += to_write; + swa->current_buffer->buffer_size = switch_audio_buffer_size(NULL); + + if (swa->current_buffer->data_size > (48000 * swa->latency) / 1000) + { + Result r = audoutAppendAudioOutBuffer(swa->current_buffer); + if (R_FAILED(r)) + return -1; + swa->current_buffer = NULL; + } + + swa->last_append = svcGetSystemTick(); + + return to_write; +} + +static bool switch_audio_stop(void *data) +{ + return true; + + switch_audio_t *swa = (switch_audio_t *)data; + if (!swa) + return false; + + if (!swa->is_paused) + { + Result rc = audoutStopAudioOut(); + if (R_FAILED(rc)) + return false; + } + + swa->is_paused = true; + return true; +} + +static bool switch_audio_start(void *data, bool is_shutdown) +{ + return true; + + switch_audio_t *swa = (switch_audio_t *)data; + if (!swa) + return false; + + if (swa->is_paused) + { + Result rc = audoutStartAudioOut(); + if (R_FAILED(rc)) + return false; + } + + swa->is_paused = false; + return true; +} + +static bool switch_audio_alive(void *data) +{ + switch_audio_t *swa = (switch_audio_t *)data; + if (!swa) + return false; + return !swa->is_paused; +} + +static void switch_audio_free(void *data) +{ + switch_audio_t *swa = (switch_audio_t *)data; + + if (swa) + { + unsigned i; + if (!swa->is_paused) + audoutStopAudioOut(); + + audoutExit(); + + for (i = 0; i < 5; i++) + free(swa->buffers[i].buffer); + + free(swa); + } +} + +static bool switch_audio_use_float(void *data) +{ + (void)data; + return false; /* force INT16 */ +} + +static size_t switch_audio_write_avail(void *data) +{ + switch_audio_t *swa = (switch_audio_t *)data; + + if (!swa || !swa->current_buffer) + return 0; + + return swa->current_buffer->buffer_size; +} + +static void switch_audio_set_nonblock_state(void *data, bool state) +{ + switch_audio_t *swa = (switch_audio_t *)data; + + if (swa) + swa->blocking = !state; +} + +static void *switch_audio_init(const char *device, + unsigned rate, unsigned latency, + unsigned block_frames, + unsigned *new_rate) +{ + unsigned i; + switch_audio_t *swa = (switch_audio_t *)calloc(1, sizeof(*swa)); + if (!swa) + return NULL; + + /* Init Audio Output */ + Result rc = audoutInitialize(); + if (R_FAILED(rc)) + { + goto cleanExit; + } + + rc = audoutStartAudioOut(); + if (R_FAILED(rc)) + goto cleanExit; + + /* Create Buffers */ + for (i = 0; i < 5; i++) + { + swa->buffers[i].next = NULL; /* Unused */ + swa->buffers[i].buffer = memalign(0x1000, switch_audio_buffer_size(NULL)); + swa->buffers[i].buffer_size = switch_audio_buffer_size(NULL); + swa->buffers[i].data_size = switch_audio_data_size(); + swa->buffers[i].data_offset = 0; + + memset(swa->buffers[i].buffer, 0, switch_audio_buffer_size(NULL)); + + audoutAppendAudioOutBuffer(&swa->buffers[i]); + } + + /* Set audio rate */ + *new_rate = audoutGetSampleRate(); + + swa->is_paused = false; + swa->current_buffer = NULL; + swa->latency = latency; + swa->last_append = svcGetSystemTick(); + swa->blocking = block_frames; + + RARCH_LOG("[Audio]: Audio initialized\n"); + + return swa; + +cleanExit:; + + if (swa) + free(swa); + + RARCH_LOG("[Audio]: Something failed in Audio Init!\n"); + + return NULL; +} + +audio_driver_t audio_switch = { + switch_audio_init, + switch_audio_write, + switch_audio_stop, + switch_audio_start, + switch_audio_alive, + switch_audio_set_nonblock_state, + switch_audio_free, + switch_audio_use_float, + "switch", + NULL, /* device_list_new */ + NULL, /* device_list_free */ + switch_audio_write_avail, + switch_audio_buffer_size, /* buffer_size */ +}; diff --git a/audio/drivers/switch_nx_thread_audio.c b/audio/drivers/switch_nx_thread_audio.c new file mode 100644 index 0000000000..2b72b318de --- /dev/null +++ b/audio/drivers/switch_nx_thread_audio.c @@ -0,0 +1,355 @@ +/* RetroArch - A frontend for libretro. + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include "../audio_driver.h" +#include "../../verbosity.h" + +#include "../../tasks/tasks_internal.h" + +#define THREAD_STACK_SIZE (1024 * 8) + +#define AUDIO_THREAD_CPU 2 + +#define CHANNELCOUNT 2 +#define BYTESPERSAMPLE sizeof(uint16_t) +#define SAMPLE_SIZE (CHANNELCOUNT * BYTESPERSAMPLE) + +#define AUDIO_BUFFER_COUNT 2 + +static inline void lockMutex(Mutex* mtx) +{ + mutexLock(mtx); +} + +typedef struct +{ + fifo_buffer_t* fifo; + Mutex fifoLock; + CondVar cond; + Mutex condLock; + + size_t fifoSize; + + volatile bool running; + bool nonblocking; + bool is_paused; + + AudioOutBuffer buffer[AUDIO_BUFFER_COUNT]; + Thread thread; + + unsigned latency; + uint32_t sampleRate; +} switch_thread_audio_t; + +static void mainLoop(void* data) +{ + switch_thread_audio_t* swa = (switch_thread_audio_t*)data; + + if (!swa) + return; + + RARCH_LOG("[Audio]: start mainLoop cpu %u tid %u\n", svcGetCurrentProcessorNumber(), swa->thread.handle); + + for (int i = 0; i < AUDIO_BUFFER_COUNT; i++) + { + swa->buffer[i].next = NULL; /* Unused */ + swa->buffer[i].buffer_size = swa->fifoSize; + swa->buffer[i].buffer = memalign(0x1000, swa->buffer[i].buffer_size); + swa->buffer[i].data_size = swa->buffer[i].buffer_size; + swa->buffer[i].data_offset = 0; + + memset(swa->buffer[i].buffer, 0, swa->buffer[i].buffer_size); + audoutAppendAudioOutBuffer(&swa->buffer[i]); + } + + AudioOutBuffer* released_out_buffer = NULL; + u32 released_out_count; + Result rc; + + while (swa->running) + { + if (!released_out_buffer) + { + rc = audoutWaitPlayFinish(&released_out_buffer, &released_out_count, U64_MAX); + if (R_FAILED(rc)) + { + swa->running = false; + RARCH_LOG("[Audio]: audoutGetReleasedAudioOutBuffer failed: %d\n", (int)rc); + break; + } + released_out_buffer->data_size = 0; + } + + size_t bufAvail = released_out_buffer->buffer_size - released_out_buffer->data_size; + + lockMutex(&swa->fifoLock); + + size_t avail = fifo_read_avail(swa->fifo); + size_t to_write = MIN(avail, bufAvail); + if (to_write > 0) + fifo_read(swa->fifo, ((u8*)released_out_buffer->buffer) + released_out_buffer->data_size, to_write); + + mutexUnlock(&swa->fifoLock); + condvarWakeAll(&swa->cond); + + released_out_buffer->data_size += to_write; + if (released_out_buffer->data_size >= released_out_buffer->buffer_size / 2) + { + rc = audoutAppendAudioOutBuffer(released_out_buffer); + if (R_FAILED(rc)) + { + RARCH_LOG("[Audio]: audoutAppendAudioOutBuffer failed: %d\n", (int)rc); + } + released_out_buffer = NULL; + } + else + svcSleepThread(16000000); /* 16ms */ + } +} + +static void *switch_thread_audio_init(const char *device, unsigned rate, unsigned latency, unsigned block_frames, unsigned *new_rate) +{ + (void)device; + + switch_thread_audio_t *swa = (switch_thread_audio_t *)calloc(1, sizeof(switch_thread_audio_t)); + + if (!swa) + return NULL; + + swa->running = true; + swa->nonblocking = true; + swa->is_paused = true; + swa->latency = MAX(latency, 8); + + Result rc = audoutInitialize(); + if (R_FAILED(rc)) + { + RARCH_LOG("[Audio]: audio init failed %d\n", (int)rc); + return NULL; + } + + rc = audoutStartAudioOut(); + if (R_FAILED(rc)) + { + RARCH_LOG("[Audio]: audio start init failed: %d\n", (int)rc); + return NULL; + } + + swa->sampleRate = audoutGetSampleRate(); + *new_rate = swa->sampleRate; + + mutexInit(&swa->fifoLock); + swa->fifoSize = (swa->sampleRate * SAMPLE_SIZE * swa->latency) / 1000; + swa->fifo = fifo_new(swa->fifoSize); + + condvarInit(&swa->cond, &swa->condLock); + + RARCH_LOG("[Audio]: switch_thread_audio_init device %s requested rate %hu rate %hu latency %hu block_frames %hu fifoSize %lu\n", + device, rate, swa->sampleRate, swa->latency, block_frames, swa->fifoSize); + + u32 prio; + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + rc = threadCreate(&swa->thread, &mainLoop, (void*)swa, THREAD_STACK_SIZE, prio + 1, AUDIO_THREAD_CPU); + + if (R_FAILED(rc)) + { + RARCH_LOG("[Audio]: thread creation failed create %u\n", swa->thread.handle); + swa->running = false; + return NULL; + } + + if (R_FAILED(threadStart(&swa->thread))) + { + RARCH_LOG("[Audio]: thread creation failed start %u\n", swa->thread.handle); + threadClose(&swa->thread); + swa->running = false; + return NULL; + } + + return swa; +} + +static bool switch_thread_audio_start(void *data, bool is_shutdown) +{ + /* RARCH_LOG("[Audio]: switch_thread_audio_start\n"); */ + switch_thread_audio_t *swa = (switch_thread_audio_t *)data; + + if (!swa) + return false; + + swa->is_paused = false; + return true; +} + +static bool switch_thread_audio_stop(void *data) +{ + switch_thread_audio_t* swa = (switch_thread_audio_t*)data; + + if (!swa) + return false; + + swa->is_paused = true; + return true; +} + +static void switch_thread_audio_free(void *data) +{ + switch_thread_audio_t *swa = (switch_thread_audio_t *)data; + + if (!swa) + return; + + if (swa->running) + { + swa->running = false; + threadWaitForExit(&swa->thread); + threadClose(&swa->thread); + } + + audoutStopAudioOut(); + audoutExit(); + + if (swa->fifo) + { + fifo_free(swa->fifo); + swa->fifo = NULL; + } + + for (int i = 0; i < AUDIO_BUFFER_COUNT; i++) + free(swa->buffer[i].buffer); + + free(swa); + swa = NULL; +} + +static ssize_t switch_thread_audio_write(void *data, const void *buf, size_t size) +{ + switch_thread_audio_t *swa = (switch_thread_audio_t *)data; + + if (!swa || !swa->running) + return 0; + + size_t avail; + size_t written; + + if (swa->nonblocking) + { + lockMutex(&swa->fifoLock); + avail = fifo_write_avail(swa->fifo); + written = MIN(avail, size); + if (written > 0) + { + fifo_write(swa->fifo, buf, written); + } + mutexUnlock(&swa->fifoLock); + } + else + { + written = 0; + while (written < size && swa->running) + { + lockMutex(&swa->fifoLock); + avail = fifo_write_avail(swa->fifo); + if (avail == 0) + { + mutexUnlock(&swa->fifoLock); + lockMutex(&swa->condLock); + if (swa->running) + condvarWait(&swa->cond); + mutexUnlock(&swa->condLock); + } + else + { + size_t write_amt = MIN(size - written, avail); + fifo_write(swa->fifo, (const char*)buf + written, write_amt); + mutexUnlock(&swa->fifoLock); + written += write_amt; + } + } + } + + return written; +} + +static bool switch_thread_audio_alive(void *data) +{ + switch_thread_audio_t *swa = (switch_thread_audio_t *)data; + + if (!swa) + return false; + + return !swa->is_paused; +} + +static void switch_thread_audio_set_nonblock_state(void *data, bool state) +{ + switch_thread_audio_t *swa = (switch_thread_audio_t *)data; + + if (swa) + swa->nonblocking = state; +} + +static bool switch_thread_audio_use_float(void *data) +{ + (void)data; + return false; +} + +static size_t switch_thread_audio_write_avail(void *data) +{ + switch_thread_audio_t* swa = (switch_thread_audio_t*)data; + + lockMutex(&swa->fifoLock); + size_t val = fifo_write_avail(swa->fifo); + mutexUnlock(&swa->fifoLock); + + return val; +} + +size_t switch_thread_audio_buffer_size(void *data) +{ + switch_thread_audio_t *swa = (switch_thread_audio_t *)data; + + if (!swa) + return 0; + + return swa->fifoSize; +} + +audio_driver_t audio_switch_thread = { + switch_thread_audio_init, + switch_thread_audio_write, + switch_thread_audio_stop, + switch_thread_audio_start, + switch_thread_audio_alive, + switch_thread_audio_set_nonblock_state, + switch_thread_audio_free, + switch_thread_audio_use_float, + "switch_thread", + NULL, /* device_list_new */ + NULL, /* device_list_free */ + switch_thread_audio_write_avail, + switch_thread_audio_buffer_size +}; + +/* vim: set ts=6 sw=6 sts=6: */ From 4d0729187f213c2f197e89f7d45a67c8967b833d Mon Sep 17 00:00:00 2001 From: radius Date: Sun, 9 Sep 2018 16:41:50 -0500 Subject: [PATCH 081/335] [discord] start getting ready for ask-to-join functionality, cleanup some of the mess --- .vscode/settings.json | 2 + command.c | 11 +++++ discord/discord.c | 79 +++++++++++++++++------------- discord/discord.h | 6 ++- menu/menu_driver.c | 15 +++--- network/netplay/netplay_frontend.c | 24 +++++++++ retroarch.c | 10 +++- 7 files changed, 102 insertions(+), 45 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 345f8a0f8e..20d5d022e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,6 +14,8 @@ "*.in": "c", "*.rh": "c", "array": "c", + "file_stream.h": "c", + "driver.h": "c" }, "C_Cpp.dimInactiveRegions": false, } \ No newline at end of file diff --git a/command.c b/command.c index 40f6310c3e..bce0de04c3 100644 --- a/command.c +++ b/command.c @@ -98,6 +98,8 @@ #define DEFAULT_NETWORK_CMD_PORT 55355 #define STDIN_BUF_SIZE 4096 +extern bool discord_is_inited; + enum cmd_source_t { CMD_NONE = 0, @@ -1980,6 +1982,15 @@ bool command_event(enum event_command cmd, void *data) core_unload_game(); if (!rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) core_unload(); +#ifdef HAVE_DISCORD + if (discord_is_inited) + { + discord_userdata_t userdata; + userdata.status = DISCORD_PRESENCE_MENU; + + command_event(CMD_EVENT_DISCORD_UPDATE, &userdata); + } +#endif } break; case CMD_EVENT_QUIT: diff --git a/discord/discord.c b/discord/discord.c index 8e1ba00e70..f58f22a407 100644 --- a/discord/discord.c +++ b/discord/discord.c @@ -25,21 +25,30 @@ #include "../msg_hash.h" -static const char* APPLICATION_ID = "475456035851599874"; +#ifdef HAVE_NETWORKING +#include "../../network/netplay/netplay.h" +#include "../../network/netplay/netplay_discovery.h" +#endif + +#ifdef HAVE_CHEEVOS +#include "../cheevos/cheevos.h" +#endif + +static const char* APPLICATION_ID = "399289711077752833"; static int FrustrationLevel = 0; static int64_t start_time = 0; static int64_t pause_time = 0; +static int64_t ellapsed_time = 0; static bool discord_ready = false; -static bool in_menu = false; static unsigned discord_status = 0; DiscordRichPresence discord_presence; static void handle_discord_ready(const DiscordUser* connectedUser) { - RARCH_LOG("[Discord] connected to user %s#%s - %s\n", + RARCH_LOG("[Discord] connected to user: %s#%s - avatar id: %s\n", connectedUser->username, connectedUser->discriminator, connectedUser->userId); @@ -78,19 +87,17 @@ static void handle_discord_join_request(const DiscordUser* request) void discord_update(enum discord_presence presence) { core_info_t *core_info = NULL; - bool skip = false; core_info_get_current_core(&core_info); if (!discord_ready) return; - if ( - (discord_status != DISCORD_PRESENCE_MENU) && - (discord_status == presence)) + if (presence == discord_status) return; - memset(&discord_presence, 0, sizeof(discord_presence)); + if (presence == DISCORD_PRESENCE_NONE || presence == DISCORD_PRESENCE_MENU) + memset(&discord_presence, 0, sizeof(discord_presence)); switch (presence) { @@ -99,19 +106,15 @@ void discord_update(enum discord_presence presence) discord_presence.largeImageKey = "base"; discord_presence.largeImageText = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_CORE); discord_presence.instance = 0; - - in_menu = true; break; case DISCORD_PRESENCE_GAME_PAUSED: discord_presence.smallImageKey = "paused"; discord_presence.smallImageText = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PAUSED); discord_presence.details = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME_PAUSED); - pause_time = time(0); - skip = true; - - if (in_menu) - break; + ellapsed_time = difftime(time(0), start_time); + discord_presence.startTimestamp = pause_time; + break; case DISCORD_PRESENCE_GAME: if (core_info) { @@ -126,7 +129,7 @@ void discord_update(enum discord_presence presence) if (!label) label = (char *)path_basename(path_get(RARCH_PATH_BASENAME)); -#if 1 +#if 0 RARCH_LOG("[Discord] current core: %s\n", system_id); RARCH_LOG("[Discord] current content: %s\n", label); #endif @@ -135,39 +138,40 @@ void discord_update(enum discord_presence presence) if (core_info->display_name) discord_presence.largeImageText = core_info->display_name; - if (in_menu) - start_time = time(0); - else - start_time = start_time + difftime(time(0), pause_time); + start_time = time(0); + if (pause_time != 0) + start_time = time(0) - ellapsed_time; - if (!skip) - { - discord_presence.smallImageKey = "playing"; - discord_presence.smallImageText = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PLAYING); - discord_presence.startTimestamp = start_time; - discord_presence.details = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME); - } + pause_time = 0; + ellapsed_time = 0; + + discord_presence.smallImageKey = "playing"; + discord_presence.smallImageText = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PLAYING); + discord_presence.startTimestamp = start_time; + discord_presence.details = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME); discord_presence.state = label; discord_presence.instance = 0; } - - in_menu = false; break; case DISCORD_PRESENCE_NETPLAY_HOSTING: + discord_presence.joinSecret = "JOINJOINJOIN"; + discord_presence.spectateSecret = "SPECSPECSPEC"; + discord_presence.partyId = "RADIUS"; + discord_presence.partyMax = 0; + discord_presence.partySize = 0; + break; + case DISCORD_PRESENCE_NETPLAY_HOSTING_STOPPED: case DISCORD_PRESENCE_NETPLAY_CLIENT: - case DISCORD_PRESENCE_CHEEVO_UNLOCKED: - /* TODO/FIXME */ + default: + discord_presence.joinSecret = NULL; break; } - if (in_menu && skip) - return; - RARCH_LOG("[Discord] updating (%d)\n", presence); Discord_UpdatePresence(&discord_presence); - discord_status = presence; + discord_status = presence; } void discord_init(void) @@ -197,3 +201,8 @@ void discord_shutdown(void) Discord_Shutdown(); discord_ready = false; } + +void discord_run_callbacks() +{ + Discord_RunCallbacks(); +} \ No newline at end of file diff --git a/discord/discord.h b/discord/discord.h index 84aa87f8ad..8148482d54 100644 --- a/discord/discord.h +++ b/discord/discord.h @@ -32,11 +32,13 @@ enum discord_presence { - DISCORD_PRESENCE_MENU = 0, + DISCORD_PRESENCE_NONE = 0, + DISCORD_PRESENCE_MENU, DISCORD_PRESENCE_GAME, DISCORD_PRESENCE_GAME_PAUSED, DISCORD_PRESENCE_CHEEVO_UNLOCKED, DISCORD_PRESENCE_NETPLAY_HOSTING, + DISCORD_PRESENCE_NETPLAY_HOSTING_STOPPED, DISCORD_PRESENCE_NETPLAY_CLIENT }; @@ -51,4 +53,6 @@ void discord_shutdown(void); void discord_update(enum discord_presence presence); +void discord_run_callbacks(); + #endif /* __RARCH_DISCORD_H */ diff --git a/menu/menu_driver.c b/menu/menu_driver.c index effc75d61a..346a292ec0 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -467,16 +467,17 @@ bool menu_display_libretro(bool is_idle, return true; } -#ifdef HAVE_DISCORD - discord_userdata_t userdata; - userdata.status = DISCORD_PRESENCE_GAME_PAUSED; - - command_event(CMD_EVENT_DISCORD_UPDATE, &userdata); -#endif - if (is_idle) + { +#ifdef HAVE_DISCORD + discord_userdata_t userdata; + userdata.status = DISCORD_PRESENCE_GAME_PAUSED; + + command_event(CMD_EVENT_DISCORD_UPDATE, &userdata); +#endif return true; /* Maybe return false here for indication of idleness? */ + } return video_driver_cached_frame(); } diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 19775f5f0e..70f7013e5e 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -26,6 +26,10 @@ #include #include +#ifdef HAVE_DISCORD +#include +#endif + #include #include "netplay_discovery.h" @@ -60,6 +64,10 @@ static bool is_mitm = false; static bool netplay_disconnect(netplay_t *netplay); +#ifdef HAVE_DISCORD +extern bool discord_is_inited; +#endif + /** * netplay_is_alive: * @netplay : pointer to netplay object @@ -1490,6 +1498,14 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) case RARCH_NETPLAY_CTL_ENABLE_SERVER: netplay_enabled = true; netplay_is_client = false; +#ifdef HAVE_DISCORD + if (discord_is_inited) + { + discord_userdata_t userdata; + userdata.status = DISCORD_PRESENCE_NETPLAY_HOSTING; + command_event(CMD_EVENT_DISCORD_UPDATE, &userdata); + } +#endif goto done; case RARCH_NETPLAY_CTL_ENABLE_CLIENT: @@ -1499,6 +1515,14 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) case RARCH_NETPLAY_CTL_DISABLE: netplay_enabled = false; +#ifdef HAVE_DISCORD + if (discord_is_inited) + { + discord_userdata_t userdata; + userdata.status = DISCORD_PRESENCE_NETPLAY_HOSTING_STOPPED; + command_event(CMD_EVENT_DISCORD_UPDATE, &userdata); + } +#endif goto done; case RARCH_NETPLAY_CTL_IS_ENABLED: diff --git a/retroarch.c b/retroarch.c index 6b49f0e41c..3573b206ed 100644 --- a/retroarch.c +++ b/retroarch.c @@ -204,7 +204,7 @@ static retro_bits_t has_set_libretro_device; static bool has_set_core = false; static bool has_set_username = false; #ifdef HAVE_DISCORD -static bool discord_is_inited = false; +bool discord_is_inited = false; #endif static bool rarch_is_inited = false; static bool rarch_error_on_init = false; @@ -3357,6 +3357,13 @@ int runloop_iterate(unsigned *sleep_ms) settings_t *settings = config_get_ptr(); unsigned max_users = *(input_driver_get_uint(INPUT_ACTION_MAX_USERS)); + if (discord_is_inited) + { +#ifdef HAVE_DISCORD + discord_run_callbacks(); +#endif + } + if (runloop_frame_time.callback) { /* Updates frame timing if frame timing callback is in use by the core. @@ -3452,7 +3459,6 @@ int runloop_iterate(unsigned *sleep_ms) if (runloop_check_cheevos()) cheevos_test(); #endif - cheat_manager_apply_retro_cheats() ; #ifdef HAVE_DISCORD From fed74b9e707a2b89a103d58ea46a6a4d5550f270 Mon Sep 17 00:00:00 2001 From: radius Date: Tue, 11 Sep 2018 23:26:55 -0500 Subject: [PATCH 082/335] [discord] populate data correctly --- .vscode/settings.json | 5 +++- discord/discord.c | 39 ++++++++++++++++++++++++++++-- network/netplay/netplay_frontend.c | 18 ++++++++------ 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 20d5d022e0..3b105d2389 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,7 +15,10 @@ "*.rh": "c", "array": "c", "file_stream.h": "c", - "driver.h": "c" + "driver.h": "c", + "iosfwd": "c", + "xlocbuf": "c", + "xmemory0": "c" }, "C_Cpp.dimInactiveRegions": false, } \ No newline at end of file diff --git a/discord/discord.c b/discord/discord.c index f58f22a407..bf94062788 100644 --- a/discord/discord.c +++ b/discord/discord.c @@ -28,6 +28,7 @@ #ifdef HAVE_NETWORKING #include "../../network/netplay/netplay.h" #include "../../network/netplay/netplay_discovery.h" +#include "../../tasks/tasks_internal.h" #endif #ifdef HAVE_CHEEVOS @@ -44,6 +45,8 @@ static int64_t ellapsed_time = 0; static bool discord_ready = false; static unsigned discord_status = 0; +struct netplay_room *room; + DiscordRichPresence discord_presence; static void handle_discord_ready(const DiscordUser* connectedUser) @@ -67,6 +70,21 @@ static void handle_discord_error(int errcode, const char* message) static void handle_discord_join(const char* secret) { RARCH_LOG("[Discord] join (%s)\n", secret); + static struct string_list *list = NULL; + list = string_split(secret, "|"); + + char tmp_hostname[32]; + snprintf(tmp_hostname, + sizeof(tmp_hostname), + "%s|%s", list->elems[0].data, list->elems[1].data); + + if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) + deinit_netplay(); + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); + + task_push_netplay_crc_scan(atoi(list->elems[3].data), + list->elems[2].data, + tmp_hostname, list->elems[4].data); } static void handle_discord_spectate(const char* secret) @@ -155,9 +173,26 @@ void discord_update(enum discord_presence presence) } break; case DISCORD_PRESENCE_NETPLAY_HOSTING: - discord_presence.joinSecret = "JOINJOINJOIN"; + room = netplay_get_host_room(); + if (room->id == 0) + return; + + RARCH_LOG("[Discord] netplay room details: id=%d, nick=%s IP=%s port=%d\n", + room->id, room->nickname, + room->host_method == NETPLAY_HOST_METHOD_MITM ? room->mitm_address : room->address, + room->host_method == NETPLAY_HOST_METHOD_MITM ? room->mitm_port : room->port); + + char party_id[128]; + snprintf(party_id, sizeof(party_id), "%d|%s", room->id, room->nickname); + char join_secret[128]; + snprintf(join_secret, sizeof(join_secret), "%s|%d|%s|%u|%s", + room->host_method == NETPLAY_HOST_METHOD_MITM ? room->mitm_address : room->address, + room->host_method == NETPLAY_HOST_METHOD_MITM ? room->mitm_port : room->port, + room->gamename, room->gamecrc, room->corename); + RARCH_LOG("%s\n", join_secret); + discord_presence.joinSecret = strdup(join_secret); discord_presence.spectateSecret = "SPECSPECSPEC"; - discord_presence.partyId = "RADIUS"; + discord_presence.partyId = party_id; discord_presence.partyMax = 0; discord_presence.partySize = 0; break; diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 70f7013e5e..c0981d7067 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -640,6 +640,15 @@ static void netplay_announce_cb(void *task_data, void *user_data, const char *er { RARCH_LOG("[netplay] announcing netplay game... \n"); +#ifdef HAVE_DISCORD + if (discord_is_inited) + { + discord_userdata_t userdata; + userdata.status = DISCORD_PRESENCE_NETPLAY_HOSTING; + command_event(CMD_EVENT_DISCORD_UPDATE, &userdata); + } +#endif + if (task_data) { unsigned i, ip_len, port_len; @@ -1498,14 +1507,6 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) case RARCH_NETPLAY_CTL_ENABLE_SERVER: netplay_enabled = true; netplay_is_client = false; -#ifdef HAVE_DISCORD - if (discord_is_inited) - { - discord_userdata_t userdata; - userdata.status = DISCORD_PRESENCE_NETPLAY_HOSTING; - command_event(CMD_EVENT_DISCORD_UPDATE, &userdata); - } -#endif goto done; case RARCH_NETPLAY_CTL_ENABLE_CLIENT: @@ -1541,6 +1542,7 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) case RARCH_NETPLAY_CTL_IS_CONNECTED: ret = false; goto done; + default: goto done; } From 677cb309822da43c6967e0fd14c062d6156275d7 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 18:29:25 +0200 Subject: [PATCH 083/335] (NSW) Start unifying both libtransistor and libnx switch audio drivers --- audio/drivers/switch_audio.c | 68 +++++++++----------- audio/drivers/switch_nx_audio.c | 109 +++++++++++++------------------- 2 files changed, 75 insertions(+), 102 deletions(-) diff --git a/audio/drivers/switch_audio.c b/audio/drivers/switch_audio.c index 322750bba0..5843a13329 100644 --- a/audio/drivers/switch_audio.c +++ b/audio/drivers/switch_audio.c @@ -23,6 +23,10 @@ #include "../audio_driver.h" #include "../../verbosity.h" +#ifndef RESULT_OK +#define RESULT_OK 0 +#endif + static const int sample_rate = 48000; static const int max_num_samples = sample_rate; static const int num_channels = 2; @@ -46,23 +50,19 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) size_t to_write = size; switch_audio_t *swa = (switch_audio_t*) data; -#if 0 - RARCH_LOG("write %ld samples\n", size/sizeof(uint16_t)); -#endif + if (!swa) + return -1; if (!swa->current_buffer) { uint32_t num; - if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != RESULT_OK) + if (audio_ipc_output_get_released_buffer( + &swa->output, &num, &swa->current_buffer) != RESULT_OK) { RARCH_LOG("Failed to get released buffer?\n"); return -1; } -#if 0 - RARCH_LOG("got buffer, num %d, ptr %p\n", num, swa->current_buffer); -#endif - if (num < 1) swa->current_buffer = NULL; @@ -74,8 +74,8 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) while(swa->current_buffer == NULL) { - uint32_t num; - uint32_t handle_idx; + uint32_t handle_idx = 0; + num = 0; svcWaitSynchronization(&handle_idx, &swa->event, 1, 33333333); svcResetSignal(swa->event); @@ -83,10 +83,10 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != RESULT_OK) return -1; } - } else { + } + else /* no buffer, nonblocking... */ return 0; - } } swa->current_buffer->data_size = 0; @@ -101,20 +101,12 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) if (swa->current_buffer->data_size > (48000*swa->latency)/1000) { - result_t r = audio_ipc_output_append_buffer(&swa->output, swa->current_buffer); - if (r != RESULT_OK) - { - RARCH_ERR("failed to append buffer: 0x%x\n", r); + if (audio_ipc_output_append_buffer(&swa->output, swa->current_buffer) + != RESULT_OK) return -1; - } swa->current_buffer = NULL; } -#if 0 - RARCH_LOG("submitted %ld samples, %ld samples since last submit\n", - to_write/num_channels/sizeof(uint16_t), - (svcGetSystemTick() - swa->last_append) * sample_rate / 19200000); -#endif swa->last_append = svcGetSystemTick(); return to_write; @@ -126,10 +118,9 @@ static bool switch_audio_stop(void *data) if (!swa) return false; - if(!swa->is_paused) { + if(!swa->is_paused) if(audio_ipc_output_stop(&swa->output) != RESULT_OK) return false; - } swa->is_paused = true; return true; @@ -139,10 +130,9 @@ static bool switch_audio_start(void *data, bool is_shutdown) { switch_audio_t *swa = (switch_audio_t*) data; - if(swa->is_paused) { + if(swa->is_paused) if (audio_ipc_output_start(&swa->output) != RESULT_OK) return false; - } swa->is_paused = false; return true; @@ -160,6 +150,9 @@ static void switch_audio_free(void *data) { switch_audio_t *swa = (switch_audio_t*) data; + if (!swa) + return; + audio_ipc_output_close(&swa->output); audio_ipc_finalize(); free(swa); @@ -190,11 +183,10 @@ static void switch_audio_set_nonblock_state(void *data, bool state) } static void *switch_audio_init(const char *device, - unsigned rate, unsigned latency, - unsigned block_frames, - unsigned *new_rate) + unsigned rate, unsigned latency, + unsigned block_frames, + unsigned *new_rate) { - result_t r; unsigned i; char names[8][0x20]; uint32_t num_names = 0; @@ -203,9 +195,7 @@ static void *switch_audio_init(const char *device, if (!swa) return NULL; - r = audio_ipc_init(); - - if (r != RESULT_OK) + if (audio_ipc_init() != RESULT_OK) goto fail; if (audio_ipc_list_outputs(&names[0], 8, &num_names) != RESULT_OK) @@ -243,10 +233,6 @@ static void *switch_audio_init(const char *device, if (audio_ipc_output_register_buffer_event(&swa->output, &swa->event) != RESULT_OK) goto fail_audio_output; - swa->blocking = block_frames; - - *new_rate = swa->output.sample_rate; - for(i = 0; i < 3; i++) { swa->buffers[i].ptr = &swa->buffers[i].sample_data; @@ -262,11 +248,16 @@ static void *switch_audio_init(const char *device, goto fail_audio_output; } + *new_rate = swa->output.sample_rate; + swa->current_buffer = NULL; swa->latency = latency; swa->last_append = svcGetSystemTick(); + swa->blocking = block_frames; swa->is_paused = true; + + RARCH_LOG("[Audio]: Audio initialized\n"); return swa; @@ -275,7 +266,8 @@ fail_audio_output: fail_audio_ipc: audio_ipc_finalize(); fail: - free(swa); + if (swa) + free(swa); return NULL; } diff --git a/audio/drivers/switch_nx_audio.c b/audio/drivers/switch_nx_audio.c index 9a31eb9211..3b163c5b7a 100644 --- a/audio/drivers/switch_nx_audio.c +++ b/audio/drivers/switch_nx_audio.c @@ -24,6 +24,10 @@ #include "../../tasks/tasks_internal.h" +#ifndef RESULT_OK +#define RESULT_OK 0 +#endif + typedef struct { bool blocking; @@ -34,21 +38,14 @@ typedef struct AudioOutBuffer *current_buffer; } switch_audio_t; -static bool switch_tasks_finder(retro_task_t *task, void *userdata) -{ - return task; -} -task_finder_data_t switch_tasks_finder_data = {switch_tasks_finder, NULL}; - -#define SAMPLERATE 48000 -#define CHANNELCOUNT 2 +static const int sample_rate = 48000; +static const int num_channels = 2; #define FRAMERATE (1000 / 30) -#define SAMPLECOUNT SAMPLERATE / FRAMERATE -#define BYTESPERSAMPLE sizeof(uint16_t) +#define SAMPLECOUNT (sample_rate / FRAMERATE) static uint32_t switch_audio_data_size(void) { - return (SAMPLECOUNT * CHANNELCOUNT * BYTESPERSAMPLE); + return (SAMPLECOUNT * num_channels * sizeof(uint16_t)); } static size_t switch_audio_buffer_size(void *data) @@ -59,41 +56,40 @@ static size_t switch_audio_buffer_size(void *data) static ssize_t switch_audio_write(void *data, const void *buf, size_t size) { - size_t to_write = size; + size_t to_write = size; switch_audio_t *swa = (switch_audio_t *)data; if (!swa) - { return -1; - } if (!swa->current_buffer) { uint32_t num; - if (R_FAILED(audoutGetReleasedAudioOutBuffer(&swa->current_buffer, &num))) + if (audoutGetReleasedAudioOutBuffer( + &swa->current_buffer, &num) != RESULT_OK) + { + RARCH_LOG("Failed to get released buffer?\n"); return -1; + } if (num < 1) - { swa->current_buffer = NULL; + if (!swa->current_buffer) + { if (swa->blocking) { - /* No buffer, blocking... */ + RARCH_LOG("No buffer, blocking...\n"); while (swa->current_buffer == NULL) { num = 0; - if (R_FAILED(audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX))) + if (audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX) != RESULT_OK) { -#if 0 - if (task_queue_find(&switch_tasks_finder_data)) - task_queue_check(); -#endif } } } - else + else /* no buffer, nonblocking */ return 0; } @@ -104,13 +100,12 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) to_write = switch_audio_buffer_size(NULL) - swa->current_buffer->data_size; memcpy(((uint8_t *)swa->current_buffer->buffer) + swa->current_buffer->data_size, buf, to_write); - swa->current_buffer->data_size += to_write; - swa->current_buffer->buffer_size = switch_audio_buffer_size(NULL); + swa->current_buffer->data_size += to_write; + swa->current_buffer->buffer_size = switch_audio_buffer_size(NULL); if (swa->current_buffer->data_size > (48000 * swa->latency) / 1000) { - Result r = audoutAppendAudioOutBuffer(swa->current_buffer); - if (R_FAILED(r)) + if (audoutAppendAudioOutBuffer(swa->current_buffer) != RESULT_OK) return -1; swa->current_buffer = NULL; } @@ -129,11 +124,8 @@ static bool switch_audio_stop(void *data) return false; if (!swa->is_paused) - { - Result rc = audoutStopAudioOut(); - if (R_FAILED(rc)) + if (audoutStopAudioOut() != RESULT_OK) return false; - } swa->is_paused = true; return true; @@ -148,11 +140,8 @@ static bool switch_audio_start(void *data, bool is_shutdown) return false; if (swa->is_paused) - { - Result rc = audoutStartAudioOut(); - if (R_FAILED(rc)) + if (audoutStartAudioOut() != RESULT_OK) return false; - } swa->is_paused = false; return true; @@ -168,21 +157,21 @@ static bool switch_audio_alive(void *data) static void switch_audio_free(void *data) { + unsigned i; switch_audio_t *swa = (switch_audio_t *)data; - if (swa) - { - unsigned i; - if (!swa->is_paused) - audoutStopAudioOut(); + if (!swa) + return; - audoutExit(); + if (!swa->is_paused) + audoutStopAudioOut(); - for (i = 0; i < 5; i++) - free(swa->buffers[i].buffer); + audoutExit(); - free(swa); - } + for (i = 0; i < 5; i++) + free(swa->buffers[i].buffer); + + free(swa); } static bool switch_audio_use_float(void *data) @@ -210,25 +199,21 @@ static void switch_audio_set_nonblock_state(void *data, bool state) } static void *switch_audio_init(const char *device, - unsigned rate, unsigned latency, - unsigned block_frames, - unsigned *new_rate) + unsigned rate, unsigned latency, + unsigned block_frames, + unsigned *new_rate) { unsigned i; switch_audio_t *swa = (switch_audio_t *)calloc(1, sizeof(*swa)); + if (!swa) return NULL; - /* Init Audio Output */ - Result rc = audoutInitialize(); - if (R_FAILED(rc)) - { - goto cleanExit; - } + if (audoutInitialize() != RESULT_OK) + goto fail; - rc = audoutStartAudioOut(); - if (R_FAILED(rc)) - goto cleanExit; + if (audoutStartAudioOut() != RESULT_OK) + goto fail; /* Create Buffers */ for (i = 0; i < 5; i++) @@ -244,26 +229,22 @@ static void *switch_audio_init(const char *device, audoutAppendAudioOutBuffer(&swa->buffers[i]); } - /* Set audio rate */ *new_rate = audoutGetSampleRate(); - swa->is_paused = false; swa->current_buffer = NULL; swa->latency = latency; swa->last_append = svcGetSystemTick(); + swa->blocking = block_frames; + swa->is_paused = false; RARCH_LOG("[Audio]: Audio initialized\n"); return swa; -cleanExit:; - +fail: if (swa) free(swa); - - RARCH_LOG("[Audio]: Something failed in Audio Init!\n"); - return NULL; } From 213a56c59fd8ba9e5b2c07d6dadd4c7f0696807a Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 18:58:12 +0200 Subject: [PATCH 084/335] Get rid of RESULT_OK usage --- audio/drivers/switch_audio.c | 24 ++++++++++-------------- audio/drivers/switch_nx_audio.c | 18 +++++++----------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/audio/drivers/switch_audio.c b/audio/drivers/switch_audio.c index 5843a13329..7a1fc6f13b 100644 --- a/audio/drivers/switch_audio.c +++ b/audio/drivers/switch_audio.c @@ -23,10 +23,6 @@ #include "../audio_driver.h" #include "../../verbosity.h" -#ifndef RESULT_OK -#define RESULT_OK 0 -#endif - static const int sample_rate = 48000; static const int max_num_samples = sample_rate; static const int num_channels = 2; @@ -57,7 +53,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) { uint32_t num; if (audio_ipc_output_get_released_buffer( - &swa->output, &num, &swa->current_buffer) != RESULT_OK) + &swa->output, &num, &swa->current_buffer) != 0) { RARCH_LOG("Failed to get released buffer?\n"); return -1; @@ -80,7 +76,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) svcWaitSynchronization(&handle_idx, &swa->event, 1, 33333333); svcResetSignal(swa->event); - if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != RESULT_OK) + if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != 0) return -1; } } @@ -102,7 +98,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) if (swa->current_buffer->data_size > (48000*swa->latency)/1000) { if (audio_ipc_output_append_buffer(&swa->output, swa->current_buffer) - != RESULT_OK) + != 0) return -1; swa->current_buffer = NULL; } @@ -119,7 +115,7 @@ static bool switch_audio_stop(void *data) return false; if(!swa->is_paused) - if(audio_ipc_output_stop(&swa->output) != RESULT_OK) + if(audio_ipc_output_stop(&swa->output) != 0) return false; swa->is_paused = true; @@ -131,7 +127,7 @@ static bool switch_audio_start(void *data, bool is_shutdown) switch_audio_t *swa = (switch_audio_t*) data; if(swa->is_paused) - if (audio_ipc_output_start(&swa->output) != RESULT_OK) + if (audio_ipc_output_start(&swa->output) != 0) return false; swa->is_paused = false; @@ -195,10 +191,10 @@ static void *switch_audio_init(const char *device, if (!swa) return NULL; - if (audio_ipc_init() != RESULT_OK) + if (audio_ipc_init() != 0) goto fail; - if (audio_ipc_list_outputs(&names[0], 8, &num_names) != RESULT_OK) + if (audio_ipc_list_outputs(&names[0], 8, &num_names) != 0) goto fail_audio_ipc; if (num_names != 1) @@ -207,7 +203,7 @@ static void *switch_audio_init(const char *device, goto fail_audio_ipc; } - if (audio_ipc_open_output(names[0], &swa->output) != RESULT_OK) + if (audio_ipc_open_output(names[0], &swa->output) != 0) goto fail_audio_ipc; if (swa->output.sample_rate != sample_rate) @@ -230,7 +226,7 @@ static void *switch_audio_init(const char *device, goto fail_audio_output; } - if (audio_ipc_output_register_buffer_event(&swa->output, &swa->event) != RESULT_OK) + if (audio_ipc_output_register_buffer_event(&swa->output, &swa->event) != 0) goto fail_audio_output; for(i = 0; i < 3; i++) @@ -244,7 +240,7 @@ static void *switch_audio_init(const char *device, if(swa->buffers[i].sample_data == NULL) goto fail_audio_output; - if (audio_ipc_output_append_buffer(&swa->output, &swa->buffers[i]) != RESULT_OK) + if (audio_ipc_output_append_buffer(&swa->output, &swa->buffers[i]) != 0) goto fail_audio_output; } diff --git a/audio/drivers/switch_nx_audio.c b/audio/drivers/switch_nx_audio.c index 3b163c5b7a..9903075f8b 100644 --- a/audio/drivers/switch_nx_audio.c +++ b/audio/drivers/switch_nx_audio.c @@ -24,10 +24,6 @@ #include "../../tasks/tasks_internal.h" -#ifndef RESULT_OK -#define RESULT_OK 0 -#endif - typedef struct { bool blocking; @@ -66,7 +62,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) { uint32_t num; if (audoutGetReleasedAudioOutBuffer( - &swa->current_buffer, &num) != RESULT_OK) + &swa->current_buffer, &num) != 0) { RARCH_LOG("Failed to get released buffer?\n"); return -1; @@ -84,7 +80,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) while (swa->current_buffer == NULL) { num = 0; - if (audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX) != RESULT_OK) + if (audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX) != 0) { } } @@ -105,7 +101,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) if (swa->current_buffer->data_size > (48000 * swa->latency) / 1000) { - if (audoutAppendAudioOutBuffer(swa->current_buffer) != RESULT_OK) + if (audoutAppendAudioOutBuffer(swa->current_buffer) != 0) return -1; swa->current_buffer = NULL; } @@ -124,7 +120,7 @@ static bool switch_audio_stop(void *data) return false; if (!swa->is_paused) - if (audoutStopAudioOut() != RESULT_OK) + if (audoutStopAudioOut() != 0) return false; swa->is_paused = true; @@ -140,7 +136,7 @@ static bool switch_audio_start(void *data, bool is_shutdown) return false; if (swa->is_paused) - if (audoutStartAudioOut() != RESULT_OK) + if (audoutStartAudioOut() != 0) return false; swa->is_paused = false; @@ -209,10 +205,10 @@ static void *switch_audio_init(const char *device, if (!swa) return NULL; - if (audoutInitialize() != RESULT_OK) + if (audoutInitialize() != 0) goto fail; - if (audoutStartAudioOut() != RESULT_OK) + if (audoutStartAudioOut() != 0) goto fail; /* Create Buffers */ From 6139f8846ac1a00ec0037c667aef73d7fb57008a Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 19:37:38 +0200 Subject: [PATCH 085/335] (NSW) We now have only one non-threaded audio driver for both SDKs instead of two --- audio/drivers/switch_audio.c | 152 +++++++++++++++---- audio/drivers/switch_nx_audio.c | 261 -------------------------------- 2 files changed, 121 insertions(+), 292 deletions(-) delete mode 100644 audio/drivers/switch_nx_audio.c diff --git a/audio/drivers/switch_audio.c b/audio/drivers/switch_audio.c index 7a1fc6f13b..9f0a7e489a 100644 --- a/audio/drivers/switch_audio.c +++ b/audio/drivers/switch_audio.c @@ -1,4 +1,6 @@ /* RetroArch - A frontend for libretro. + * Copyright (C) 2018 - misson2000 + * Copyright (C) 2018 - m4xw * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -17,12 +19,36 @@ #include #include -#include -#include +#ifdef HAVE_LIBNX +#include +#else +#include +#include +#endif #include "../audio_driver.h" #include "../../verbosity.h" +#ifdef HAVE_LIBNX +#define BUFFER_COUNT 5 +#else +#define BUFFER_COUNT 3 +#endif + +#ifdef HAVE_LIBNX +#define switch_audio_ipc_init audoutInitialize +#define switch_audio_ipc_output_get_released_buffer(a, b) audoutGetReleasedAudioOutBuffer(&a->current_buffer, &b) +#define switch_audio_ipc_output_append_buffer(a, b) audoutAppendAudioOutBuffer(b) +#define switch_audio_ipc_output_stop(a) audoutStopAudioOut() +#define switch_audio_ipc_output_start(a) audoutStartAudioOut() +#else +#define switch_audio_ipc_init audio_ipc_init +#define switch_audio_ipc_output_get_released_buffer(a, b) audio_ipc_output_get_released_buffer(&a->output, &b, &a->current_buffer) +#define switch_audio_ipc_output_append_buffer(a, b) audio_ipc_output_append_buffer(&a->output, &b) +#define switch_audio_ipc_output_stop(a) audio_ipc_output_stop(&a->output) +#define switch_audio_ipc_output_start(a) audio_ipc_output_start(&a->output) +#endif + static const int sample_rate = 48000; static const int max_num_samples = sample_rate; static const int num_channels = 2; @@ -34,13 +60,34 @@ typedef struct bool is_paused; uint64_t last_append; unsigned latency; - audio_output_buffer_t buffers[3]; + audio_output_buffer_t buffers[BUFFER_COUNT]; audio_output_buffer_t *current_buffer; audio_output_t output; handle_t event; } switch_audio_t; +static uint32_t switch_audio_data_size(void) +{ +#ifdef HAVE_LIBNX + static const int framerate = 1000 / 30; + static const int samplecount = (sample_rate / framerate); + return (samplecount * num_channels * sizeof(uint16_t)); +#else + return sample_buffer_size; +#endif +} + +static size_t switch_audio_buffer_size(void *data) +{ + (void) data; +#ifdef HAVE_LIBNX + return (switch_audio_data_size() + 0xfff) & ~0xfff; +#else + return sample_buffer_size; +#endif +} + static ssize_t switch_audio_write(void *data, const void *buf, size_t size) { size_t to_write = size; @@ -52,8 +99,7 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) if (!swa->current_buffer) { uint32_t num; - if (audio_ipc_output_get_released_buffer( - &swa->output, &num, &swa->current_buffer) != 0) + if (switch_audio_ipc_output_get_released_buffer(swa, num) != 0) { RARCH_LOG("Failed to get released buffer?\n"); return -1; @@ -73,11 +119,15 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) uint32_t handle_idx = 0; num = 0; +#ifdef HAVE_LIBNX + if (audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX) != 0) { } +#else svcWaitSynchronization(&handle_idx, &swa->event, 1, 33333333); svcResetSignal(swa->event); - if (audio_ipc_output_get_released_buffer(&swa->output, &num, &swa->current_buffer) != 0) + if (switch_audio_ipc_output_get_released_buffer(swa, num) != 0) return -1; +#endif } } else @@ -88,16 +138,16 @@ static ssize_t switch_audio_write(void *data, const void *buf, size_t size) swa->current_buffer->data_size = 0; } - if (to_write > sample_buffer_size - swa->current_buffer->data_size) - to_write = sample_buffer_size - swa->current_buffer->data_size; + if (to_write > switch_audio_buffer_size(NULL) - swa->current_buffer->data_size) + to_write = switch_audio_buffer_size(NULL) - swa->current_buffer->data_size; memcpy(((uint8_t*) swa->current_buffer->sample_data) + swa->current_buffer->data_size, buf, to_write); swa->current_buffer->data_size += to_write; - swa->current_buffer->buffer_size = sample_buffer_size; + swa->current_buffer->buffer_size = switch_audio_buffer_size(NULL); - if (swa->current_buffer->data_size > (48000*swa->latency)/1000) + if (swa->current_buffer->data_size > (48000 * swa->latency) / 1000) { - if (audio_ipc_output_append_buffer(&swa->output, swa->current_buffer) + if (switch_audio_ipc_output_append_buffer(swa, swa->current_buffer) != 0) return -1; swa->current_buffer = NULL; @@ -114,23 +164,32 @@ static bool switch_audio_stop(void *data) if (!swa) return false; - if(!swa->is_paused) - if(audio_ipc_output_stop(&swa->output) != 0) + /* TODO/FIXME - fix libnx codepath */ +#ifndef HAVE_LIBNX + + if (!swa->is_paused) + if (switch_audio_ipc_output_stop(swa) != 0) return false; swa->is_paused = true; +#endif return true; } static bool switch_audio_start(void *data, bool is_shutdown) { switch_audio_t *swa = (switch_audio_t*) data; + if (!swa) + return false; - if(swa->is_paused) - if (audio_ipc_output_start(&swa->output) != 0) + /* TODO/FIXME - fix libnx codepath */ +#ifndef HAVE_LIBNX + if (swa->is_paused) + if (switch_audio_ipc_output_start(swa) != 0) return false; swa->is_paused = false; +#endif return true; } @@ -149,8 +208,18 @@ static void switch_audio_free(void *data) if (!swa) return; +#ifdef HAVE_LIBNX + if (!swa->is_paused) + audoutStopAudioOut(); + + audoutExit(); + + for (i = 0; i < BUFFER_COUNT; i++) + free(swa->buffers[i].buffer); +#else audio_ipc_output_close(&swa->output); audio_ipc_finalize(); +#endif free(swa); } @@ -191,9 +260,13 @@ static void *switch_audio_init(const char *device, if (!swa) return NULL; - if (audio_ipc_init() != 0) + if (switch_audio_ipc_init() != 0) goto fail; +#ifdef HAVE_LIBNX + if (audoutStartAudioOut() != 0) + goto fail; +#else if (audio_ipc_list_outputs(&names[0], 8, &num_names) != 0) goto fail_audio_ipc; @@ -228,23 +301,40 @@ static void *switch_audio_init(const char *device, if (audio_ipc_output_register_buffer_event(&swa->output, &swa->event) != 0) goto fail_audio_output; +#endif - for(i = 0; i < 3; i++) + for (i = 0; i < BUFFER_COUNT; i++) { - swa->buffers[i].ptr = &swa->buffers[i].sample_data; - swa->buffers[i].sample_data = alloc_pages(sample_buffer_size, sample_buffer_size, NULL); - swa->buffers[i].buffer_size = sample_buffer_size; - swa->buffers[i].data_size = sample_buffer_size; - swa->buffers[i].unknown = 0; + swa->buffers[i].buffer_size = switch_audio_buffer_size(NULL); + swa->buffers[i].data_size = switch_audio_data_size(); - if(swa->buffers[i].sample_data == NULL) +#ifdef HAVE_LIBNX + swa->buffers[i].next = NULL; /* Unused */ + swa->buffers[i].data_offset = 0; + swa->buffers[i].buffer = memalign(0x1000, switch_audio_buffer_size(NULL)); + + if (swa->buffers[i].buffer == NULL) + goto fail_audio_output; + + memset(swa->buffers[i].buffer, 0, switch_audio_buffer_size(NULL)); +#else + swa->buffers[i].ptr = &swa->buffers[i].sample_data; + swa->buffers[i].unknown = 0; + swa->buffers[i].sample_data = alloc_pages(sample_buffer_size, switch_audio_buffer_size(NULL), NULL); + + if (swa->buffers[i].sample_data == NULL) goto fail_audio_output; - - if (audio_ipc_output_append_buffer(&swa->output, &swa->buffers[i]) != 0) +#endif + + if (switch_audio_ipc_output_append_buffer(swa, swa->buffers[i]) != 0) goto fail_audio_output; } +#ifdef HAVE_LIBNX + *new_rate = audoutGetSampleRate(); +#else *new_rate = swa->output.sample_rate; +#endif swa->current_buffer = NULL; swa->latency = latency; @@ -258,21 +348,21 @@ static void *switch_audio_init(const char *device, return swa; fail_audio_output: +/* TODO/FIXME - fix libnx codepath */ +#ifndef HAVE_LIBNX audio_ipc_output_close(&swa->output); +#endif fail_audio_ipc: +/* TODO/FIXME - fix libnx codepath */ +#ifndef HAVE_LIBNX audio_ipc_finalize(); +#endif fail: if (swa) free(swa); return NULL; } -static size_t switch_audio_buffer_size(void *data) -{ - (void) data; - return sample_buffer_size; -} - audio_driver_t audio_switch = { switch_audio_init, switch_audio_write, diff --git a/audio/drivers/switch_nx_audio.c b/audio/drivers/switch_nx_audio.c deleted file mode 100644 index 9903075f8b..0000000000 --- a/audio/drivers/switch_nx_audio.c +++ /dev/null @@ -1,261 +0,0 @@ -/* RetroArch - A frontend for libretro. - * - * RetroArch is free software: you can redistribute it and/or modify it under the terms - * of the GNU General Public License as published by the Free Software Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with RetroArch. - * If not, see . - */ - -#include -#include -#include -#include - -#include - -#include "../audio_driver.h" -#include "../../verbosity.h" - -#include "../../tasks/tasks_internal.h" - -typedef struct -{ - bool blocking; - bool is_paused; - uint64_t last_append; - unsigned latency; - AudioOutBuffer buffers[5]; - AudioOutBuffer *current_buffer; -} switch_audio_t; - -static const int sample_rate = 48000; -static const int num_channels = 2; -#define FRAMERATE (1000 / 30) -#define SAMPLECOUNT (sample_rate / FRAMERATE) - -static uint32_t switch_audio_data_size(void) -{ - return (SAMPLECOUNT * num_channels * sizeof(uint16_t)); -} - -static size_t switch_audio_buffer_size(void *data) -{ - (void)data; - return (switch_audio_data_size() + 0xfff) & ~0xfff; -} - -static ssize_t switch_audio_write(void *data, const void *buf, size_t size) -{ - size_t to_write = size; - switch_audio_t *swa = (switch_audio_t *)data; - - if (!swa) - return -1; - - if (!swa->current_buffer) - { - uint32_t num; - if (audoutGetReleasedAudioOutBuffer( - &swa->current_buffer, &num) != 0) - { - RARCH_LOG("Failed to get released buffer?\n"); - return -1; - } - - if (num < 1) - swa->current_buffer = NULL; - - if (!swa->current_buffer) - { - if (swa->blocking) - { - RARCH_LOG("No buffer, blocking...\n"); - - while (swa->current_buffer == NULL) - { - num = 0; - if (audoutWaitPlayFinish(&swa->current_buffer, &num, U64_MAX) != 0) - { - } - } - } - else /* no buffer, nonblocking */ - return 0; - } - - swa->current_buffer->data_size = 0; - } - - if (to_write > switch_audio_buffer_size(NULL) - swa->current_buffer->data_size) - to_write = switch_audio_buffer_size(NULL) - swa->current_buffer->data_size; - - memcpy(((uint8_t *)swa->current_buffer->buffer) + swa->current_buffer->data_size, buf, to_write); - swa->current_buffer->data_size += to_write; - swa->current_buffer->buffer_size = switch_audio_buffer_size(NULL); - - if (swa->current_buffer->data_size > (48000 * swa->latency) / 1000) - { - if (audoutAppendAudioOutBuffer(swa->current_buffer) != 0) - return -1; - swa->current_buffer = NULL; - } - - swa->last_append = svcGetSystemTick(); - - return to_write; -} - -static bool switch_audio_stop(void *data) -{ - return true; - - switch_audio_t *swa = (switch_audio_t *)data; - if (!swa) - return false; - - if (!swa->is_paused) - if (audoutStopAudioOut() != 0) - return false; - - swa->is_paused = true; - return true; -} - -static bool switch_audio_start(void *data, bool is_shutdown) -{ - return true; - - switch_audio_t *swa = (switch_audio_t *)data; - if (!swa) - return false; - - if (swa->is_paused) - if (audoutStartAudioOut() != 0) - return false; - - swa->is_paused = false; - return true; -} - -static bool switch_audio_alive(void *data) -{ - switch_audio_t *swa = (switch_audio_t *)data; - if (!swa) - return false; - return !swa->is_paused; -} - -static void switch_audio_free(void *data) -{ - unsigned i; - switch_audio_t *swa = (switch_audio_t *)data; - - if (!swa) - return; - - if (!swa->is_paused) - audoutStopAudioOut(); - - audoutExit(); - - for (i = 0; i < 5; i++) - free(swa->buffers[i].buffer); - - free(swa); -} - -static bool switch_audio_use_float(void *data) -{ - (void)data; - return false; /* force INT16 */ -} - -static size_t switch_audio_write_avail(void *data) -{ - switch_audio_t *swa = (switch_audio_t *)data; - - if (!swa || !swa->current_buffer) - return 0; - - return swa->current_buffer->buffer_size; -} - -static void switch_audio_set_nonblock_state(void *data, bool state) -{ - switch_audio_t *swa = (switch_audio_t *)data; - - if (swa) - swa->blocking = !state; -} - -static void *switch_audio_init(const char *device, - unsigned rate, unsigned latency, - unsigned block_frames, - unsigned *new_rate) -{ - unsigned i; - switch_audio_t *swa = (switch_audio_t *)calloc(1, sizeof(*swa)); - - if (!swa) - return NULL; - - if (audoutInitialize() != 0) - goto fail; - - if (audoutStartAudioOut() != 0) - goto fail; - - /* Create Buffers */ - for (i = 0; i < 5; i++) - { - swa->buffers[i].next = NULL; /* Unused */ - swa->buffers[i].buffer = memalign(0x1000, switch_audio_buffer_size(NULL)); - swa->buffers[i].buffer_size = switch_audio_buffer_size(NULL); - swa->buffers[i].data_size = switch_audio_data_size(); - swa->buffers[i].data_offset = 0; - - memset(swa->buffers[i].buffer, 0, switch_audio_buffer_size(NULL)); - - audoutAppendAudioOutBuffer(&swa->buffers[i]); - } - - *new_rate = audoutGetSampleRate(); - - swa->current_buffer = NULL; - swa->latency = latency; - swa->last_append = svcGetSystemTick(); - - swa->blocking = block_frames; - swa->is_paused = false; - - RARCH_LOG("[Audio]: Audio initialized\n"); - - return swa; - -fail: - if (swa) - free(swa); - return NULL; -} - -audio_driver_t audio_switch = { - switch_audio_init, - switch_audio_write, - switch_audio_stop, - switch_audio_start, - switch_audio_alive, - switch_audio_set_nonblock_state, - switch_audio_free, - switch_audio_use_float, - "switch", - NULL, /* device_list_new */ - NULL, /* device_list_free */ - switch_audio_write_avail, - switch_audio_buffer_size, /* buffer_size */ -}; From 517b1b9089dcb0ea9cc79d84892ac8e953eb79ad Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 19:54:51 +0200 Subject: [PATCH 086/335] Add HAVE_LIBNX ifdefs to switch_input.c/switch_joypad.c, and features_cpu.c --- input/drivers/switch_input.c | 4 ++ input/drivers_joypad/switch_joypad.c | 93 ++++++++++++++++++++++--- input/input_autodetect_builtin.c | 2 +- libretro-common/features/features_cpu.c | 8 ++- 4 files changed, 94 insertions(+), 13 deletions(-) diff --git a/input/drivers/switch_input.c b/input/drivers/switch_input.c index d363e22e74..067e355a2f 100644 --- a/input/drivers/switch_input.c +++ b/input/drivers/switch_input.c @@ -9,6 +9,10 @@ #include "../../config.h" #endif +#ifdef HAVE_LIBNX +#include +#endif + #include "../input_driver.h" #define MAX_PADS 10 diff --git a/input/drivers_joypad/switch_joypad.c b/input/drivers_joypad/switch_joypad.c index 03930a3458..1f67283ccc 100644 --- a/input/drivers_joypad/switch_joypad.c +++ b/input/drivers_joypad/switch_joypad.c @@ -2,8 +2,13 @@ #include "../../config.h" #endif -#include +#ifdef HAVE_LIBNX +#include +#else +#include +#endif +#include "../configuration.h" #include "../input_driver.h" #include "../../tasks/tasks_internal.h" @@ -13,10 +18,20 @@ #include "string.h" +#ifdef HAVE_LIBNX + +#ifndef MAX_PADS +#define MAX_PADS 8 +#endif + +#else + #ifndef MAX_PADS #define MAX_PADS 10 #endif +#endif + static uint16_t pad_state[MAX_PADS]; static int16_t analog_state[MAX_PADS][2][2]; extern uint64_t lifecycle_state; @@ -40,10 +55,16 @@ static void switch_joypad_autodetect_add(unsigned autoconf_pad) static bool switch_joypad_init(void *data) { +#ifdef HAVE_LIBNX + unsigned i; + hidScanInput(); + for (i = 0; i < MAX_PADS; i++) + switch_joypad_autodetect_add(i); +#else hid_init(); - switch_joypad_autodetect_add(0); switch_joypad_autodetect_add(1); +#endif return true; } @@ -126,27 +147,78 @@ static bool switch_joypad_query_pad(unsigned pad) static void switch_joypad_destroy(void) { +#ifndef HAVE_LIBNX hid_finalize(); +#endif } +#ifdef HAVE_LIBNX +int lastMode = 0; // 0 = handheld, 1 = whatever + static void switch_joypad_poll(void) { + settings_t *settings = config_get_ptr(); + + hidScanInput(); + + if (settings->bools.split_joycon && !hidGetHandheldMode()) + { + if (lastMode != 1) + { + RARCH_LOG("[HID] Enable Split Joycon!\n"); + hidSetNpadJoyAssignmentModeSingleByDefault(CONTROLLER_PLAYER_1); + hidSetNpadJoyAssignmentModeSingleByDefault(CONTROLLER_PLAYER_2); + lastMode = 1; + } + } + else + { + if (lastMode != 0) + { + RARCH_LOG("[HID] Disable Split Joycon!\n"); + hidSetNpadJoyAssignmentModeDual(CONTROLLER_PLAYER_1); + hidSetNpadJoyAssignmentModeDual(CONTROLLER_PLAYER_2); + lastMode = 0; + } + } + for (int i = 0; i < MAX_PADS; i++) + { + HidControllerID target = (i == 0) ? CONTROLLER_P1_AUTO : i; + pad_state[i] = hidKeysDown(target) | hidKeysHeld(target); + JoystickPosition joyPositionLeft, joyPositionRight; + hidJoystickRead(&joyPositionLeft, target, JOYSTICK_LEFT); + hidJoystickRead(&joyPositionRight, target, JOYSTICK_RIGHT); + analog_state[i][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_X] = joyPositionLeft.dx; + analog_state[i][RETRO_DEVICE_INDEX_ANALOG_LEFT][RETRO_DEVICE_ID_ANALOG_Y] = -joyPositionLeft.dy; + analog_state[i][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = joyPositionRight.dx; + analog_state[i][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = -joyPositionRight.dy; + } +} +#else +static void switch_joypad_poll(void) +{ + int16_t lsx, lsy, rsx, rsy; hid_controller_t *controllers = hid_get_shared_memory()->controllers; hid_controller_t *cont = &controllers[0]; hid_controller_state_entry_t ent = cont->main.entries[cont->main.latest_idx]; hid_controller_state_entry_t ent8 = (cont+8)->main.entries[(cont+8)->main.latest_idx]; - pad_state[0] = ent.button_state | ent8.button_state; + pad_state[0] = ent.button_state | ent8.button_state; - int16_t lsx, lsy, rsx, rsy; - lsx = ent.left_stick_x; - lsy = ent.left_stick_y; - rsx = ent.right_stick_x; - rsy = ent.right_stick_y; - if(ent8.left_stick_x != 0 || ent8.left_stick_y != 0) { // handheld overrides player 1 + lsx = ent.left_stick_x; + lsy = ent.left_stick_y; + rsx = ent.right_stick_x; + rsy = ent.right_stick_y; + + if (ent8.left_stick_x != 0 || ent8.left_stick_y != 0) + { + /* handheld overrides player 1 */ lsx = ent8.left_stick_x; lsy = ent8.left_stick_y; } - if(ent8.right_stick_x != 0 || ent8.right_stick_y != 0) { // handheld overrides player 1 + + if (ent8.right_stick_x != 0 || ent8.right_stick_y != 0) + { + /* handheld overrides player 1 */ rsx = ent8.right_stick_x; rsy = ent8.right_stick_y; } @@ -156,6 +228,7 @@ static void switch_joypad_poll(void) analog_state[0][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_X] = rsx; analog_state[0][RETRO_DEVICE_INDEX_ANALOG_RIGHT][RETRO_DEVICE_ID_ANALOG_Y] = -rsy; } +#endif input_device_driver_t switch_joypad = { switch_joypad_init, diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index 59e039c441..9af86a6dbc 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -668,7 +668,7 @@ const char* const input_builtin_autoconfs[] = #ifdef __CELLOS_LV2__ DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS), #endif -#ifdef __SWITCH__ +#if defined(__SWITCH__) || defined(SWITCH) DECL_AUTOCONF_DEVICE("Switch Controller", "switch", SWITCH_DEFAULT_BINDS), #endif #ifdef EMSCRIPTEN diff --git a/libretro-common/features/features_cpu.c b/libretro-common/features/features_cpu.c index 0d46fbaffe..9bf919c15d 100644 --- a/libretro-common/features/features_cpu.c +++ b/libretro-common/features/features_cpu.c @@ -79,7 +79,9 @@ #include #endif -#ifdef SWITCH +#if defined(HAVE_LIBNX) +#include +#elif defined(SWITCH) #include #include #endif @@ -219,7 +221,7 @@ retro_time_t cpu_features_get_time_usec(void) return sys_time_get_system_time(); #elif defined(GEKKO) return ticks_to_microsecs(gettime()); -#elif defined(SWITCH) +#elif defined(SWITCH) || defined(HAVE_LIBNX) return (svcGetSystemTick() * 10) / 192; #elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__) struct timespec tv = {0}; @@ -481,6 +483,8 @@ unsigned cpu_features_get_core_amount(void) return 1; #elif defined(VITA) return 4; +#elif defined(HAVE_LIBNX) || defined(SWITCH) + return 4; #elif defined(_3DS) u8 device_model = 0xFF; CFGU_GetSystemModel(&device_model);/*(0 = O3DS, 1 = O3DSXL, 2 = N3DS, 3 = 2DS, 4 = N3DSXL, 5 = N2DSXL)*/ From cc8b458ee3bd1f8e724bbea64e8f2d2a9012f72f Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 20:01:56 +0200 Subject: [PATCH 087/335] Add menu_display_switch.c --- griffin/griffin.c | 4 + menu/drivers_display/menu_display_switch.c | 104 +++++++++++++++++++++ menu/menu_driver.c | 4 + menu/menu_driver.h | 2 + 4 files changed, 114 insertions(+) create mode 100644 menu/drivers_display/menu_display_switch.c diff --git a/griffin/griffin.c b/griffin/griffin.c index b2131b38ed..118c307fc6 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -1215,6 +1215,10 @@ MENU #include "../menu/drivers_display/menu_display_wiiu.c" #endif +#if defined(HAVE_LIBNX) +#include "../menu/drivers_display/menu_display_switch.c" +#endif + #ifdef HAVE_CACA #include "../menu/drivers_display/menu_display_caca.c" #endif diff --git a/menu/drivers_display/menu_display_switch.c b/menu/drivers_display/menu_display_switch.c new file mode 100644 index 0000000000..585ba98d3b --- /dev/null +++ b/menu/drivers_display/menu_display_switch.c @@ -0,0 +1,104 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2018 - m4xw + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ +#include + +#include +#include + +#include "../../gfx/font_driver.h" +#include "../../gfx/video_driver.h" + +#include "../menu_driver.h" + +static void *menu_display_switch_get_default_mvp(video_frame_info_t *video_info) +{ + return NULL; +} + +static void menu_display_switch_blend_begin(video_frame_info_t *video_info) +{ +} + +static void menu_display_switch_blend_end(video_frame_info_t *video_info) +{ +} + +static void menu_display_switch_draw(menu_display_ctx_draw_t *draw, + video_frame_info_t *video_info) +{ +} + +static void menu_display_switch_draw_pipeline( + menu_display_ctx_draw_t *draw, video_frame_info_t *video_info) +{ +} + +static void menu_display_switch_viewport(menu_display_ctx_draw_t *draw, + video_frame_info_t *video_info) +{ +} + +static void menu_display_switch_restore_clear_color(void) +{ +} + +static void menu_display_switch_clear_color( + menu_display_ctx_clearcolor_t *clearcolor, + video_frame_info_t *video_info) +{ + (void)clearcolor; +} + +static bool menu_display_switch_font_init_first( + void **font_handle, void *video_data, + const char *font_path, float font_size, + bool is_threaded) +{ + font_data_t **handle = (font_data_t**)font_handle; + *handle = font_driver_init_first(video_data, + font_path, font_size, true, + is_threaded, + FONT_DRIVER_RENDER_SWITCH); + return *handle; +} + +static const float *menu_display_switch_get_default_vertices(void) +{ + static float dummy[16] = {0.0f}; + return &dummy[0]; +} + +static const float *menu_display_switch_get_default_tex_coords(void) +{ + static float dummy[16] = {0.0f}; + return &dummy[0]; +} + +menu_display_ctx_driver_t menu_display_ctx_switch = { + menu_display_switch_draw, + menu_display_switch_draw_pipeline, + menu_display_switch_viewport, + menu_display_switch_blend_begin, + menu_display_switch_blend_end, + menu_display_switch_restore_clear_color, + menu_display_switch_clear_color, + menu_display_switch_get_default_mvp, + menu_display_switch_get_default_vertices, + menu_display_switch_get_default_tex_coords, + menu_display_switch_font_init_first, + MENU_VIDEO_DRIVER_SWITCH, + "menu_display_switch", + false +}; diff --git a/menu/menu_driver.c b/menu/menu_driver.c index effc75d61a..0ae873fc26 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -325,6 +325,10 @@ static bool menu_display_check_compatibility( if (string_is_equal(video_driver, "vga")) return true; break; + case MENU_VIDEO_DRIVER_SWITCH: + if (string_is_equal(video_driver, "switch")) + return true; + break; } return false; diff --git a/menu/menu_driver.h b/menu/menu_driver.h index c802d8e812..b040f3aed4 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -318,6 +318,7 @@ enum menu_display_driver_type MENU_VIDEO_DRIVER_CACA, MENU_VIDEO_DRIVER_SIXEL, MENU_VIDEO_DRIVER_GDI, + MENU_VIDEO_DRIVER_SWITCH, MENU_VIDEO_DRIVER_VGA }; @@ -818,6 +819,7 @@ extern menu_display_ctx_driver_t menu_display_ctx_wiiu; extern menu_display_ctx_driver_t menu_display_ctx_caca; extern menu_display_ctx_driver_t menu_display_ctx_gdi; extern menu_display_ctx_driver_t menu_display_ctx_vga; +extern menu_display_ctx_driver_t menu_display_ctx_switch; extern menu_display_ctx_driver_t menu_display_ctx_sixel; extern menu_display_ctx_driver_t menu_display_ctx_null; From 19b4ef3b2c07126160ba56e43dc5899603642ea8 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 20:04:52 +0200 Subject: [PATCH 088/335] Add conv rgb565 to ABGR8888 by m4xw --- libretro-common/gfx/scaler/pixconv.c | 59 ++++++++++++++++++++ libretro-common/gfx/scaler/scaler.c | 3 + libretro-common/include/gfx/scaler/pixconv.h | 4 ++ 3 files changed, 66 insertions(+) diff --git a/libretro-common/gfx/scaler/pixconv.c b/libretro-common/gfx/scaler/pixconv.c index 64f5d89d0d..15f0094781 100644 --- a/libretro-common/gfx/scaler/pixconv.c +++ b/libretro-common/gfx/scaler/pixconv.c @@ -254,6 +254,65 @@ void conv_rgb565_argb8888(void *output_, const void *input_, } } +void conv_rgb565_abgr8888(void *output_, const void *input_, + int width, int height, + int out_stride, int in_stride) +{ + int h; + const uint16_t *input = (const uint16_t*)input_; + uint32_t *output = (uint32_t*)output_; + #if defined(__SSE2__) + const __m128i pix_mask_r = _mm_set1_epi16(0x1f << 10); + const __m128i pix_mask_g = _mm_set1_epi16(0x3f << 5); + const __m128i pix_mask_b = _mm_set1_epi16(0x1f << 5); + const __m128i mul16_r = _mm_set1_epi16(0x0210); + const __m128i mul16_g = _mm_set1_epi16(0x2080); + const __m128i mul16_b = _mm_set1_epi16(0x4200); + const __m128i a = _mm_set1_epi16(0x00ff); + int max_width = width - 7; +#endif + for (h = 0; h < height; + h++, output += out_stride >> 2, input += in_stride >> 1) + { + int w = 0; +#if defined(__SSE2__) + for (; w < max_width; w += 8) + { + __m128i res_lo, res_hi; + __m128i res_lo_bg, res_hi_bg, res_lo_ra, res_hi_ra; + const __m128i in = _mm_loadu_si128((const __m128i*)(input + w)); + __m128i r = _mm_and_si128(_mm_srli_epi16(in, 1), pix_mask_r); + __m128i g = _mm_and_si128(in, pix_mask_g); + __m128i b = _mm_and_si128(_mm_slli_epi16(in, 5), pix_mask_b); + r = _mm_mulhi_epi16(r, mul16_r); + g = _mm_mulhi_epi16(g, mul16_g); + b = _mm_mulhi_epi16(b, mul16_b); + res_lo_bg = _mm_unpacklo_epi8(b, g); + res_hi_bg = _mm_unpackhi_epi8(b, g); + res_lo_ra = _mm_unpacklo_epi8(r, a); + res_hi_ra = _mm_unpackhi_epi8(r, a); + res_lo = _mm_or_si128(res_lo_bg, + _mm_slli_si128(res_lo_ra, 2)); + res_hi = _mm_or_si128(res_hi_bg, + _mm_slli_si128(res_hi_ra, 2)); + _mm_storeu_si128((__m128i*)(output + w + 0), res_lo); + _mm_storeu_si128((__m128i*)(output + w + 4), res_hi); + } +#endif + for (; w < width; w++) + { + uint32_t col = input[w]; + uint32_t r = (col >> 11) & 0x1f; + uint32_t g = (col >> 5) & 0x3f; + uint32_t b = (col >> 0) & 0x1f; + r = (r << 3) | (r >> 2); + g = (g << 2) | (g >> 4); + b = (b << 3) | (b >> 2); + output[w] = (0xffu << 24) | (b << 16) | (g << 8) | (r << 0); + } + } +} + void conv_argb8888_rgba4444(void *output_, const void *input_, int width, int height, int out_stride, int in_stride) diff --git a/libretro-common/gfx/scaler/scaler.c b/libretro-common/gfx/scaler/scaler.c index 803fecb1aa..047c374548 100644 --- a/libretro-common/gfx/scaler/scaler.c +++ b/libretro-common/gfx/scaler/scaler.c @@ -119,6 +119,9 @@ bool scaler_ctx_gen_filter(struct scaler_ctx *ctx) case SCALER_FMT_ARGB8888: ctx->direct_pixconv = conv_rgb565_argb8888; break; + case SCALER_FMT_ABGR8888: + ctx->direct_pixconv = conv_rgb565_abgr8888; + break; case SCALER_FMT_BGR24: ctx->direct_pixconv = conv_rgb565_bgr24; break; diff --git a/libretro-common/include/gfx/scaler/pixconv.h b/libretro-common/include/gfx/scaler/pixconv.h index 100864de68..b83e0e7f03 100644 --- a/libretro-common/include/gfx/scaler/pixconv.h +++ b/libretro-common/include/gfx/scaler/pixconv.h @@ -42,6 +42,10 @@ void conv_rgb565_0rgb1555(void *output, const void *input, int width, int height, int out_stride, int in_stride); +void conv_rgb565_abgr8888(void *output, const void *input, + int width, int height, + int out_stride, int in_stride); + void conv_rgb565_argb8888(void *output, const void *input, int width, int height, int out_stride, int in_stride); From 8f9dc13aa73d2cdd118a803c25ee4cfaf157a273 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 21:28:54 +0200 Subject: [PATCH 089/335] Add copyrights --- audio/drivers/switch_nx_thread_audio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/audio/drivers/switch_nx_thread_audio.c b/audio/drivers/switch_nx_thread_audio.c index 2b72b318de..e857aee145 100644 --- a/audio/drivers/switch_nx_thread_audio.c +++ b/audio/drivers/switch_nx_thread_audio.c @@ -1,4 +1,7 @@ /* RetroArch - A frontend for libretro. + * Copyright (C) 2018 - misson2000 + * Copyright (C) 2018 - m4xw + * Copyright (C) 2018 - lifajucejo * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- From 0158bbe4aa81c4cacd067b8837efe60d769780b5 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 21:44:53 +0200 Subject: [PATCH 090/335] Add switch_nx_gfx.c --- gfx/drivers/switch_gfx.c | 16 + gfx/drivers/switch_nx_gfx.c | 782 +++++++++++++++++++++++++++++++++ gfx/drivers_font/switch_font.c | 350 +++++++++++++++ gfx/font_driver.h | 1 + gfx/video_defines.h | 3 +- 5 files changed, 1151 insertions(+), 1 deletion(-) create mode 100644 gfx/drivers/switch_nx_gfx.c create mode 100644 gfx/drivers_font/switch_font.c diff --git a/gfx/drivers/switch_gfx.c b/gfx/drivers/switch_gfx.c index 6bab28d5e3..b367786369 100644 --- a/gfx/drivers/switch_gfx.c +++ b/gfx/drivers/switch_gfx.c @@ -1,3 +1,19 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2018 - misson2000 + * Copyright (C) 2018 - m4xw + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + #include #include #include diff --git a/gfx/drivers/switch_nx_gfx.c b/gfx/drivers/switch_nx_gfx.c new file mode 100644 index 0000000000..5a34783951 --- /dev/null +++ b/gfx/drivers/switch_nx_gfx.c @@ -0,0 +1,782 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2018 - misson2000 + * Copyright (C) 2018 - m4xw + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#ifdef HAVE_CONFIG_H +#include "../../config.h" +#endif + +#ifdef HAVE_MENU +#include "../../menu/menu_driver.h" +#endif + +#include "../font_driver.h" + +#include "../../configuration.h" +#include "../../command.h" +#include "../../driver.h" + +#include "../../retroarch.h" +#include "../../verbosity.h" + +#include "../common/switch_common.h" + +#ifndef HAVE_THREADS +#include "../../tasks/tasks_internal.h" +#endif + +#ifdef HAVE_NXRGUI +extern uint32_t *nx_backgroundImage; +// Temp Overlay // KILL IT WITH FIRE +extern uint32_t *tmp_overlay; +#endif + +// (C) libtransistor +static int pdep(uint32_t mask, uint32_t value) +{ + uint32_t out = 0; + for (int shift = 0; shift < 32; shift++) + { + uint32_t bit = 1u << shift; + if (mask & bit) + { + if (value & 1) + out |= bit; + value >>= 1; + } + } + return out; +} + +static uint32_t swizzle_x(uint32_t v) { return pdep(~0x7B4u, v); } +static uint32_t swizzle_y(uint32_t v) { return pdep(0x7B4, v); } + +void gfx_slow_swizzling_blit(uint32_t *buffer, uint32_t *image, int w, int h, int tx, int ty, bool blend) +{ + uint32_t *dest = buffer; + uint32_t *src = image; + int x0 = tx; + int y0 = ty; + int x1 = x0 + w; + int y1 = y0 + h; + const uint32_t tile_height = 128; + const uint32_t padded_width = 128 * 10; + + // we're doing this in pixels - should just shift the swizzles instead + uint32_t offs_x0 = swizzle_x(x0); + uint32_t offs_y = swizzle_y(y0); + uint32_t x_mask = swizzle_x(~0u); + uint32_t y_mask = swizzle_y(~0u); + uint32_t incr_y = swizzle_x(padded_width); + + // step offs_x0 to the right row of tiles + offs_x0 += incr_y * (y0 / tile_height); + + uint32_t x, y; + for (y = y0; y < y1; y++) + { + uint32_t *dest_line = dest + offs_y; + uint32_t offs_x = offs_x0; + + for (x = x0; x < x1; x++) + { + uint32_t pixel = *src++; + if (blend) // supercheap masking + { + uint32_t dst = dest_line[offs_x]; + uint8_t src_a = ((pixel & 0xFF000000) >> 24); + + if (src_a > 0) + { + pixel &= 0x00FFFFFF; + } + else + { + pixel = dst; + } + } + + dest_line[offs_x] = pixel; + + offs_x = (offs_x - x_mask) & x_mask; + } + + offs_y = (offs_y - y_mask) & y_mask; + if (!offs_y) + offs_x0 += incr_y; // wrap into next tile row + } +} + +// needed to clear surface completely as hw scaling doesn't always scale to full resoution perflectly +static void clear_screen(switch_video_t *sw) +{ + gfxConfigureResolution(sw->vp.full_width, sw->vp.full_height); + + uint32_t *out_buffer = (uint32_t *)gfxGetFramebuffer(NULL, NULL); + + memset(out_buffer, 0, gfxGetFramebufferSize()); + + gfxFlushBuffers(); + gfxSwapBuffers(); + gfxWaitForVsync(); +} + +static void *switch_init(const video_info_t *video, + const input_driver_t **input, void **input_data) +{ + void *switchinput = NULL; + + switch_video_t *sw = (switch_video_t *)calloc(1, sizeof(*sw)); + if (!sw) + return NULL; + + printf("loading switch gfx driver, width: %d, height: %d threaded: %d smooth %d\n", video->width, video->height, video->is_threaded, video->smooth); + sw->vp.x = 0; + sw->vp.y = 0; + sw->vp.width = sw->o_width = video->width; + sw->vp.height = sw->o_height = video->height; + sw->overlay_enabled = false; + sw->overlay = NULL; + sw->in_menu = false; + + sw->vp.full_width = 1280; + sw->vp.full_height = 720; + + // Sanity check + sw->vp.width = MIN(sw->vp.width, sw->vp.full_width); + sw->vp.height = MIN(sw->vp.height, sw->vp.full_height); + + sw->vsync = video->vsync; + sw->rgb32 = video->rgb32; + sw->keep_aspect = true; + sw->should_resize = true; + sw->o_size = true; + sw->is_threaded = video->is_threaded; + sw->smooth = video->smooth; + sw->menu_texture.enable = false; + + // Autoselect driver + if (input && input_data) + { + settings_t *settings = config_get_ptr(); + switchinput = input_switch.init(settings->arrays.input_joypad_driver); + *input = switchinput ? &input_switch : NULL; + *input_data = switchinput; + } + + font_driver_init_osd(sw, false, + video->is_threaded, + FONT_DRIVER_RENDER_SWITCH); + + clear_screen(sw); + + return sw; +} + +static void switch_update_viewport(switch_video_t *sw, video_frame_info_t *video_info) +{ + int x = 0; + int y = 0; + float width = sw->vp.full_width; + float height = sw->vp.full_height; + if (sw->o_size) + { + width = sw->o_width; + height = sw->o_height; + sw->vp.x = (int)(((float)sw->vp.full_width - width)) / 2; + sw->vp.y = (int)(((float)sw->vp.full_height - height)) / 2; + + sw->vp.width = width; + sw->vp.height = height; + + return; + } + + settings_t *settings = config_get_ptr(); + float desired_aspect = video_driver_get_aspect_ratio(); + + // We crash if >1.0f + printf("[Video] Aspect: %f\n", desired_aspect); + /*if (desired_aspect > 1.8f) + desired_aspect = 1.7778f; + + if (desired_aspect < 1.2f && desired_aspect != 0.0f) + desired_aspect = 1.0f;*/ + + if (settings->bools.video_scale_integer) + { + video_viewport_get_scaled_integer(&sw->vp, sw->vp.full_width, sw->vp.full_height, desired_aspect, sw->keep_aspect); + } + else if (sw->keep_aspect) + { +#if defined(HAVE_MENU) + if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM) + { + sw->vp.x = sw->vp.y = 0; + sw->vp.width = width; + sw->vp.height = height; + } + else +#endif + { + float delta; + float device_aspect = ((float)sw->vp.full_width) / sw->vp.full_height; + + if (fabsf(device_aspect - desired_aspect) < 0.0001f) + { + /* + * If the aspect ratios of screen and desired aspect + * ratio are sufficiently equal (floating point stuff), + * assume they are actually equal. + */ + } + else if (device_aspect > desired_aspect) + { + delta = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f; + x = (int)roundf(width * (0.5f - delta)); + width = (unsigned)roundf(2.0f * width * delta); + } + else + { + delta = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f; + y = (int)roundf(height * (0.5f - delta)); + height = (unsigned)roundf(2.0f * height * delta); + } + } + + sw->vp.x = x; + sw->vp.y = y; + + sw->vp.width = width; + sw->vp.height = height; + } + else + { + sw->vp.x = sw->vp.y = 0; + sw->vp.width = width; + sw->vp.height = height; + } +} + +static void switch_set_aspect_ratio(void *data, unsigned aspect_ratio_idx) +{ + switch_video_t *sw = (switch_video_t *)data; + + if (!sw) + return; + + sw->keep_aspect = true; + sw->o_size = false; + + settings_t *settings = config_get_ptr(); + + switch (aspect_ratio_idx) + { + case ASPECT_RATIO_SQUARE: + video_driver_set_viewport_square_pixel(); + break; + + case ASPECT_RATIO_CORE: + video_driver_set_viewport_core(); + sw->o_size = true; + sw->keep_aspect = false; + break; + + case ASPECT_RATIO_CONFIG: + video_driver_set_viewport_config(); + break; + + case ASPECT_RATIO_CUSTOM: + if (settings->bools.video_scale_integer) + { + video_driver_set_viewport_core(); + sw->o_size = true; + sw->keep_aspect = false; + } + break; + + default: + break; + } + + video_driver_set_aspect_ratio_value(aspectratio_lut[aspect_ratio_idx].value); + + sw->should_resize = true; +} + +static bool switch_frame(void *data, const void *frame, + unsigned width, unsigned height, + uint64_t frame_count, unsigned pitch, + const char *msg, video_frame_info_t *video_info) +{ + switch_video_t *sw = data; + uint32_t *out_buffer = NULL; + bool ffwd_mode = video_info->input_driver_nonblock_state; + + if (!frame) + return true; + + if (ffwd_mode && !sw->is_threaded) + { + // render every 4th frame when in ffwd mode and not threaded + if ((frame_count % 4) != 0) + return true; + } + + if (sw->should_resize || width != sw->last_width || height != sw->last_height) + { + printf("[Video] Requesting new size: width %i height %i\n", width, height); + printf("[Video] fw: %i fh: %i w: %i h: %i x: %i y: %i\n", sw->vp.full_width, sw->vp.full_height, sw->vp.width, sw->vp.height, sw->vp.x, sw->vp.y); + switch_update_viewport(sw, video_info); + printf("[Video] fw: %i fh: %i w: %i h: %i x: %i y: %i\n", sw->vp.full_width, sw->vp.full_height, sw->vp.width, sw->vp.height, sw->vp.x, sw->vp.y); + + // Sanity check + sw->vp.width = MIN(sw->vp.width, sw->vp.full_width); + sw->vp.height = MIN(sw->vp.height, sw->vp.full_height); + + scaler_ctx_gen_reset(&sw->scaler); + + sw->scaler.in_width = width; + sw->scaler.in_height = height; + sw->scaler.in_stride = pitch; + sw->scaler.in_fmt = sw->rgb32 ? SCALER_FMT_ARGB8888 : SCALER_FMT_RGB565; + + if (!sw->smooth) + { + sw->scaler.out_width = sw->vp.width; + sw->scaler.out_height = sw->vp.height; + sw->scaler.out_stride = sw->vp.full_width * sizeof(uint32_t); + } + else + { + sw->scaler.out_width = width; + sw->scaler.out_height = height; + sw->scaler.out_stride = width * sizeof(uint32_t); + + float screen_ratio = (float)sw->vp.full_width / sw->vp.full_height; + float tgt_ratio = (float)sw->vp.width / sw->vp.height; + + sw->hw_scale.width = ceil(screen_ratio / tgt_ratio * sw->scaler.out_width); + sw->hw_scale.height = sw->scaler.out_height; + sw->hw_scale.x_offset = ceil((sw->hw_scale.width - sw->scaler.out_width) / 2.0); + if (!video_info->menu_is_alive) + { + clear_screen(sw); + gfxConfigureResolution(sw->hw_scale.width, sw->hw_scale.height); + } + } + sw->scaler.out_fmt = SCALER_FMT_ABGR8888; + + sw->scaler.scaler_type = SCALER_TYPE_POINT; + + if (!scaler_ctx_gen_filter(&sw->scaler)) + { + printf("failed to generate scaler for main image\n"); + return false; + } + + sw->last_width = width; + sw->last_height = height; + + sw->should_resize = false; + } + + out_buffer = (uint32_t *)gfxGetFramebuffer(NULL, NULL); + + if (sw->in_menu && !video_info->menu_is_alive && sw->smooth) + { + memset(out_buffer, 0, sw->vp.full_width * sw->vp.full_height * 4); + gfxConfigureResolution(sw->hw_scale.width, sw->hw_scale.height); + } + sw->in_menu = video_info->menu_is_alive; + + if (sw->menu_texture.enable) + { + menu_driver_frame(video_info); + + if (sw->menu_texture.pixels) + { +#ifdef HAVE_NXRGUI + gfx_slow_swizzling_blit(out_buffer, nx_backgroundImage, sw->vp.full_width, sw->vp.full_height, 0, 0, false); +#else + memset(out_buffer, 0, gfxGetFramebufferSize()); +#endif + scaler_ctx_scale(&sw->menu_texture.scaler, sw->tmp_image + ((sw->vp.full_height - sw->menu_texture.tgth) / 2) * sw->vp.full_width + ((sw->vp.full_width - sw->menu_texture.tgtw) / 2), sw->menu_texture.pixels); + gfx_slow_swizzling_blit(out_buffer, sw->tmp_image, sw->vp.full_width, sw->vp.full_height, 0, 0, true); + } + } + else if (sw->smooth) // bilinear + { + struct scaler_ctx *ctx = &sw->scaler; + scaler_ctx_scale_direct(ctx, sw->image, frame); + int w = sw->scaler.out_width; + int h = sw->scaler.out_height; + for (int y = 0; y < h; y++) + for (int x = 0; x < w; x++) + out_buffer[gfxGetFramebufferDisplayOffset(x + sw->hw_scale.x_offset, y)] = sw->image[y * w + x]; + } + else + { + struct scaler_ctx *ctx = &sw->scaler; + scaler_ctx_scale(ctx, sw->image + (sw->vp.y * sw->vp.full_width) + sw->vp.x, frame); + gfx_slow_swizzling_blit(out_buffer, sw->image, sw->vp.full_width, sw->vp.full_height, 0, 0, false); +#ifdef HAVE_NXRGUI + if (tmp_overlay) + { + gfx_slow_swizzling_blit(out_buffer, tmp_overlay, sw->vp.full_width, sw->vp.full_height, 0, 0, true); + } +#endif + } + + if (video_info->statistics_show && !sw->smooth) + { + struct font_params *osd_params = (struct font_params *)&video_info->osd_stat_params; + + if (osd_params) + { + font_driver_render_msg(video_info, NULL, video_info->stat_text, + (const struct font_params *)&video_info->osd_stat_params); + } + } + + if (msg) + font_driver_render_msg(video_info, NULL, msg, NULL); + + gfxFlushBuffers(); + gfxSwapBuffers(); + if (sw->vsync || video_info->menu_is_alive) + gfxWaitForVsync(); + + return true; +} + +static void switch_set_nonblock_state(void *data, bool toggle) +{ + switch_video_t *sw = data; + sw->vsync = !toggle; +} + +static bool switch_alive(void *data) +{ + (void)data; + return true; +} + +static bool switch_focus(void *data) +{ + (void)data; + return true; +} + +static bool switch_suppress_screensaver(void *data, bool enable) +{ + (void)data; + (void)enable; + return false; +} + +static bool switch_has_windowed(void *data) +{ + (void)data; + return false; +} + +static void switch_free(void *data) +{ + switch_video_t *sw = data; + if (sw->menu_texture.pixels) + free(sw->menu_texture.pixels); + + free(sw); +} + +static bool switch_set_shader(void *data, + enum rarch_shader_type type, const char *path) +{ + (void)data; + (void)type; + (void)path; + + return false; +} + +static void switch_set_rotation(void *data, unsigned rotation) +{ + switch_video_t *sw = data; + if (!sw) + return; + sw->rotation = rotation; +} + +static void switch_viewport_info(void *data, struct video_viewport *vp) +{ + switch_video_t *sw = data; + *vp = sw->vp; +} + +static bool switch_read_viewport(void *data, uint8_t *buffer, bool is_idle) +{ + (void)data; + (void)buffer; + + return true; +} + +static void switch_set_texture_frame( + void *data, const void *frame, bool rgb32, + unsigned width, unsigned height, float alpha) +{ + switch_video_t *sw = data; + size_t sz = width * height * (rgb32 ? 4 : 2); + + if (!sw->menu_texture.pixels || + sw->menu_texture.width != width || + sw->menu_texture.height != height) + { + if (sw->menu_texture.pixels) + { + realloc(sw->menu_texture.pixels, sz); + } + else + { + sw->menu_texture.pixels = malloc(sz); + } + + if (!sw->menu_texture.pixels) + { + printf("failed to allocate buffer for menu texture\n"); + return; + } + + int xsf = 1280 / width; + int ysf = 720 / height; + int sf = xsf; + + if (ysf < sf) + sf = ysf; + + sw->menu_texture.width = width; + sw->menu_texture.height = height; + sw->menu_texture.tgtw = width * sf; + sw->menu_texture.tgth = height * sf; + + struct scaler_ctx *sctx = &sw->menu_texture.scaler; + scaler_ctx_gen_reset(sctx); + + sctx->in_width = width; + sctx->in_height = height; + sctx->in_stride = width * (rgb32 ? 4 : 2); + sctx->in_fmt = rgb32 ? SCALER_FMT_ARGB8888 : SCALER_FMT_RGB565; + sctx->out_width = sw->menu_texture.tgtw; + sctx->out_height = sw->menu_texture.tgth; + sctx->out_stride = 1280 * 4; + sctx->out_fmt = SCALER_FMT_ABGR8888; + + sctx->scaler_type = SCALER_TYPE_POINT; + + if (!scaler_ctx_gen_filter(sctx)) + { + printf("failed to generate scaler for menu texture\n"); + return; + } + } + + memcpy(sw->menu_texture.pixels, frame, sz); +} + +static void switch_apply_state_changes(void *data) +{ + (void)data; +} + +static void switch_set_texture_enable(void *data, bool enable, bool full_screen) +{ + switch_video_t *sw = data; + + if (!sw->menu_texture.enable && enable) + { + gfxConfigureResolution(sw->vp.full_width, sw->vp.full_height); + } + else if (!enable && sw->menu_texture.enable && sw->smooth) + { + clear_screen(sw); + gfxConfigureResolution(sw->hw_scale.width, sw->hw_scale.height); + } + + sw->menu_texture.enable = enable; + sw->menu_texture.fullscreen = full_screen; +} + +static void switch_set_osd_msg(void *data, + video_frame_info_t *video_info, + const char *msg, + const void *params, void *font) +{ + switch_video_t *sw = (switch_video_t *)data; + + if (sw) + font_driver_render_msg(video_info, font, msg, params); +} + +#ifdef HAVE_OVERLAY +static void switch_overlay_enable(void *data, bool state) +{ + printf("[Video] Enabled Overlay\n"); + + switch_video_t *swa = (switch_video_t *)data; + + if (!swa) + return; + + swa->overlay_enabled = state; +} + +static bool switch_overlay_load(void *data, + const void *image_data, unsigned num_images) +{ + switch_video_t *swa = (switch_video_t *)data; + + struct texture_image *images = (struct texture_image *)image_data; + + if (!swa) + return false; + + swa->overlay = images; + swa->overlay_enabled = true; + + return true; +} + +static void switch_overlay_tex_geom(void *data, + unsigned idx, float x, float y, float w, float h) +{ + switch_video_t *swa = (switch_video_t *)data; + + if (!swa) + return; +} + +static void switch_overlay_vertex_geom(void *data, + unsigned idx, float x, float y, float w, float h) +{ + switch_video_t *swa = (switch_video_t *)data; + + if (!swa) + return; +} + +static void switch_overlay_full_screen(void *data, bool enable) +{ + (void)data; + (void)enable; +} + +static void switch_overlay_set_alpha(void *data, unsigned idx, float mod) +{ + (void)data; + (void)idx; + (void)mod; +} + +static const video_overlay_interface_t switch_overlay = { + switch_overlay_enable, + switch_overlay_load, + switch_overlay_tex_geom, + switch_overlay_vertex_geom, + switch_overlay_full_screen, + switch_overlay_set_alpha, +}; + +void switch_overlay_interface(void *data, const video_overlay_interface_t **iface) +{ + switch_video_t *swa = (switch_video_t *)data; + if (!swa) + return; + *iface = &switch_overlay; +} + +#endif + +static const video_poke_interface_t switch_poke_interface = { + NULL, /* get_flags */ + NULL, /* set_coords */ + NULL, /* set_mvp */ + NULL, /* load_texture */ + NULL, /* unload_texture */ + NULL, /* set_video_mode */ + NULL, /* get_refresh_rate */ + NULL, /* set_filtering */ + NULL, /* get_video_output_size */ + NULL, /* get_video_output_prev */ + NULL, /* get_video_output_next */ + NULL, /* get_current_framebuffer */ + NULL, /* get_proc_address */ + switch_set_aspect_ratio, /* set_aspect_ratio */ + switch_apply_state_changes, /* apply_state_changes */ + switch_set_texture_frame, + switch_set_texture_enable, + switch_set_osd_msg, + NULL, /* show_mouse */ + NULL, /* grab_mouse_toggle */ + NULL, /* get_current_shader */ + NULL, /* get_current_software_framebuffer */ + NULL, /* get_hw_render_interface */ +}; + +static void switch_get_poke_interface(void *data, + const video_poke_interface_t **iface) +{ + (void)data; + *iface = &switch_poke_interface; +} + +video_driver_t video_switch = { + switch_init, + switch_frame, + switch_set_nonblock_state, + switch_alive, + switch_focus, + switch_suppress_screensaver, + switch_has_windowed, + switch_set_shader, + switch_free, + "switch", + NULL, /* set_viewport */ + switch_set_rotation, + switch_viewport_info, + switch_read_viewport, + NULL, /* read_frame_raw */ +#ifdef HAVE_OVERLAY + switch_overlay_interface, /* switch_overlay_interface */ +#endif + switch_get_poke_interface, +}; + +/* vim: set ts=6 sw=6 sts=6: */ diff --git a/gfx/drivers_font/switch_font.c b/gfx/drivers_font/switch_font.c new file mode 100644 index 0000000000..0b9d5be7f3 --- /dev/null +++ b/gfx/drivers_font/switch_font.c @@ -0,0 +1,350 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2018 - lifajucejo + * Copyright (C) 2018 - m4xw + * Copyright (C) 2018 - natinusala + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include +#include +#include + +#include + +#include "../font_driver.h" +#include "../video_driver.h" + +#include "../../verbosity.h" + +#include "../common/switch_common.h" + +typedef struct +{ + struct font_atlas *atlas; + + const font_renderer_driver_t *font_driver; + void *font_data; +} switch_font_t; + +static void *switch_font_init_font(void *data, const char *font_path, + float font_size, bool is_threaded) +{ + switch_font_t *font = (switch_font_t *)calloc(1, sizeof(switch_font_t)); + + if (!font) + return NULL; + + if (!font_renderer_create_default((const void **)&font->font_driver, + &font->font_data, font_path, font_size)) + { + RARCH_WARN("Couldn't initialize font renderer.\n"); + free(font); + return NULL; + } + + font->atlas = font->font_driver->get_atlas(font->font_data); + + RARCH_LOG("Switch font driver initialized with backend %s\n", font->font_driver->ident); + + return font; +} + +static void switch_font_free_font(void *data, bool is_threaded) +{ + switch_font_t *font = (switch_font_t *)data; + + if (!font) + return; + + if (font->font_driver && font->font_data) + font->font_driver->free(font->font_data); + + free(font); +} + +static int switch_font_get_message_width(void *data, const char *msg, + unsigned msg_len, float scale) +{ + switch_font_t *font = (switch_font_t *)data; + + unsigned i; + int delta_x = 0; + + if (!font) + return 0; + + for (i = 0; i < msg_len; i++) + { + const char *msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + const struct font_glyph *glyph = + font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + delta_x += glyph->advance_x; + } + + return delta_x * scale; +} + +static void switch_font_render_line( + video_frame_info_t *video_info, + switch_font_t *font, const char *msg, unsigned msg_len, + float scale, const unsigned int color, float pos_x, + float pos_y, unsigned text_align) +{ + int delta_x = 0; + int delta_y = 0; + + unsigned fbWidth = 0; + unsigned fbHeight = 0; + + uint32_t *out_buffer = (uint32_t *)gfxGetFramebuffer(&fbWidth, &fbHeight); + if (out_buffer) + { + int x = roundf(pos_x * fbWidth); + int y = roundf((1.0f - pos_y) * fbHeight); + + switch (text_align) + { + case TEXT_ALIGN_RIGHT: + x -= switch_font_get_message_width(font, msg, msg_len, scale); + break; + case TEXT_ALIGN_CENTER: + x -= switch_font_get_message_width(font, msg, msg_len, scale) / 2; + break; + } + + for (int i = 0; i < msg_len; i++) + { + int off_x, off_y, tex_x, tex_y, width, height; + const char *msg_tmp = &msg[i]; + unsigned code = utf8_walk(&msg_tmp); + unsigned skip = msg_tmp - &msg[i]; + + if (skip > 1) + i += skip - 1; + + const struct font_glyph *glyph = + font->font_driver->get_glyph(font->font_data, code); + + if (!glyph) /* Do something smarter here ... */ + glyph = font->font_driver->get_glyph(font->font_data, '?'); + + if (!glyph) + continue; + + off_x = x + glyph->draw_offset_x + delta_x; + off_y = y + glyph->draw_offset_y + delta_y; + width = glyph->width; + height = glyph->height; + + tex_x = glyph->atlas_offset_x; + tex_y = glyph->atlas_offset_y; + + for (int y = tex_y; y < tex_y + height; y++) + { + uint8_t *row = &font->atlas->buffer[y * font->atlas->width]; + for (int x = tex_x; x < tex_x + width; x++) + { + if (!row[x]) + continue; + int x1 = off_x + (x - tex_x); + int y1 = off_y + (y - tex_y); + if (x1 < fbWidth && y1 < fbHeight) + out_buffer[gfxGetFramebufferDisplayOffset(x1, y1)] = color; + } + } + + delta_x += glyph->advance_x; + delta_y += glyph->advance_y; + } + } +} + +#define AVG_GLPYH_LIMIT 140 +static void switch_font_render_message( + video_frame_info_t *video_info, + switch_font_t *font, const char *msg, float scale, + const unsigned int color, float pos_x, float pos_y, + unsigned text_align) +{ + int lines = 0; + float line_height; + + if (!msg || !*msg) + return; + + /* If the font height is not supported just draw as usual */ + if (!font->font_driver->get_line_height) + { + int msgLen = strlen(msg); + if (msgLen <= AVG_GLPYH_LIMIT) + { + switch_font_render_line(video_info, font, msg, strlen(msg), + scale, color, pos_x, pos_y, text_align); + } + return; + } + line_height = scale / font->font_driver->get_line_height(font->font_data); + + for (;;) + { + const char *delim = strchr(msg, '\n'); + + /* Draw the line */ + if (delim) + { + unsigned msg_len = delim - msg; + if (msg_len <= AVG_GLPYH_LIMIT) + { + switch_font_render_line(video_info, font, msg, msg_len, + scale, color, pos_x, pos_y - (float)lines * line_height, + text_align); + } + msg += msg_len + 1; + lines++; + } + else + { + unsigned msg_len = strlen(msg); + if (msg_len <= AVG_GLPYH_LIMIT) + { + switch_font_render_line(video_info, font, msg, msg_len, + scale, color, pos_x, pos_y - (float)lines * line_height, + text_align); + } + break; + } + } +} + +static void switch_font_render_msg( + video_frame_info_t *video_info, + void *data, const char *msg, + const struct font_params *params) +{ + float x, y, scale, drop_mod, drop_alpha; + int drop_x, drop_y; + unsigned max_glyphs; + enum text_alignment text_align; + unsigned color, color_dark, r, g, b, + alpha, r_dark, g_dark, b_dark, alpha_dark; + switch_font_t *font = (switch_font_t *)data; + unsigned width = video_info->width; + unsigned height = video_info->height; + + if (!font || !msg || msg && !*msg) + return; + + if (params) + { + x = params->x; + y = params->y; + scale = params->scale; + text_align = params->text_align; + drop_x = params->drop_x; + drop_y = params->drop_y; + drop_mod = params->drop_mod; + drop_alpha = params->drop_alpha; + + r = FONT_COLOR_GET_RED(params->color); + g = FONT_COLOR_GET_GREEN(params->color); + b = FONT_COLOR_GET_BLUE(params->color); + alpha = FONT_COLOR_GET_ALPHA(params->color); + + color = params->color; + } + else + { + x = 0.0f; + y = 0.0f; + scale = 1.0f; + text_align = TEXT_ALIGN_LEFT; + + r = (video_info->font_msg_color_r * 255); + g = (video_info->font_msg_color_g * 255); + b = (video_info->font_msg_color_b * 255); + alpha = 255; + color = COLOR_ABGR(r, g, b, alpha); + + drop_x = -2; + drop_y = -2; + drop_mod = 0.3f; + drop_alpha = 1.0f; + } + + max_glyphs = strlen(msg); + + /*if (drop_x || drop_y) + max_glyphs *= 2; + + if (drop_x || drop_y) + { + r_dark = r * drop_mod; + g_dark = g * drop_mod; + b_dark = b * drop_mod; + alpha_dark = alpha * drop_alpha; + color_dark = COLOR_ABGR(r_dark, g_dark, b_dark, alpha_dark); + + switch_font_render_message(video_info, font, msg, scale, color_dark, + x + scale * drop_x / width, y + + scale * drop_y / height, text_align); + }*/ + + switch_font_render_message(video_info, font, msg, scale, + color, x, y, text_align); +} + +static const struct font_glyph *switch_font_get_glyph( + void *data, uint32_t code) +{ + switch_font_t *font = (switch_font_t *)data; + + if (!font || !font->font_driver) + return NULL; + + if (!font->font_driver->ident) + return NULL; + + return font->font_driver->get_glyph((void *)font->font_driver, code); +} + +static void switch_font_bind_block(void *data, void *userdata) +{ + (void)data; +} + +font_renderer_t switch_font = + { + switch_font_init_font, + switch_font_free_font, + switch_font_render_msg, + "switchfont", + switch_font_get_glyph, + switch_font_bind_block, + NULL, /* flush_block */ + switch_font_get_message_width, +}; diff --git a/gfx/font_driver.h b/gfx/font_driver.h index a32b834e85..03f08c6d54 100644 --- a/gfx/font_driver.h +++ b/gfx/font_driver.h @@ -173,6 +173,7 @@ extern font_renderer_t caca_font; extern font_renderer_t gdi_font; extern font_renderer_t vga_font; extern font_renderer_t sixel_font; +extern font_renderer_t switch_font; extern font_renderer_driver_t stb_font_renderer; extern font_renderer_driver_t stb_unicode_font_renderer; diff --git a/gfx/video_defines.h b/gfx/video_defines.h index 61b09d393a..7633846589 100644 --- a/gfx/video_defines.h +++ b/gfx/video_defines.h @@ -96,7 +96,8 @@ enum font_driver_render_api FONT_DRIVER_RENDER_CACA, FONT_DRIVER_RENDER_SIXEL, FONT_DRIVER_RENDER_GDI, - FONT_DRIVER_RENDER_VGA + FONT_DRIVER_RENDER_VGA, + FONT_DRIVER_RENDER_SWITCH }; enum text_alignment From 7428fef4bc2d9ab2fc14033b87ec51462e94bedf Mon Sep 17 00:00:00 2001 From: twinaphex Date: Wed, 12 Sep 2018 21:50:11 +0200 Subject: [PATCH 091/335] Cleanups --- gfx/drivers/switch_nx_gfx.c | 38 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/gfx/drivers/switch_nx_gfx.c b/gfx/drivers/switch_nx_gfx.c index 5a34783951..3674852544 100644 --- a/gfx/drivers/switch_nx_gfx.c +++ b/gfx/drivers/switch_nx_gfx.c @@ -114,13 +114,9 @@ void gfx_slow_swizzling_blit(uint32_t *buffer, uint32_t *image, int w, int h, in uint8_t src_a = ((pixel & 0xFF000000) >> 24); if (src_a > 0) - { pixel &= 0x00FFFFFF; - } else - { pixel = dst; - } } dest_line[offs_x] = pixel; @@ -151,8 +147,7 @@ static void clear_screen(switch_video_t *sw) static void *switch_init(const video_info_t *video, const input_driver_t **input, void **input_data) { - void *switchinput = NULL; - + void *switchinput = NULL; switch_video_t *sw = (switch_video_t *)calloc(1, sizeof(*sw)); if (!sw) return NULL; @@ -200,12 +195,16 @@ static void *switch_init(const video_info_t *video, return sw; } -static void switch_update_viewport(switch_video_t *sw, video_frame_info_t *video_info) +static void switch_update_viewport(switch_video_t *sw, + video_frame_info_t *video_info) { - int x = 0; - int y = 0; - float width = sw->vp.full_width; - float height = sw->vp.full_height; + settings_t *settings = config_get_ptr(); + int x = 0; + int y = 0; + float desired_aspect = 0.0f; + float width = sw->vp.full_width; + float height = sw->vp.full_height; + if (sw->o_size) { width = sw->o_width; @@ -219,10 +218,9 @@ static void switch_update_viewport(switch_video_t *sw, video_frame_info_t *video return; } - settings_t *settings = config_get_ptr(); - float desired_aspect = video_driver_get_aspect_ratio(); + desired_aspect = video_driver_get_aspect_ratio(); - // We crash if >1.0f + /* We crash if >1.0f */ printf("[Video] Aspect: %f\n", desired_aspect); /*if (desired_aspect > 1.8f) desired_aspect = 1.7778f; @@ -336,9 +334,9 @@ static bool switch_frame(void *data, const void *frame, uint64_t frame_count, unsigned pitch, const char *msg, video_frame_info_t *video_info) { - switch_video_t *sw = data; + switch_video_t *sw = data; uint32_t *out_buffer = NULL; - bool ffwd_mode = video_info->input_driver_nonblock_state; + bool ffwd_mode = video_info->input_driver_nonblock_state; if (!frame) return true; @@ -460,10 +458,8 @@ static bool switch_frame(void *data, const void *frame, struct font_params *osd_params = (struct font_params *)&video_info->osd_stat_params; if (osd_params) - { font_driver_render_msg(video_info, NULL, video_info->stat_text, (const struct font_params *)&video_info->osd_stat_params); - } } if (msg) @@ -561,13 +557,9 @@ static void switch_set_texture_frame( sw->menu_texture.height != height) { if (sw->menu_texture.pixels) - { realloc(sw->menu_texture.pixels, sz); - } else - { sw->menu_texture.pixels = malloc(sz); - } if (!sw->menu_texture.pixels) { @@ -621,9 +613,7 @@ static void switch_set_texture_enable(void *data, bool enable, bool full_screen) switch_video_t *sw = data; if (!sw->menu_texture.enable && enable) - { gfxConfigureResolution(sw->vp.full_width, sw->vp.full_height); - } else if (!enable && sw->menu_texture.enable && sw->smooth) { clear_screen(sw); From 2ff87fd66391b18f8ecb08557be2e0462fbf7878 Mon Sep 17 00:00:00 2001 From: Rob Loach Date: Fri, 14 Sep 2018 09:39:20 -0400 Subject: [PATCH 092/335] emscripten: Add ChaiLove selection to web player --- pkg/emscripten/libretro/embed.html | 1 + pkg/emscripten/libretro/index.html | 1 + 2 files changed, 2 insertions(+) diff --git a/pkg/emscripten/libretro/embed.html b/pkg/emscripten/libretro/embed.html index fbe346576c..788fb073af 100644 --- a/pkg/emscripten/libretro/embed.html +++ b/pkg/emscripten/libretro/embed.html @@ -28,6 +28,7 @@