diff --git a/gfx/video_crt_switch.c b/gfx/video_crt_switch.c
index d154cfa41b..4a9e582aaa 100644
--- a/gfx/video_crt_switch.c
+++ b/gfx/video_crt_switch.c
@@ -1,206 +1,351 @@
-/* CRT SwitchRes Core
- * Copyright (C) 2018 Alphanu / Ben Templeman.
- *
- * RetroArch - A frontend for libretro.
- * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
- * Copyright (C) 2011-2017 - Daniel De Matteis
- *
- * 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 "video_driver.h"
-#include "video_crt_switch.h"
-#include "video_display_server.h"
-
-static unsigned ra_core_width = 0;
-static unsigned ra_core_height = 0;
-static unsigned ra_tmp_width = 0;
-static unsigned ra_tmp_height = 0;
-static unsigned ra_set_core_hz = 0;
-static unsigned orig_width = 0;
-static unsigned orig_height = 0;
-static int crt_center_adjust = 0;
-
-static bool first_run = true;
-
-static float ra_tmp_core_hz = 0.0f;
-static float fly_aspect = 0.0f;
-static float ra_core_hz = 0.0f;
-
-static void crt_check_first_run(void)
-{
- if (!first_run)
- return;
-
- first_run = false;
-}
-
-static void switch_crt_hz(void)
-{
- if (ra_core_hz == ra_tmp_core_hz)
- return;
- /* set hz float to an int for windows switching */
- if (ra_core_hz < 100)
- {
- if (ra_core_hz < 53)
- ra_set_core_hz = 50;
- if (ra_core_hz >= 53 && ra_core_hz < 57)
- ra_set_core_hz = 55;
- if (ra_core_hz >= 57)
- ra_set_core_hz = 60;
- }
-
- if (ra_core_hz > 100)
- {
- if (ra_core_hz < 106)
- ra_set_core_hz = 120;
- if (ra_core_hz >= 106 && ra_core_hz < 114)
- ra_set_core_hz = 110;
- if (ra_core_hz >= 114)
- ra_set_core_hz = 120;
- }
-
- video_monitor_set_refresh_rate(ra_set_core_hz);
-
- ra_tmp_core_hz = ra_core_hz;
-}
-
-void crt_aspect_ratio_switch(unsigned width, unsigned height)
-{
- /* send aspect float to videeo_driver */
- fly_aspect = (float)width / height;
- video_driver_set_aspect_ratio_value((float)fly_aspect);
-}
-
-static void switch_res_crt(unsigned width, unsigned height)
-{
- if (height > 100)
- {
- video_display_server_set_resolution(width, height,
- ra_set_core_hz, ra_core_hz, crt_center_adjust);
- video_driver_apply_state_changes();
- }
-}
-
-/* Create correct aspect to fit video if resolution does not exist */
-static void crt_screen_setup_aspect(unsigned width, unsigned height)
-{
-
- switch_crt_hz();
- /* get original resolution of core */
- if (height == 4)
- {
- /* detect menu only */
- if (width < 1920)
- width = 320;
-
- height = 240;
-
- crt_aspect_ratio_switch(width, height);
- }
-
- if (height < 200 && height != 144)
- {
- crt_aspect_ratio_switch(width, height);
- height = 200;
- }
-
- if (height > 200)
- crt_aspect_ratio_switch(width, height);
-
- if (height == 144 && ra_set_core_hz == 50)
- {
- height = 288;
- crt_aspect_ratio_switch(width, height);
- }
-
- if (height > 200 && height < 224)
- {
- crt_aspect_ratio_switch(width, height);
- height = 224;
- }
-
- if (height > 224 && height < 240)
- {
- crt_aspect_ratio_switch(width, height);
- height = 240;
- }
-
- if (height > 240 && height < 255)
- {
- crt_aspect_ratio_switch(width, height);
- height = 254;
- }
-
- if (height == 528 && ra_set_core_hz == 60)
- {
- crt_aspect_ratio_switch(width, height);
- height = 480;
- }
-
- if (height >= 240 && height < 255 && ra_set_core_hz == 55)
- {
- crt_aspect_ratio_switch(width, height);
- height = 254;
- }
-
- switch_res_crt(width, height);
-}
-
-void crt_switch_res_core(unsigned width, unsigned height, float hz, unsigned crt_mode, int crt_switch_center_adjust)
-{
- /* ra_core_hz float passed from within
- * void video_driver_monitor_adjust_system_rates(void) */
- ra_core_width = width;
- ra_core_height = height;
- ra_core_hz = hz;
- crt_center_adjust = crt_switch_center_adjust;
-
- if (crt_mode == 2)
- {
- if (hz > 53)
- ra_core_hz = hz * 2;
-
- if (hz <= 53)
- ra_core_hz = 120.0f;
- }
-
- crt_check_first_run();
-
- /* Detect resolution change and switch */
- if (
- (ra_tmp_height != ra_core_height) ||
- (ra_core_width != ra_tmp_width)
- )
- crt_screen_setup_aspect(width, height);
-
- ra_tmp_height = ra_core_height;
- ra_tmp_width = ra_core_width;
-
- /* Check if aspect is correct, if notchange */
- if (video_driver_get_aspect_ratio() != fly_aspect)
- {
- video_driver_set_aspect_ratio_value((float)fly_aspect);
- video_driver_apply_state_changes();
- }
-}
-
-void crt_video_restore(void)
-{
- if (first_run)
- return;
-
- first_run = true;
-}
+/* CRT SwitchRes Core
+ * Copyright (C) 2018 Alphanu / Ben Templeman.
+ *
+ * RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ *
+ * 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 "video_driver.h"
+#include "video_crt_switch.h"
+#include "video_display_server.h"
+
+#if defined(__arm__)
+ #include "include/userland/interface/vmcs_host/vc_vchi_gencmd.h"
+#endif
+
+static unsigned ra_core_width = 0;
+static unsigned ra_core_height = 0;
+static unsigned ra_tmp_width = 0;
+static unsigned ra_tmp_height = 0;
+static unsigned ra_set_core_hz = 0;
+static unsigned orig_width = 0;
+static unsigned orig_height = 0;
+static int crt_center_adjust = 0;
+
+static bool first_run = true;
+
+static float ra_tmp_core_hz = 0.0f;
+static float fly_aspect = 0.0f;
+static float ra_core_hz = 0.0f;
+static unsigned crt_index = 0;
+
+static void crt_check_first_run(void)
+{
+ if (!first_run)
+ return;
+
+ first_run = false;
+}
+
+static void switch_crt_hz(void)
+{
+ if (ra_core_hz == ra_tmp_core_hz)
+ return;
+ /* set hz float to an int for windows switching */
+ if (ra_core_hz < 100)
+ {
+ if (ra_core_hz < 53)
+ ra_set_core_hz = 50;
+ if (ra_core_hz >= 53 && ra_core_hz < 57)
+ ra_set_core_hz = 55;
+ if (ra_core_hz >= 57)
+ ra_set_core_hz = 60;
+ }
+
+ if (ra_core_hz > 100)
+ {
+ if (ra_core_hz < 106)
+ ra_set_core_hz = 120;
+ if (ra_core_hz >= 106 && ra_core_hz < 114)
+ ra_set_core_hz = 110;
+ if (ra_core_hz >= 114)
+ ra_set_core_hz = 120;
+ }
+
+ video_monitor_set_refresh_rate(ra_set_core_hz);
+
+ ra_tmp_core_hz = ra_core_hz;
+}
+
+void crt_aspect_ratio_switch(unsigned width, unsigned height)
+{
+ /* send aspect float to videeo_driver */
+ fly_aspect = (float)width / height;
+ video_driver_set_aspect_ratio_value((float)fly_aspect);
+}
+
+static void switch_res_crt(unsigned width, unsigned height)
+{
+ video_display_server_set_resolution(width, height,
+ ra_set_core_hz, ra_core_hz, crt_center_adjust, crt_index);
+ #if defined(__arm__)
+ crt_rpi_switch(width, height, ra_core_hz);
+ video_monitor_set_refresh_rate(ra_core_hz);
+ crt_switch_driver_reinit();
+ #endif
+ video_driver_apply_state_changes();
+}
+
+/* Create correct aspect to fit video if resolution does not exist */
+static void crt_screen_setup_aspect(unsigned width, unsigned height)
+{
+ #if defined(__arm__)
+ if (height > 300)
+ height = height/2;
+ #endif
+
+ switch_crt_hz();
+ /* get original resolution of core */
+ if (height == 4)
+ {
+ /* detect menu only */
+ if (width < 1920)
+ width = 320;
+
+ height = 240;
+
+ crt_aspect_ratio_switch(width, height);
+ }
+
+ if (height < 200 && height != 144)
+ {
+ crt_aspect_ratio_switch(width, height);
+ height = 200;
+ }
+
+ if (height > 200)
+ crt_aspect_ratio_switch(width, height);
+
+ if (height == 144 && ra_set_core_hz == 50)
+ {
+ height = 288;
+ crt_aspect_ratio_switch(width, height);
+ }
+
+ if (height > 200 && height < 224)
+ {
+ crt_aspect_ratio_switch(width, height);
+ height = 224;
+ }
+
+ if (height > 224 && height < 240)
+ {
+ crt_aspect_ratio_switch(width, height);
+ height = 240;
+ }
+
+ if (height > 240 && height < 255)
+ {
+ crt_aspect_ratio_switch(width, height);
+ height = 254;
+ }
+
+ if (height == 528 && ra_set_core_hz == 60)
+ {
+ crt_aspect_ratio_switch(width, height);
+ height = 480;
+ }
+
+ if (height >= 240 && height < 255 && ra_set_core_hz == 55)
+ {
+ crt_aspect_ratio_switch(width, height);
+ height = 254;
+ }
+
+ switch_res_crt(width, height);
+}
+
+void crt_switch_res_core(unsigned width, unsigned height, float hz, unsigned crt_mode, int crt_switch_center_adjust)
+{
+ /* ra_core_hz float passed from within
+ * void video_driver_monitor_adjust_system_rates(void) */
+ ra_core_width = width;
+ ra_core_height = height;
+ ra_core_hz = hz;
+ crt_center_adjust = crt_switch_center_adjust;
+ crt_index = monitor_index;
+
+ if (crt_mode == 2)
+ {
+ if (hz > 53)
+ ra_core_hz = hz * 2;
+
+ if (hz <= 53)
+ ra_core_hz = 120.0f;
+ }
+
+ crt_check_first_run();
+
+ /* Detect resolution change and switch */
+ if (
+ (ra_tmp_height != ra_core_height) ||
+ (ra_core_width != ra_tmp_width)
+ )
+ crt_screen_setup_aspect(width, height);
+
+ ra_tmp_height = ra_core_height;
+ ra_tmp_width = ra_core_width;
+
+ /* Check if aspect is correct, if notchange */
+ if (video_driver_get_aspect_ratio() != fly_aspect)
+ {
+ video_driver_set_aspect_ratio_value((float)fly_aspect);
+ video_driver_apply_state_changes();
+ }
+}
+
+void crt_video_restore(void)
+{
+ if (first_run)
+ return;
+
+ first_run = true;
+}
+
+#if defined(__arm__)
+static void crt_rpi_switch(int width, int height, float hz)
+{
+ static char output[250] = {0};
+ static char output1[250] = {0};
+ static char output2[250] = {0};
+ static char set_hdmi[250] ={0};
+ static char set_hdmi_timing[250] = {0};
+ int i = 0;
+ int hfp = 0;
+ int hsp = 0;
+ int hbp = 0;
+ int vfp = 0;
+ int vsp = 0;
+ 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;
+ int ip_flag = 0;
+
+ /* set core refresh from hz */
+ video_monitor_set_refresh_rate(hz);
+
+ /* following code is the mode line generator */
+
+ 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;
+ hfp = width * 0.065;
+
+ hsp = width * 0.1433-hfp;
+
+ hbp = width * 0.3-hsp-hfp;
+
+
+ if (height < 241)
+ vmax = 261;
+ if (height < 241 && hz > 56 && hz < 58)
+ vmax = 280;
+ if (height < 241 && hz < 55)
+ vmax = 313;
+ if (height > 250 && height < 260 && hz > 54)
+ vmax = 296;
+ if (height > 250 && height < 260 && hz > 52 && hz < 54)
+ vmax = 285;
+ if (height > 250 && height < 260 && hz < 52)
+ vmax = 313;
+ if (height > 260 && height < 300)
+ vmax = 318;
+
+ if (height > 400 && hz > 56)
+ vmax = 533;
+ if (height > 520 && hz < 57)
+ vmax = 580;
+
+ if (height > 300 && hz < 56)
+ vmax = 615;
+ if (height > 500 && hz < 56)
+ vmax = 624;
+ if (height > 300)
+ pdefault = pdefault * 2;
+
+ vfp = (height + ((vmax - height) / 2) - pdefault) - height;
+
+ if (height < 300)
+ vsp = vfp + 3; /* needs to be 3 for progressive */
+ if (height > 300)
+ vsp = vfp + 6; /* needs to be 6 for interlaced */
+
+ vsp = 3;
+
+ vbp = (vmax-height)-vsp-vfp;
+
+ hmax = width+hfp+hsp+hbp;
+
+ if (height < 300)
+ {
+ pixel_clock = (hmax * vmax * hz) ;
+ ip_flag = 0;
+ }
+
+ if (height > 300)
+ {
+ pixel_clock = (hmax * vmax * (hz/2)) /2 ;
+ ip_flag = 1;
+ }
+ /* above code is the modeline generator */
+
+ snprintf(set_hdmi_timing, sizeof(set_hdmi_timings), "hdmi_timings %d 1 %d %d %d %d 1 %d %d %d 0 0 0 %f %d %f 1 ", width, hfp, hsp, hbp, height, vfp,vsp, vbp, hz, ip_flag, pixel_clock);
+
+ VCHI_INSTANCE_T vchi_instance;
+ VCHI_CONNECTION_T *vchi_connection = NULL;
+ char buffer[1024];
+
+ vcos_init ();
+
+ vchi_initialise (&vchi_instance);
+
+ vchi_connect (NULL, 0, vchi_instance);
+
+ vc_vchi_gencmd_init (vchi_instance, &vchi_connection, 1);
+
+
+ vc_gencmd (buffer, sizeof (buffer), set_hdmi_timing);
+
+ vc_gencmd_stop ();
+
+ vchi_disconnect (vchi_instance);
+
+ snprintf(output1, sizeof(output1),"tvservice -e \"DMT 87\" > /dev/null");
+ system(output1);
+ snprintf(output2, sizeof(output1),"fbset -g %d %d %d %d 24 > /dev/null",width, height, width, height);
+ system(output2);
+}
+#endif
+
diff --git a/gfx/video_crt_switch.h b/gfx/video_crt_switch.h
index 98cfd4150b..df388ec2ce 100644
--- a/gfx/video_crt_switch.h
+++ b/gfx/video_crt_switch.h
@@ -1,38 +1,38 @@
-/* CRT SwitchRes Core
- * Copyright (C) 2018 Alphanu / Ben Templeman.
- *
- * RetroArch - A frontend for libretro.
- * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
- * Copyright (C) 2011-2017 - Daniel De Matteis
- *
- * 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 .
- */
-
-#ifndef __VIDEO_CRT_SWITCH_H__
-#define __VIDEO_CRT_SWITCH_H__
-
-#include
-
-#include
-#include
-
-RETRO_BEGIN_DECLS
-
-void crt_switch_res_core(unsigned width, unsigned height, float hz, unsigned crt_mode, int crt_switch_center_adjust);
-
-void crt_aspect_ratio_switch(unsigned width, unsigned height);
-
-void crt_video_restore(void);
-
-RETRO_END_DECLS
-
-#endif
+/* CRT SwitchRes Core
+ * Copyright (C) 2018 Alphanu / Ben Templeman.
+ *
+ * RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ *
+ * 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 .
+ */
+
+#ifndef __VIDEO_CRT_SWITCH_H__
+#define __VIDEO_CRT_SWITCH_H__
+
+#include
+
+#include
+#include
+
+RETRO_BEGIN_DECLS
+
+void crt_switch_res_core(unsigned width, unsigned height, float hz, unsigned crt_mode, int crt_switch_center_adjust, int monitor_index);
+
+void crt_aspect_ratio_switch(unsigned width, unsigned height);
+
+void crt_video_restore(void);
+
+RETRO_END_DECLS
+
+#endif
diff --git a/gfx/video_display_server.c b/gfx/video_display_server.c
index f5f4f917ea..9917de9ddd 100644
--- a/gfx/video_display_server.c
+++ b/gfx/video_display_server.c
@@ -1,112 +1,112 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
- * Copyright (C) 2011-2017 - Daniel De Matteis
- * Copyright (C) 2016-2017 - Brad Parker
- *
- * 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 "video_display_server.h"
-#include "video_driver.h"
-#include "../verbosity.h"
-
-static const video_display_server_t *current_display_server = &dispserv_null;
-static void *current_display_server_data = NULL;
-
-const char *video_display_server_get_ident(void)
-{
- if (!current_display_server)
- return "null";
- return current_display_server->ident;
-}
-
-void* video_display_server_init(void)
-{
- enum rarch_display_type type = video_driver_display_type_get();
-
- video_display_server_destroy();
-
- switch (type)
- {
- case RARCH_DISPLAY_WIN32:
-#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
- current_display_server = &dispserv_win32;
-#endif
- break;
- case RARCH_DISPLAY_X11:
-#if defined(HAVE_X11)
- current_display_server = &dispserv_x11;
-#endif
- break;
- default:
- current_display_server = &dispserv_null;
- break;
- }
-
- current_display_server_data = current_display_server->init();
-
- RARCH_LOG("[Video]: Found display server: %s\n",
- current_display_server->ident);
-
- return current_display_server_data;
-}
-
-void video_display_server_destroy(void)
-{
- if (current_display_server && current_display_server->destroy)
- if (current_display_server_data)
- current_display_server->destroy(current_display_server_data);
-}
-
-bool video_display_server_set_window_opacity(unsigned opacity)
-{
- if (current_display_server && current_display_server->set_window_opacity)
- return current_display_server->set_window_opacity(current_display_server_data, opacity);
- return false;
-}
-
-bool video_display_server_set_window_progress(int progress, bool finished)
-{
- if (current_display_server && current_display_server->set_window_progress)
- return current_display_server->set_window_progress(current_display_server_data, progress, finished);
- return false;
-}
-
-bool video_display_server_set_window_decorations(bool on)
-{
- if (current_display_server && current_display_server->set_window_decorations)
- return current_display_server->set_window_decorations(current_display_server_data, on);
- return false;
-}
-
-bool video_display_server_set_resolution(unsigned width, unsigned height,
- int int_hz, float hz, int center)
-{
- if (current_display_server && current_display_server->set_resolution)
- return current_display_server->set_resolution(current_display_server_data, width, height, int_hz, hz, center);
- return false;
-}
-
-void *video_display_server_get_resolution_list(unsigned *size)
-{
- if (current_display_server && current_display_server->get_resolution_list)
- return current_display_server->get_resolution_list(current_display_server_data, size);
- return NULL;
-}
-
-const char *video_display_server_get_output_options(void)
-{
- if (current_display_server && current_display_server->get_output_options)
- return current_display_server->get_output_options(current_display_server_data);
- return NULL;
-}
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ * Copyright (C) 2016-2017 - Brad Parker
+ *
+ * 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 "video_display_server.h"
+#include "video_driver.h"
+#include "../verbosity.h"
+
+static const video_display_server_t *current_display_server = &dispserv_null;
+static void *current_display_server_data = NULL;
+
+const char *video_display_server_get_ident(void)
+{
+ if (!current_display_server)
+ return "null";
+ return current_display_server->ident;
+}
+
+void* video_display_server_init(void)
+{
+ enum rarch_display_type type = video_driver_display_type_get();
+
+ video_display_server_destroy();
+
+ switch (type)
+ {
+ case RARCH_DISPLAY_WIN32:
+#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
+ current_display_server = &dispserv_win32;
+#endif
+ break;
+ case RARCH_DISPLAY_X11:
+#if defined(HAVE_X11)
+ current_display_server = &dispserv_x11;
+#endif
+ break;
+ default:
+ current_display_server = &dispserv_null;
+ break;
+ }
+
+ current_display_server_data = current_display_server->init();
+
+ RARCH_LOG("[Video]: Found display server: %s\n",
+ current_display_server->ident);
+
+ return current_display_server_data;
+}
+
+void video_display_server_destroy(void)
+{
+ if (current_display_server && current_display_server->destroy)
+ if (current_display_server_data)
+ current_display_server->destroy(current_display_server_data);
+}
+
+bool video_display_server_set_window_opacity(unsigned opacity)
+{
+ if (current_display_server && current_display_server->set_window_opacity)
+ return current_display_server->set_window_opacity(current_display_server_data, opacity);
+ return false;
+}
+
+bool video_display_server_set_window_progress(int progress, bool finished)
+{
+ if (current_display_server && current_display_server->set_window_progress)
+ return current_display_server->set_window_progress(current_display_server_data, progress, finished);
+ return false;
+}
+
+bool video_display_server_set_window_decorations(bool on)
+{
+ if (current_display_server && current_display_server->set_window_decorations)
+ return current_display_server->set_window_decorations(current_display_server_data, on);
+ return false;
+}
+
+bool video_display_server_set_resolution(unsigned width, unsigned height,
+ int int_hz, float hz, int center, int monitor_index)
+{
+ if (current_display_server && current_display_server->set_resolution)
+ return current_display_server->set_resolution(current_display_server_data, width, height, int_hz, hz, center, monitor_index);
+ return false;
+}
+
+void *video_display_server_get_resolution_list(unsigned *size)
+{
+ if (current_display_server && current_display_server->get_resolution_list)
+ return current_display_server->get_resolution_list(current_display_server_data, size);
+ return NULL;
+}
+
+const char *video_display_server_get_output_options(void)
+{
+ if (current_display_server && current_display_server->get_output_options)
+ return current_display_server->get_output_options(current_display_server_data);
+ return NULL;
+}
diff --git a/gfx/video_display_server.h b/gfx/video_display_server.h
index 2824b4b4ee..d3c990ca85 100644
--- a/gfx/video_display_server.h
+++ b/gfx/video_display_server.h
@@ -1,77 +1,77 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
- * Copyright (C) 2011-2017 - Daniel De Matteis
- * Copyright (C) 2016-2017 - Brad Parker
- *
- * 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 .
- */
-
-#ifndef __VIDEO_DISPLAY_SERVER__H
-#define __VIDEO_DISPLAY_SERVER__H
-
-#include
-#include
-
-RETRO_BEGIN_DECLS
-
-typedef struct video_display_config
-{
- unsigned width;
- unsigned height;
- unsigned bpp;
- unsigned refreshrate;
- unsigned idx;
- bool current;
-} video_display_config_t;
-
-typedef struct video_display_server
-{
- void *(*init)(void);
- void (*destroy)(void *data);
- bool (*set_window_opacity)(void *data, unsigned opacity);
- bool (*set_window_progress)(void *data, int progress, bool finished);
- bool (*set_window_decorations)(void *data, bool on);
- bool (*set_resolution)(void *data, unsigned width,
- unsigned height, int int_hz, float hz, int center);
- void *(*get_resolution_list)(void *data,
- unsigned *size);
- const char *(*get_output_options)(void *data);
- const char *ident;
-} video_display_server_t;
-
-void* video_display_server_init(void);
-
-void video_display_server_destroy(void);
-
-bool video_display_server_set_window_opacity(unsigned opacity);
-
-bool video_display_server_set_window_progress(int progress, bool finished);
-
-bool video_display_server_set_window_decorations(bool on);
-
-bool video_display_server_set_resolution(
- unsigned width, unsigned height,
- int int_hz, float hz, int center);
-
-void *video_display_server_get_resolution_list(unsigned *size);
-
-const char *video_display_server_get_output_options(void);
-
-const char *video_display_server_get_ident(void);
-
-extern const video_display_server_t dispserv_win32;
-extern const video_display_server_t dispserv_x11;
-extern const video_display_server_t dispserv_null;
-
-RETRO_END_DECLS
-
-#endif
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ * Copyright (C) 2016-2017 - Brad Parker
+ *
+ * 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 .
+ */
+
+#ifndef __VIDEO_DISPLAY_SERVER__H
+#define __VIDEO_DISPLAY_SERVER__H
+
+#include
+#include
+
+RETRO_BEGIN_DECLS
+
+typedef struct video_display_config
+{
+ unsigned width;
+ unsigned height;
+ unsigned bpp;
+ unsigned refreshrate;
+ unsigned idx;
+ bool current;
+} video_display_config_t;
+
+typedef struct video_display_server
+{
+ void *(*init)(void);
+ void (*destroy)(void *data);
+ bool (*set_window_opacity)(void *data, unsigned opacity);
+ bool (*set_window_progress)(void *data, int progress, bool finished);
+ bool (*set_window_decorations)(void *data, bool on);
+ bool (*set_resolution)(void *data, unsigned width,
+ unsigned height, int int_hz, float hz, int center, int monitor_index);
+ void *(*get_resolution_list)(void *data,
+ unsigned *size);
+ const char *(*get_output_options)(void *data);
+ const char *ident;
+} video_display_server_t;
+
+void* video_display_server_init(void);
+
+void video_display_server_destroy(void);
+
+bool video_display_server_set_window_opacity(unsigned opacity);
+
+bool video_display_server_set_window_progress(int progress, bool finished);
+
+bool video_display_server_set_window_decorations(bool on);
+
+bool video_display_server_set_resolution(
+ unsigned width, unsigned height,
+ int int_hz, float hz, int center, int monitor_index);
+
+void *video_display_server_get_resolution_list(unsigned *size);
+
+const char *video_display_server_get_output_options(void);
+
+const char *video_display_server_get_ident(void);
+
+extern const video_display_server_t dispserv_win32;
+extern const video_display_server_t dispserv_x11;
+extern const video_display_server_t dispserv_null;
+
+RETRO_END_DECLS
+
+#endif
diff --git a/gfx/video_driver.c b/gfx/video_driver.c
index 3e05c64d70..f3a9bb5096 100644
--- a/gfx/video_driver.c
+++ b/gfx/video_driver.c
@@ -1,3778 +1,3783 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
- * Copyright (C) 2011-2017 - Daniel De Matteis
- *
- * 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
-#include
-#include
-#include
-
-#include "../audio/audio_driver.h"
-#include "../menu/menu_shader.h"
-
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-#include "../dynamic.h"
-
-#ifdef HAVE_THREADS
-#include
-#endif
-
-#ifdef HAVE_MENU
-#include "../menu/menu_driver.h"
-#include "../menu/menu_setting.h"
-#endif
-
-#include "video_thread_wrapper.h"
-#include "video_driver.h"
-#include "video_display_server.h"
-#include "video_crt_switch.h"
-
-#include "../frontend/frontend_driver.h"
-#include "../record/record_driver.h"
-#include "../config.def.h"
-#include "../configuration.h"
-#include "../driver.h"
-#include "../retroarch.h"
-#include "../input/input_driver.h"
-#include "../list_special.h"
-#include "../core.h"
-#include "../command.h"
-#include "../msg_hash.h"
-#include "../verbosity.h"
-
-#define MEASURE_FRAME_TIME_SAMPLES_COUNT (2 * 1024)
-
-#define TIME_TO_FPS(last_time, new_time, frames) ((1000000.0f * (frames)) / ((new_time) - (last_time)))
-
-#define FPS_UPDATE_INTERVAL 256
-
-#ifdef HAVE_THREADS
-#define video_driver_is_threaded_internal() ((!video_driver_is_hw_context() && video_driver_threaded) ? true : false)
-#else
-#define video_driver_is_threaded_internal() (false)
-#endif
-
-#ifdef HAVE_THREADS
-#define video_driver_lock() \
- if (display_lock) \
- slock_lock(display_lock)
-
-#define video_driver_unlock() \
- if (display_lock) \
- slock_unlock(display_lock)
-
-#define video_driver_context_lock() \
- if (context_lock) \
- slock_lock(context_lock)
-
-#define video_driver_context_unlock() \
- if (context_lock) \
- slock_unlock(context_lock)
-
-#define video_driver_lock_free() \
- slock_free(display_lock); \
- slock_free(context_lock); \
- display_lock = NULL; \
- context_lock = NULL
-
-#define video_driver_threaded_lock(is_threaded) \
- if (is_threaded) \
- video_driver_lock()
-
-#define video_driver_threaded_unlock(is_threaded) \
- if (is_threaded) \
- video_driver_unlock()
-#else
-#define video_driver_lock() ((void)0)
-#define video_driver_unlock() ((void)0)
-#define video_driver_lock_free() ((void)0)
-#define video_driver_threaded_lock(is_threaded) ((void)0)
-#define video_driver_threaded_unlock(is_threaded) ((void)0)
-#define video_driver_context_lock() ((void)0)
-#define video_driver_context_unlock() ((void)0)
-#endif
-
-typedef struct video_pixel_scaler
-{
- struct scaler_ctx *scaler;
- void *scaler_out;
-} video_pixel_scaler_t;
-
-static void (*video_driver_cb_shader_use)(void *data,
- void *shader_data, unsigned index, bool set_active);
-static bool (*video_driver_cb_shader_set_mvp)(void *data,
- void *shader_data, const void *mat_data);
-bool (*video_driver_cb_has_focus)(void);
-
-/* Opaque handles to currently running window.
- * Used by e.g. input drivers which bind to a window.
- * Drivers are responsible for setting these if an input driver
- * could potentially make use of this. */
-static uintptr_t video_driver_display = 0;
-static uintptr_t video_driver_window = 0;
-
-static rarch_softfilter_t *video_driver_state_filter = NULL;
-static void *video_driver_state_buffer = NULL;
-static unsigned video_driver_state_scale = 0;
-static unsigned video_driver_state_out_bpp = 0;
-static bool video_driver_state_out_rgb32 = false;
-static bool video_driver_crt_switching_active = false;
-
-static struct retro_system_av_info video_driver_av_info;
-
-static enum retro_pixel_format video_driver_pix_fmt = RETRO_PIXEL_FORMAT_0RGB1555;
-
-static const void *frame_cache_data = NULL;
-static unsigned frame_cache_width = 0;
-static unsigned frame_cache_height = 0;
-static size_t frame_cache_pitch = 0;
-static bool video_driver_threaded = false;
-
-static float video_driver_core_hz = 0.0f;
-static float video_driver_aspect_ratio = 0.0f;
-static unsigned video_driver_width = 0;
-static unsigned video_driver_height = 0;
-
-static enum rarch_display_type video_driver_display_type = RARCH_DISPLAY_NONE;
-static char video_driver_title_buf[64] = {0};
-static char video_driver_window_title[512] = {0};
-static bool video_driver_window_title_update = true;
-
-static retro_time_t video_driver_frame_time_samples[MEASURE_FRAME_TIME_SAMPLES_COUNT];
-static uint64_t video_driver_frame_time_count = 0;
-static uint64_t video_driver_frame_count = 0;
-
-static void *video_driver_data = NULL;
-static video_driver_t *current_video = NULL;
-
-/* Interface for "poking". */
-static const video_poke_interface_t *video_driver_poke = NULL;
-
-/* Used for 15-bit -> 16-bit conversions that take place before
- * being passed to video driver. */
-static video_pixel_scaler_t *video_driver_scaler_ptr = NULL;
-
-static struct retro_hw_render_callback hw_render;
-
-static const struct
-retro_hw_render_context_negotiation_interface *
-hw_render_context_negotiation = NULL;
-
-/* Graphics driver requires RGBA byte order data (ABGR on little-endian)
- * for 32-bit.
- * This takes effect for overlay and shader cores that wants to load
- * data into graphics driver. Kinda hackish to place it here, it is only
- * used for GLES.
- * TODO: Refactor this better. */
-static bool video_driver_use_rgba = false;
-static bool video_driver_data_own = false;
-static bool video_driver_active = false;
-
-static video_driver_frame_t frame_bak = NULL;
-
-/* If set during context deinit, the driver should keep
- * graphics context alive to avoid having to reset all
- * context state. */
-static bool video_driver_cache_context = false;
-
-/* Set to true by driver if context caching succeeded. */
-static bool video_driver_cache_context_ack = false;
-static uint8_t *video_driver_record_gpu_buffer = NULL;
-
-#ifdef HAVE_THREADS
-static slock_t *display_lock = NULL;
-static slock_t *context_lock = NULL;
-#endif
-
-static gfx_ctx_driver_t current_video_context;
-
-static void *video_context_data = NULL;
-
-/**
- * dynamic.c:dynamic_request_hw_context will try to set flag data when the context
- * is in the middle of being rebuilt; in these cases we will save flag
- * data and set this to true.
- * When the context is reinit, it checks this, reads from
- * deferred_flag_data and cleans it.
- *
- * TODO - Dirty hack, fix it better
- */
-static bool deferred_video_context_driver_set_flags = false;
-static gfx_ctx_flags_t deferred_flag_data = {0};
-
-static bool video_started_fullscreen = false;
-
-static shader_backend_t *current_shader = NULL;
-static void *current_shader_data = NULL;
-
-struct aspect_ratio_elem aspectratio_lut[ASPECT_RATIO_END] = {
- { "4:3", 1.3333f },
- { "16:9", 1.7778f },
- { "16:10", 1.6f },
- { "16:15", 16.0f / 15.0f },
- { "21:9", 21.0f / 9.0f },
- { "1:1", 1.0f },
- { "2:1", 2.0f },
- { "3:2", 1.5f },
- { "3:4", 0.75f },
- { "4:1", 4.0f },
- { "9:16", 0.5625f },
- { "5:4", 1.25f },
- { "6:5", 1.2f },
- { "7:9", 0.7777f },
- { "8:3", 2.6666f },
- { "8:7", 1.1428f },
- { "19:12", 1.5833f },
- { "19:14", 1.3571f },
- { "30:17", 1.7647f },
- { "32:9", 3.5555f },
- { "Config", 0.0f },
- { "Square pixel", 1.0f },
- { "Core provided", 1.0f },
- { "Custom", 0.0f }
-};
-
-static const video_driver_t *video_drivers[] = {
-#ifdef HAVE_OPENGL
- &video_gl,
-#endif
-#ifdef HAVE_VULKAN
- &video_vulkan,
-#endif
-#ifdef HAVE_METAL
- &video_metal,
-#endif
-#ifdef XENON
- &video_xenon360,
-#endif
-#if defined(HAVE_D3D12)
- &video_d3d12,
-#endif
-#if defined(HAVE_D3D11)
- &video_d3d11,
-#endif
-#if defined(HAVE_D3D10)
- &video_d3d10,
-#endif
-#if defined(HAVE_D3D9)
- &video_d3d9,
-#endif
-#if defined(HAVE_D3D8)
- &video_d3d8,
-#endif
-#ifdef HAVE_VITA2D
- &video_vita2d,
-#endif
-#ifdef PSP
- &video_psp1,
-#endif
-#ifdef PS2
- &video_ps2,
-#endif
-#ifdef _3DS
- &video_ctr,
-#endif
-#ifdef SWITCH
- &video_switch,
-#endif
-#ifdef HAVE_SDL
- &video_sdl,
-#endif
-#ifdef HAVE_SDL2
- &video_sdl2,
-#endif
-#ifdef HAVE_XVIDEO
- &video_xvideo,
-#endif
-#ifdef GEKKO
- &video_gx,
-#endif
-#ifdef WIIU
- &video_wiiu,
-#endif
-#ifdef HAVE_VG
- &video_vg,
-#endif
-#ifdef HAVE_OMAP
- &video_omap,
-#endif
-#ifdef HAVE_EXYNOS
- &video_exynos,
-#endif
-#ifdef HAVE_DISPMANX
- &video_dispmanx,
-#endif
-#ifdef HAVE_SUNXI
- &video_sunxi,
-#endif
-#ifdef HAVE_PLAIN_DRM
- &video_drm,
-#endif
-#ifdef HAVE_XSHM
- &video_xshm,
-#endif
-#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
- &video_gdi,
-#endif
-#ifdef DJGPP
- &video_vga,
-#endif
-#ifdef HAVE_SIXEL
- &video_sixel,
-#endif
-#ifdef HAVE_CACA
- &video_caca,
-#endif
- &video_null,
- NULL,
-};
-
-static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
-#if defined(ORBIS)
- &orbis_ctx,
-#endif
-#if defined(HAVE_LIBNX) && defined(HAVE_OPENGL)
- &switch_ctx,
-#endif
-#if defined(__CELLOS_LV2__)
- &gfx_ctx_ps3,
-#endif
-#if defined(HAVE_VIDEOCORE)
- &gfx_ctx_videocore,
-#endif
-#if defined(HAVE_MALI_FBDEV)
- &gfx_ctx_mali_fbdev,
-#endif
-#if defined(HAVE_VIVANTE_FBDEV)
- &gfx_ctx_vivante_fbdev,
-#endif
-#if defined(HAVE_OPENDINGUX_FBDEV)
- &gfx_ctx_opendingux_fbdev,
-#endif
-#if defined(_WIN32) && (defined(HAVE_OPENGL) || defined(HAVE_VULKAN))
- &gfx_ctx_wgl,
-#endif
-#if defined(HAVE_WAYLAND)
- &gfx_ctx_wayland,
-#endif
-#if defined(HAVE_X11) && !defined(HAVE_OPENGLES)
-#if defined(HAVE_OPENGL) || defined(HAVE_VULKAN)
- &gfx_ctx_x,
-#endif
-#endif
-#if defined(HAVE_X11) && defined(HAVE_OPENGL) && defined(HAVE_EGL)
- &gfx_ctx_x_egl,
-#endif
-#if defined(HAVE_KMS)
- &gfx_ctx_drm,
-#endif
-#if defined(ANDROID)
- &gfx_ctx_android,
-#endif
-#if defined(__QNX__)
- &gfx_ctx_qnx,
-#endif
-#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)
- &gfx_ctx_cocoagl,
-#endif
-#if defined(__APPLE__) && !defined(TARGET_IPHONE_SIMULATOR) && !defined(TARGET_OS_IPHONE)
- &gfx_ctx_cgl,
-#endif
-#if (defined(HAVE_SDL) || defined(HAVE_SDL2)) && defined(HAVE_OPENGL)
- &gfx_ctx_sdl_gl,
-#endif
-#ifdef HAVE_OSMESA
- &gfx_ctx_osmesa,
-#endif
-#ifdef EMSCRIPTEN
- &gfx_ctx_emscripten,
-#endif
-#if defined(HAVE_VULKAN) && defined(HAVE_VULKAN_DISPLAY)
- &gfx_ctx_khr_display,
-#endif
-#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
- &gfx_ctx_gdi,
-#endif
-#ifdef HAVE_SIXEL
- &gfx_ctx_sixel,
-#endif
- &gfx_ctx_null,
- NULL
-};
-
-static const shader_backend_t *shader_ctx_drivers[] = {
-#ifdef HAVE_GLSL
- &gl_glsl_backend,
-#endif
-#ifdef HAVE_CG
- &gl_cg_backend,
-#endif
- &shader_null_backend,
- NULL
-};
-
-bool video_driver_started_fullscreen(void)
-{
- return video_started_fullscreen;
-}
-
-/* Stub functions */
-
-static void update_window_title_null(void *data, void *data2)
-{
-}
-
-static void swap_buffers_null(void *data, void *data2)
-{
-}
-
-static bool get_metrics_null(void *data, enum display_metric_types type,
- float *value)
-{
- return false;
-}
-
-static bool set_resize_null(void *a, unsigned b, unsigned c)
-{
- return false;
-}
-
-/**
- * video_driver_find_handle:
- * @idx : index of driver to get handle to.
- *
- * Returns: handle to video driver at index. Can be NULL
- * if nothing found.
- **/
-const void *video_driver_find_handle(int idx)
-{
- const void *drv = video_drivers[idx];
- if (!drv)
- return NULL;
- return drv;
-}
-
-/**
- * video_driver_find_ident:
- * @idx : index of driver to get handle to.
- *
- * Returns: Human-readable identifier of video driver at index. Can be NULL
- * if nothing found.
- **/
-const char *video_driver_find_ident(int idx)
-{
- const video_driver_t *drv = video_drivers[idx];
- if (!drv)
- return NULL;
- return drv->ident;
-}
-
-/**
- * config_get_video_driver_options:
- *
- * Get an enumerated list of all video driver names, separated by '|'.
- *
- * Returns: string listing of all video driver names, separated by '|'.
- **/
-const char* config_get_video_driver_options(void)
-{
- return char_list_new_special(STRING_LIST_VIDEO_DRIVERS, NULL);
-}
-
-bool video_driver_is_threaded(void)
-{
- return video_driver_is_threaded_internal();
-}
-
-#ifdef HAVE_VULKAN
-static bool hw_render_context_is_vulkan(enum retro_hw_context_type type)
-{
- return type == RETRO_HW_CONTEXT_VULKAN;
-}
-#endif
-
-#if defined(HAVE_OPENGL)
-static bool hw_render_context_is_gl(enum retro_hw_context_type type)
-{
- switch (type)
- {
- case RETRO_HW_CONTEXT_OPENGL:
- case RETRO_HW_CONTEXT_OPENGLES2:
- case RETRO_HW_CONTEXT_OPENGL_CORE:
- case RETRO_HW_CONTEXT_OPENGLES3:
- case RETRO_HW_CONTEXT_OPENGLES_VERSION:
- return true;
- default:
- break;
- }
-
- return false;
-}
-#endif
-
-bool *video_driver_get_threaded(void)
-{
- return &video_driver_threaded;
-}
-
-void video_driver_set_threaded(bool val)
-{
- video_driver_threaded = val;
-}
-
-/**
- * video_driver_get_ptr:
- *
- * Use this if you need the real video driver
- * and driver data pointers.
- *
- * Returns: video driver's userdata.
- **/
-void *video_driver_get_ptr(bool force_nonthreaded_data)
-{
-#ifdef HAVE_THREADS
- if (video_driver_is_threaded_internal() && !force_nonthreaded_data)
- return video_thread_get_ptr(NULL);
-#endif
-
- return video_driver_data;
-}
-
-const char *video_driver_get_ident(void)
-{
- return (current_video) ? current_video->ident : NULL;
-}
-
-const video_poke_interface_t *video_driver_get_poke(void)
-{
- return video_driver_poke;
-}
-
-static bool video_context_has_focus(void)
-{
- return current_video_context.has_focus && current_video_context.has_focus(video_context_data);
-}
-
-static bool video_driver_has_focus(void)
-{
- return current_video && current_video->focus && current_video->focus(video_driver_data);
-}
-
-static bool null_driver_has_focus(void)
-{
- return true;
-}
-
-static void video_context_driver_reset(void)
-{
- if (!current_video_context.get_metrics)
- current_video_context.get_metrics = get_metrics_null;
-
- if (!current_video_context.update_window_title)
- current_video_context.update_window_title = update_window_title_null;
-
- if (!current_video_context.set_resize)
- current_video_context.set_resize = set_resize_null;
-
- if (!current_video_context.swap_buffers)
- current_video_context.swap_buffers = swap_buffers_null;
-
- if (current_video_context.has_focus)
- video_driver_cb_has_focus = video_context_has_focus;
-
-}
-
-bool video_context_driver_set(const gfx_ctx_driver_t *data)
-{
- if (!data)
- return false;
- current_video_context = *data;
- video_context_driver_reset();
- return true;
-}
-
-void video_context_driver_destroy(void)
-{
- current_video_context.init = NULL;
- current_video_context.bind_api = NULL;
- current_video_context.swap_interval = NULL;
- current_video_context.set_video_mode = NULL;
- current_video_context.get_video_size = NULL;
- current_video_context.get_video_output_size = NULL;
- current_video_context.get_video_output_prev = NULL;
- current_video_context.get_video_output_next = NULL;
- current_video_context.get_metrics = get_metrics_null;
- current_video_context.translate_aspect = NULL;
- current_video_context.update_window_title = update_window_title_null;
- current_video_context.check_window = NULL;
- current_video_context.set_resize = set_resize_null;
- current_video_context.has_focus = NULL;
- current_video_context.suppress_screensaver = NULL;
- current_video_context.has_windowed = NULL;
- current_video_context.swap_buffers = swap_buffers_null;
- current_video_context.input_driver = NULL;
- current_video_context.get_proc_address = NULL;
- current_video_context.image_buffer_init = NULL;
- current_video_context.image_buffer_write = NULL;
- current_video_context.show_mouse = NULL;
- current_video_context.ident = NULL;
- current_video_context.get_flags = NULL;
- current_video_context.set_flags = NULL;
- current_video_context.bind_hw_render = NULL;
- current_video_context.get_context_data = NULL;
- current_video_context.make_current = NULL;
-}
-
-/**
- * video_driver_get_current_framebuffer:
- *
- * Gets pointer to current hardware renderer framebuffer object.
- * Used by RETRO_ENVIRONMENT_SET_HW_RENDER.
- *
- * Returns: pointer to hardware framebuffer object, otherwise 0.
- **/
-uintptr_t video_driver_get_current_framebuffer(void)
-{
- if (video_driver_poke && video_driver_poke->get_current_framebuffer)
- return video_driver_poke->get_current_framebuffer(video_driver_data);
- return 0;
-}
-
-retro_proc_address_t video_driver_get_proc_address(const char *sym)
-{
- if (video_driver_poke && video_driver_poke->get_proc_address)
- return video_driver_poke->get_proc_address(video_driver_data, sym);
- return NULL;
-}
-
-bool video_driver_set_shader(enum rarch_shader_type type,
- const char *path)
-{
- if (current_video->set_shader)
- return current_video->set_shader(video_driver_data, type, path);
- return false;
-}
-
-static void video_driver_filter_free(void)
-{
- if (video_driver_state_filter)
- rarch_softfilter_free(video_driver_state_filter);
- video_driver_state_filter = NULL;
-
- if (video_driver_state_buffer)
- {
-#ifdef _3DS
- linearFree(video_driver_state_buffer);
-#else
- free(video_driver_state_buffer);
-#endif
- }
- video_driver_state_buffer = NULL;
-
- video_driver_state_scale = 0;
- video_driver_state_out_bpp = 0;
- video_driver_state_out_rgb32 = false;
-}
-
-static void video_driver_init_filter(enum retro_pixel_format colfmt_int)
-{
- unsigned pow2_x, pow2_y, maxsize;
- void *buf = NULL;
- settings_t *settings = config_get_ptr();
- struct retro_game_geometry *geom = &video_driver_av_info.geometry;
- unsigned width = geom->max_width;
- unsigned height = geom->max_height;
- /* Deprecated format. Gets pre-converted. */
- enum retro_pixel_format colfmt =
- (colfmt_int == RETRO_PIXEL_FORMAT_0RGB1555) ?
- RETRO_PIXEL_FORMAT_RGB565 : colfmt_int;
-
- if (video_driver_is_hw_context())
- {
- RARCH_WARN("Cannot use CPU filters when hardware rendering is used.\n");
- return;
- }
-
- video_driver_state_filter = rarch_softfilter_new(
- settings->paths.path_softfilter_plugin,
- RARCH_SOFTFILTER_THREADS_AUTO, colfmt, width, height);
-
- if (!video_driver_state_filter)
- {
- RARCH_ERR("[Video]: Failed to load filter.\n");
- return;
- }
-
- rarch_softfilter_get_max_output_size(video_driver_state_filter,
- &width, &height);
-
- pow2_x = next_pow2(width);
- pow2_y = next_pow2(height);
- maxsize = MAX(pow2_x, pow2_y);
- video_driver_state_scale = maxsize / RARCH_SCALE_BASE;
- video_driver_state_out_rgb32 = rarch_softfilter_get_output_format(
- video_driver_state_filter) ==
- RETRO_PIXEL_FORMAT_XRGB8888;
-
- video_driver_state_out_bpp = video_driver_state_out_rgb32 ?
- sizeof(uint32_t) :
- sizeof(uint16_t);
-
- /* TODO: Aligned output. */
-#ifdef _3DS
- buf = linearMemAlign(
- width * height * video_driver_state_out_bpp, 0x80);
-#else
- buf = malloc(
- width * height * video_driver_state_out_bpp);
-#endif
- if (!buf)
- {
- RARCH_ERR("[Video]: Softfilter initialization failed.\n");
- video_driver_filter_free();
- return;
- }
-
- video_driver_state_buffer = buf;
-}
-
-static void video_driver_init_input(const input_driver_t *tmp)
-{
- const input_driver_t **input = input_get_double_ptr();
- if (*input)
- return;
-
- /* Video driver didn't provide an input driver,
- * so we use configured one. */
- RARCH_LOG("[Video]: Graphics driver did not initialize an input driver."
- " Attempting to pick a suitable driver.\n");
-
- if (tmp)
- *input = tmp;
- else
- input_driver_find_driver();
-
- /* This should never really happen as tmp (driver.input) is always
- * found before this in find_driver_input(), or we have aborted
- * in a similar fashion anyways. */
- if (!input_get_ptr())
- goto error;
-
- if (input_driver_init())
- return;
-
-error:
- RARCH_ERR("[Video]: Cannot initialize input driver. Exiting ...\n");
- retroarch_fail(1, "video_driver_init_input()");
-}
-
-/**
- * video_driver_monitor_compute_fps_statistics:
- *
- * Computes monitor FPS statistics.
- **/
-static void video_driver_monitor_compute_fps_statistics(void)
-{
- double avg_fps = 0.0;
- double stddev = 0.0;
- unsigned samples = 0;
-
- if (video_driver_frame_time_count <
- (2 * MEASURE_FRAME_TIME_SAMPLES_COUNT))
- {
- RARCH_LOG(
- "[Video]: Does not have enough samples for monitor refresh rate"
- " estimation. Requires to run for at least %u frames.\n",
- 2 * MEASURE_FRAME_TIME_SAMPLES_COUNT);
- return;
- }
-
- if (video_monitor_fps_statistics(&avg_fps, &stddev, &samples))
- {
- RARCH_LOG("[Video]: Average monitor Hz: %.6f Hz. (%.3f %% frame time"
- " deviation, based on %u last samples).\n",
- avg_fps, 100.0 * stddev, samples);
- }
-}
-
-static void video_driver_pixel_converter_free(void)
-{
- if (!video_driver_scaler_ptr)
- return;
-
- scaler_ctx_gen_reset(video_driver_scaler_ptr->scaler);
-
- if (video_driver_scaler_ptr->scaler)
- free(video_driver_scaler_ptr->scaler);
- video_driver_scaler_ptr->scaler = NULL;
-
- if (video_driver_scaler_ptr->scaler_out)
- free(video_driver_scaler_ptr->scaler_out);
- video_driver_scaler_ptr->scaler_out = NULL;
-
- if (video_driver_scaler_ptr)
- free(video_driver_scaler_ptr);
- video_driver_scaler_ptr = NULL;
-}
-
-static void video_driver_free_internal(void)
-{
-#ifdef HAVE_THREADS
- bool is_threaded = video_driver_is_threaded_internal();
-#endif
-
- command_event(CMD_EVENT_OVERLAY_DEINIT, NULL);
-
- if (!video_driver_is_video_cache_context())
- video_driver_free_hw_context();
-
- if (
- !input_driver_owns_driver() &&
- !input_driver_is_data_ptr_same(video_driver_data)
- )
- input_driver_deinit();
-
- if (
- !video_driver_data_own
- && video_driver_data
- && current_video && current_video->free
- )
- current_video->free(video_driver_data);
-
- video_driver_pixel_converter_free();
- video_driver_filter_free();
-
- command_event(CMD_EVENT_SHADER_DIR_DEINIT, NULL);
-
-#ifdef HAVE_THREADS
- if (is_threaded)
- return;
-#endif
-
- video_driver_monitor_compute_fps_statistics();
-}
-
-static bool video_driver_pixel_converter_init(unsigned size)
-{
- struct retro_hw_render_callback *hwr =
- video_driver_get_hw_context();
- void *scalr_out = NULL;
- video_pixel_scaler_t *scalr = NULL;
- struct scaler_ctx *scalr_ctx = NULL;
-
- /* If pixel format is not 0RGB1555, we don't need to do
- * any internal pixel conversion. */
- if (video_driver_pix_fmt != RETRO_PIXEL_FORMAT_0RGB1555)
- return true;
-
- /* No need to perform pixel conversion for HW rendering contexts. */
- if (hwr && hwr->context_type != RETRO_HW_CONTEXT_NONE)
- return true;
-
- RARCH_WARN("0RGB1555 pixel format is deprecated,"
- " and will be slower. For 15/16-bit, RGB565"
- " format is preferred.\n");
-
- scalr = (video_pixel_scaler_t*)calloc(1, sizeof(*scalr));
-
- if (!scalr)
- goto error;
-
- video_driver_scaler_ptr = scalr;
-
- scalr_ctx = (struct scaler_ctx*)calloc(1, sizeof(*scalr_ctx));
-
- if (!scalr_ctx)
- goto error;
-
- video_driver_scaler_ptr->scaler = scalr_ctx;
- video_driver_scaler_ptr->scaler->scaler_type = SCALER_TYPE_POINT;
- video_driver_scaler_ptr->scaler->in_fmt = SCALER_FMT_0RGB1555;
-
- /* TODO: Pick either ARGB8888 or RGB565 depending on driver. */
- video_driver_scaler_ptr->scaler->out_fmt = SCALER_FMT_RGB565;
-
- if (!scaler_ctx_gen_filter(scalr_ctx))
- goto error;
-
- scalr_out = calloc(sizeof(uint16_t), size * size);
-
- if (!scalr_out)
- goto error;
-
- video_driver_scaler_ptr->scaler_out = scalr_out;
-
- return true;
-
-error:
- video_driver_pixel_converter_free();
- video_driver_filter_free();
-
- return false;
-}
-
-static bool video_driver_init_internal(bool *video_is_threaded)
-{
- video_info_t video;
- unsigned max_dim, scale, width, height;
- video_viewport_t *custom_vp = NULL;
- const input_driver_t *tmp = NULL;
- rarch_system_info_t *system = NULL;
- static uint16_t dummy_pixels[32] = {0};
- settings_t *settings = config_get_ptr();
- struct retro_game_geometry *geom = &video_driver_av_info.geometry;
-
- if (!string_is_empty(settings->paths.path_softfilter_plugin))
- video_driver_init_filter(video_driver_pix_fmt);
-
- max_dim = MAX(geom->max_width, geom->max_height);
- scale = next_pow2(max_dim) / RARCH_SCALE_BASE;
- scale = MAX(scale, 1);
-
- if (video_driver_state_filter)
- scale = video_driver_state_scale;
-
- /* Update core-dependent aspect ratio values. */
- video_driver_set_viewport_square_pixel();
- video_driver_set_viewport_core();
- video_driver_set_viewport_config();
-
- /* Update CUSTOM viewport. */
- custom_vp = video_viewport_get_custom();
-
- if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
- {
- float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value;
- aspectratio_lut[ASPECT_RATIO_CUSTOM].value =
- (custom_vp->width && custom_vp->height) ?
- (float)custom_vp->width / custom_vp->height : default_aspect;
- }
-
- video_driver_set_aspect_ratio_value(
- aspectratio_lut[settings->uints.video_aspect_ratio_idx].value);
-
- if (settings->bools.video_fullscreen|| retroarch_is_forced_fullscreen())
- {
- width = settings->uints.video_fullscreen_x;
- height = settings->uints.video_fullscreen_y;
- }
- else
- {
- /* To-Do: remove when the new window resizing core is hooked */
- if (settings->bools.video_window_save_positions &&
- (settings->uints.window_position_width || settings->uints.window_position_height))
- {
- width = settings->uints.window_position_width;
- height = settings->uints.window_position_height;
- }
- else
- {
- if (settings->bools.video_force_aspect)
- {
- /* Do rounding here to simplify integer scale correctness. */
- unsigned base_width =
- roundf(geom->base_height * video_driver_get_aspect_ratio());
- width = roundf(base_width * settings->floats.video_scale);
- }
- else
- width = roundf(geom->base_width * settings->floats.video_scale);
- height = roundf(geom->base_height * settings->floats.video_scale);
-}
- }
-
- if (width && height)
- RARCH_LOG("[Video]: Video @ %ux%u\n", width, height);
- else
- RARCH_LOG("[Video]: Video @ fullscreen\n");
-
- video_driver_display_type_set(RARCH_DISPLAY_NONE);
- video_driver_display_set(0);
- video_driver_window_set(0);
-
- if (!video_driver_pixel_converter_init(RARCH_SCALE_BASE * scale))
- {
- RARCH_ERR("[Video]: Failed to initialize pixel converter.\n");
- goto error;
- }
-
- video.width = width;
- video.height = height;
- video.fullscreen = settings->bools.video_fullscreen || retroarch_is_forced_fullscreen();
- video.vsync = settings->bools.video_vsync && !rarch_ctl(RARCH_CTL_IS_NONBLOCK_FORCED, NULL);
- video.force_aspect = settings->bools.video_force_aspect;
- video.font_enable = settings->bools.video_font_enable;
- video.swap_interval = settings->uints.video_swap_interval;
-#ifdef GEKKO
- video.viwidth = settings->uints.video_viwidth;
- video.vfilter = settings->bools.video_vfilter;
-#endif
- video.smooth = settings->bools.video_smooth;
- video.input_scale = scale;
- video.rgb32 = video_driver_state_filter ?
- video_driver_state_out_rgb32 :
- (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
- video.parent = 0;
-
- video_started_fullscreen = video.fullscreen;
-
- /* Reset video frame count */
- video_driver_frame_count = 0;
-
- tmp = input_get_ptr();
- /* Need to grab the "real" video driver interface on a reinit. */
- video_driver_find_driver();
-
-#ifdef HAVE_THREADS
- video.is_threaded = video_driver_is_threaded_internal();
- *video_is_threaded = video.is_threaded;
-
- if (video.is_threaded)
- {
- /* Can't do hardware rendering with threaded driver currently. */
- RARCH_LOG("[Video]: Starting threaded video driver ...\n");
-
- if (!video_init_thread((const video_driver_t**)¤t_video,
- &video_driver_data,
- input_get_double_ptr(), input_driver_get_data_ptr(),
- current_video, video))
- {
- RARCH_ERR("[Video]: Cannot open threaded video driver ... Exiting ...\n");
- goto error;
- }
- }
- else
-#endif
- video_driver_data = current_video->init(
- &video, input_get_double_ptr(),
- input_driver_get_data_ptr());
-
- if (!video_driver_data)
- {
- RARCH_ERR("[Video]: Cannot open video driver ... Exiting ...\n");
- goto error;
- }
-
- if (current_video->focus)
- video_driver_cb_has_focus = video_driver_has_focus;
-
- video_driver_poke = NULL;
- if (current_video->poke_interface)
- current_video->poke_interface(video_driver_data, &video_driver_poke);
-
- if (current_video->viewport_info &&
- (!custom_vp->width ||
- !custom_vp->height))
- {
- /* Force custom viewport to have sane parameters. */
- custom_vp->width = width;
- custom_vp->height = height;
-
- video_driver_get_viewport_info(custom_vp);
- }
-
- system = runloop_get_system_info();
-
- video_driver_set_rotation(
- (settings->uints.video_rotation + system->rotation) % 4);
-
- current_video->suppress_screensaver(video_driver_data,
- settings->bools.ui_suspend_screensaver_enable);
-
- video_driver_init_input(tmp);
-
- command_event(CMD_EVENT_OVERLAY_DEINIT, NULL);
- command_event(CMD_EVENT_OVERLAY_INIT, NULL);
-
- if (!core_is_game_loaded())
- video_driver_cached_frame_set(&dummy_pixels, 4, 4, 8);
-
-#if defined(PSP)
- video_driver_set_texture_frame(&dummy_pixels, false, 1, 1, 1.0f);
-#endif
-
- video_context_driver_reset();
-
- video_display_server_init();
-
- command_event(CMD_EVENT_SHADER_DIR_INIT, NULL);
-
- return true;
-
-error:
- retroarch_fail(1, "init_video()");
- return false;
-}
-
-bool video_driver_set_viewport(unsigned width, unsigned height,
- bool force_fullscreen, bool allow_rotate)
-{
- if (!current_video || !current_video->set_viewport)
- return false;
- current_video->set_viewport(video_driver_data, width, height,
- force_fullscreen, allow_rotate);
- return true;
-}
-
-bool video_driver_set_rotation(unsigned rotation)
-{
- if (!current_video || !current_video->set_rotation)
- return false;
- current_video->set_rotation(video_driver_data, rotation);
- return true;
-}
-
-bool video_driver_set_video_mode(unsigned width,
- unsigned height, bool fullscreen)
-{
- gfx_ctx_mode_t mode;
-
- if (video_driver_poke && video_driver_poke->set_video_mode)
- {
- video_driver_poke->set_video_mode(video_driver_data,
- width, height, fullscreen);
- return true;
- }
-
- mode.width = width;
- mode.height = height;
- mode.fullscreen = fullscreen;
-
- return video_context_driver_set_video_mode(&mode);
-}
-
-bool video_driver_get_video_output_size(unsigned *width, unsigned *height)
-{
- if (!video_driver_poke || !video_driver_poke->get_video_output_size)
- return false;
- video_driver_poke->get_video_output_size(video_driver_data,
- width, height);
- return true;
-}
-
-void video_driver_set_osd_msg(const char *msg, const void *data, void *font)
-{
- video_frame_info_t video_info;
- video_driver_build_info(&video_info);
- if (video_driver_poke && video_driver_poke->set_osd_msg)
- video_driver_poke->set_osd_msg(video_driver_data, &video_info, msg, data, font);
-}
-
-void video_driver_set_texture_enable(bool enable, bool fullscreen)
-{
- if (video_driver_poke && video_driver_poke->set_texture_enable)
- video_driver_poke->set_texture_enable(video_driver_data,
- enable, fullscreen);
-}
-
-void video_driver_set_texture_frame(const void *frame, bool rgb32,
- unsigned width, unsigned height, float alpha)
-{
- if (video_driver_poke && video_driver_poke->set_texture_frame)
- video_driver_poke->set_texture_frame(video_driver_data,
- frame, rgb32, width, height, alpha);
-}
-
-#ifdef HAVE_OVERLAY
-bool video_driver_overlay_interface(const video_overlay_interface_t **iface)
-{
- if (!current_video || !current_video->overlay_interface)
- return false;
- current_video->overlay_interface(video_driver_data, iface);
- return true;
-}
-#endif
-
-void *video_driver_read_frame_raw(unsigned *width,
- unsigned *height, size_t *pitch)
-{
- if (!current_video || !current_video->read_frame_raw)
- return NULL;
- return current_video->read_frame_raw(video_driver_data, width,
- height, pitch);
-}
-
-void video_driver_set_filtering(unsigned index, bool smooth)
-{
- if (video_driver_poke && video_driver_poke->set_filtering)
- video_driver_poke->set_filtering(video_driver_data, index, smooth);
-}
-
-void video_driver_cached_frame_set(const void *data, unsigned width,
- unsigned height, size_t pitch)
-{
- if (data)
- frame_cache_data = data;
- frame_cache_width = width;
- frame_cache_height = height;
- frame_cache_pitch = pitch;
-}
-
-void video_driver_cached_frame_get(const void **data, unsigned *width,
- unsigned *height, size_t *pitch)
-{
- if (data)
- *data = frame_cache_data;
- if (width)
- *width = frame_cache_width;
- if (height)
- *height = frame_cache_height;
- if (pitch)
- *pitch = frame_cache_pitch;
-}
-
-void video_driver_get_size(unsigned *width, unsigned *height)
-{
-#ifdef HAVE_THREADS
- bool is_threaded = video_driver_is_threaded_internal();
- video_driver_threaded_lock(is_threaded);
-#endif
- if (width)
- *width = video_driver_width;
- if (height)
- *height = video_driver_height;
-#ifdef HAVE_THREADS
- video_driver_threaded_unlock(is_threaded);
-#endif
-}
-
-void video_driver_set_size(unsigned *width, unsigned *height)
-{
-#ifdef HAVE_THREADS
- bool is_threaded = video_driver_is_threaded_internal();
- video_driver_threaded_lock(is_threaded);
-#endif
- if (width)
- video_driver_width = *width;
- if (height)
- video_driver_height = *height;
-#ifdef HAVE_THREADS
- video_driver_threaded_unlock(is_threaded);
-#endif
-}
-
-/**
- * video_monitor_set_refresh_rate:
- * @hz : New refresh rate for monitor.
- *
- * Sets monitor refresh rate to new value.
- **/
-void video_monitor_set_refresh_rate(float hz)
-{
- char msg[128];
- settings_t *settings = config_get_ptr();
-
- snprintf(msg, sizeof(msg),
- "Setting refresh rate to: %.3f Hz.", hz);
- runloop_msg_queue_push(msg, 1, 180, false);
- RARCH_LOG("%s\n", msg);
-
- configuration_set_float(settings,
- settings->floats.video_refresh_rate,
- hz);
-}
-
-/**
- * video_monitor_fps_statistics
- * @refresh_rate : Monitor refresh rate.
- * @deviation : Deviation from measured refresh rate.
- * @sample_points : Amount of sampled points.
- *
- * Gets the monitor FPS statistics based on the current
- * runtime.
- *
- * Returns: true (1) on success.
- * false (0) if:
- * a) threaded video mode is enabled
- * b) less than 2 frame time samples.
- * c) FPS monitor enable is off.
- **/
-bool video_monitor_fps_statistics(double *refresh_rate,
- double *deviation, unsigned *sample_points)
-{
- unsigned i;
- retro_time_t accum = 0;
- retro_time_t avg = 0;
- retro_time_t accum_var = 0;
- unsigned samples = 0;
-
-#ifdef HAVE_THREADS
- if (video_driver_is_threaded_internal())
- return false;
-#endif
-
- samples = MIN(MEASURE_FRAME_TIME_SAMPLES_COUNT,
- (unsigned)video_driver_frame_time_count);
-
- if (samples < 2)
- return false;
-
- /* Measure statistics on frame time (microsecs), *not* FPS. */
- for (i = 0; i < samples; i++)
- {
- accum += video_driver_frame_time_samples[i];
-#if 0
- RARCH_LOG("[Video]: Interval #%u: %d usec / frame.\n",
- i, (int)frame_time_samples[i]);
-#endif
- }
-
- avg = accum / samples;
-
- /* Drop first measurement. It is likely to be bad. */
- for (i = 0; i < samples; i++)
- {
- retro_time_t diff = video_driver_frame_time_samples[i] - avg;
- accum_var += diff * diff;
- }
-
- *deviation = sqrt((double)accum_var / (samples - 1)) / avg;
-
- if (refresh_rate)
- *refresh_rate = 1000000.0 / avg;
-
- if (sample_points)
- *sample_points = samples;
-
- return true;
-}
-
-float video_driver_get_aspect_ratio(void)
-{
- return video_driver_aspect_ratio;
-}
-
-void video_driver_set_aspect_ratio_value(float value)
-{
- video_driver_aspect_ratio = value;
-}
-
-static bool video_driver_frame_filter(
- const void *data,
- video_frame_info_t *video_info,
- unsigned width, unsigned height,
- size_t pitch,
- unsigned *output_width, unsigned *output_height,
- unsigned *output_pitch)
-{
- rarch_softfilter_get_output_size(video_driver_state_filter,
- output_width, output_height, width, height);
-
- *output_pitch = (*output_width) * video_driver_state_out_bpp;
-
- rarch_softfilter_process(video_driver_state_filter,
- video_driver_state_buffer, *output_pitch,
- data, width, height, pitch);
-
- if (video_info->post_filter_record && recording_data)
- recording_dump_frame(video_driver_state_buffer,
- *output_width, *output_height, *output_pitch,
- video_info->runloop_is_idle);
-
- return true;
-}
-
-rarch_softfilter_t *video_driver_frame_filter_get_ptr(void)
-{
- return video_driver_state_filter;
-}
-
-enum retro_pixel_format video_driver_get_pixel_format(void)
-{
- return video_driver_pix_fmt;
-}
-
-void video_driver_set_pixel_format(enum retro_pixel_format fmt)
-{
- video_driver_pix_fmt = fmt;
-}
-
-/**
- * video_driver_cached_frame:
- *
- * Renders the current video frame.
- **/
-bool video_driver_cached_frame(void)
-{
- void *recording = recording_driver_get_data_ptr();
-
- recording_driver_lock();
-
- /* Cannot allow recording when pushing duped frames. */
- recording_data = NULL;
-
- retro_ctx.frame_cb(
- (frame_cache_data != RETRO_HW_FRAME_BUFFER_VALID)
- ? frame_cache_data : NULL,
- frame_cache_width,
- frame_cache_height, frame_cache_pitch);
-
- recording_data = recording;
-
- recording_driver_unlock();
-
- return true;
-}
-
-void video_driver_monitor_adjust_system_rates(void)
-{
- float timing_skew = 0.0f;
- settings_t *settings = config_get_ptr();
- float video_refresh_rate = settings->floats.video_refresh_rate;
- float timing_skew_hz = video_refresh_rate;
- const struct retro_system_timing *info = (const struct retro_system_timing*)&video_driver_av_info.timing;
-
- rarch_ctl(RARCH_CTL_UNSET_NONBLOCK_FORCED, NULL);
-
- if (!info || info->fps <= 0.0)
- return;
-
- video_driver_core_hz = info->fps;
-
- if (video_driver_crt_switching_active)
- timing_skew_hz = video_driver_core_hz;
- timing_skew = fabs(
- 1.0f - info->fps / timing_skew_hz);
-
- if (!settings->bools.vrr_runloop_enable)
- {
- /* We don't want to adjust pitch too much. If we have extreme cases,
- * just don't readjust at all. */
- if (timing_skew <= settings->floats.audio_max_timing_skew)
- return;
-
- RARCH_LOG("[Video]: Timings deviate too much. Will not adjust."
- " (Display = %.2f Hz, Game = %.2f Hz)\n",
- video_refresh_rate,
- (float)info->fps);
- }
-
- if (info->fps <= timing_skew_hz)
- return;
-
- /* We won't be able to do VSync reliably when game FPS > monitor FPS. */
- rarch_ctl(RARCH_CTL_SET_NONBLOCK_FORCED, NULL);
- RARCH_LOG("[Video]: Game FPS > Monitor FPS. Cannot rely on VSync.\n");
-}
-
-void video_driver_menu_settings(void **list_data, void *list_info_data,
- void *group_data, void *subgroup_data, const char *parent_group)
-{
-#ifdef HAVE_MENU
- rarch_setting_t **list = (rarch_setting_t**)list_data;
- rarch_setting_info_t *list_info = (rarch_setting_info_t*)list_info_data;
- rarch_setting_group_info_t *group_info = (rarch_setting_group_info_t*)group_data;
- rarch_setting_group_info_t *subgroup_info = (rarch_setting_group_info_t*)subgroup_data;
- global_t *global = global_get_ptr();
-
- (void)list;
- (void)list_info;
- (void)group_info;
- (void)subgroup_info;
- (void)global;
-
-#if defined(__CELLOS_LV2__)
- CONFIG_BOOL(
- list, list_info,
- &global->console.screen.pal60_enable,
- MENU_ENUM_LABEL_PAL60_ENABLE,
- MENU_ENUM_LABEL_VALUE_PAL60_ENABLE,
- 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);
-#endif
-#if defined(GEKKO) || defined(_XBOX360)
- CONFIG_UINT(
- list, list_info,
- &global->console.screen.gamma_correction,
- MENU_ENUM_LABEL_VIDEO_GAMMA,
- MENU_ENUM_LABEL_VALUE_VIDEO_GAMMA,
- 0,
- group_info,
- subgroup_info,
- parent_group,
- general_write_handler,
- general_read_handler);
- menu_settings_list_current_add_cmd(
- list,
- list_info,
- CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
- menu_settings_list_current_add_range(
- list,
- list_info,
- 0,
- MAX_GAMMA_SETTING,
- 1,
- true,
- true);
- settings_data_list_current_add_flags(list, list_info,
- SD_FLAG_CMD_APPLY_AUTO|SD_FLAG_ADVANCED);
-#endif
-#if defined(_XBOX1) || defined(HW_RVL)
- CONFIG_BOOL(
- list, list_info,
- &global->console.softfilter_enable,
- MENU_ENUM_LABEL_VIDEO_SOFT_FILTER,
- MENU_ENUM_LABEL_VALUE_VIDEO_SOFT_FILTER,
- 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);
- menu_settings_list_current_add_cmd(
- list,
- list_info,
- CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
-#endif
-#ifdef _XBOX1
- CONFIG_UINT(
- list, list_info,
- &global->console.screen.flicker_filter_index,
- MENU_ENUM_LABEL_VIDEO_FILTER_FLICKER,
- MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_FLICKER,
- 0,
- group_info,
- subgroup_info,
- parent_group,
- general_write_handler,
- general_read_handler);
- menu_settings_list_current_add_range(list, list_info,
- 0, 5, 1, true, true);
-#endif
-#endif
-}
-
-static void video_driver_lock_new(void)
-{
- video_driver_lock_free();
-#ifdef HAVE_THREADS
- if (!display_lock)
- display_lock = slock_new();
- retro_assert(display_lock);
-
- if (!context_lock)
- context_lock = slock_new();
- retro_assert(context_lock);
-#endif
-}
-
-void video_driver_destroy(void)
-{
- video_display_server_destroy();
- crt_video_restore();
-
- video_driver_cb_has_focus = null_driver_has_focus;
- video_driver_use_rgba = false;
- video_driver_data_own = false;
- video_driver_active = false;
- video_driver_cache_context = false;
- video_driver_cache_context_ack = false;
- video_driver_record_gpu_buffer = NULL;
- current_video = NULL;
- video_driver_set_cached_frame_ptr(NULL);
-}
-
-void video_driver_set_cached_frame_ptr(const void *data)
-{
- if (data)
- frame_cache_data = data;
-}
-
-void video_driver_set_stub_frame(void)
-{
- frame_bak = current_video->frame;
- current_video->frame = video_null.frame;
-}
-
-void video_driver_unset_stub_frame(void)
-{
- if (frame_bak != NULL)
- current_video->frame = frame_bak;
-
- frame_bak = NULL;
-}
-
-bool video_driver_is_stub_frame(void)
-{
- return current_video->frame == video_null.frame;
-}
-
-bool video_driver_supports_recording(void)
-{
- settings_t *settings = config_get_ptr();
- return settings->bools.video_gpu_record
- && current_video->read_viewport;
-}
-
-bool video_driver_supports_viewport_read(void)
-{
- settings_t *settings = config_get_ptr();
- return (settings->bools.video_gpu_screenshot ||
- (video_driver_is_hw_context() && !current_video->read_frame_raw))
- && current_video->read_viewport && current_video->viewport_info;
-}
-
-bool video_driver_supports_read_frame_raw(void)
-{
- if (current_video->read_frame_raw)
- return true;
- return false;
-}
-
-void video_driver_set_viewport_config(void)
-{
- settings_t *settings = config_get_ptr();
-
- if (settings->floats.video_aspect_ratio < 0.0f)
- {
- struct retro_game_geometry *geom = &video_driver_av_info.geometry;
-
- if (geom->aspect_ratio > 0.0f &&
- settings->bools.video_aspect_ratio_auto)
- aspectratio_lut[ASPECT_RATIO_CONFIG].value = geom->aspect_ratio;
- else
- {
- unsigned base_width = geom->base_width;
- unsigned base_height = geom->base_height;
-
- /* Get around division by zero errors */
- if (base_width == 0)
- base_width = 1;
- if (base_height == 0)
- base_height = 1;
- aspectratio_lut[ASPECT_RATIO_CONFIG].value =
- (float)base_width / base_height; /* 1:1 PAR. */
- }
- }
- else
- {
- aspectratio_lut[ASPECT_RATIO_CONFIG].value =
- settings->floats.video_aspect_ratio;
- }
-}
-
-void video_driver_set_viewport_square_pixel(void)
-{
- unsigned len, highest, i, aspect_x, aspect_y;
- struct retro_game_geometry *geom = &video_driver_av_info.geometry;
- unsigned width = geom->base_width;
- unsigned height = geom->base_height;
-
- if (width == 0 || height == 0)
- return;
-
- len = MIN(width, height);
- highest = 1;
-
- for (i = 1; i < len; i++)
- {
- if ((width % i) == 0 && (height % i) == 0)
- highest = i;
- }
-
- aspect_x = width / highest;
- aspect_y = height / highest;
-
- snprintf(aspectratio_lut[ASPECT_RATIO_SQUARE].name,
- sizeof(aspectratio_lut[ASPECT_RATIO_SQUARE].name),
- "1:1 PAR (%u:%u DAR)", aspect_x, aspect_y);
-
- aspectratio_lut[ASPECT_RATIO_SQUARE].value = (float)aspect_x / aspect_y;
-}
-
-void video_driver_set_viewport_core(void)
-{
- struct retro_game_geometry *geom = &video_driver_av_info.geometry;
-
- if (!geom || geom->base_width <= 0.0f || geom->base_height <= 0.0f)
- return;
-
- /* Fallback to 1:1 pixel ratio if none provided */
- if (geom->aspect_ratio > 0.0f)
- aspectratio_lut[ASPECT_RATIO_CORE].value = geom->aspect_ratio;
- else
- aspectratio_lut[ASPECT_RATIO_CORE].value =
- (float)geom->base_width / geom->base_height;
-}
-
-void video_driver_reset_custom_viewport(void)
-{
- struct video_viewport *custom_vp = video_viewport_get_custom();
-
- custom_vp->width = 0;
- custom_vp->height = 0;
- custom_vp->x = 0;
- custom_vp->y = 0;
-}
-
-void video_driver_set_rgba(void)
-{
- video_driver_lock();
- video_driver_use_rgba = true;
- video_driver_unlock();
-}
-
-void video_driver_unset_rgba(void)
-{
- video_driver_lock();
- video_driver_use_rgba = false;
- video_driver_unlock();
-}
-
-bool video_driver_supports_rgba(void)
-{
- bool tmp;
- video_driver_lock();
- tmp = video_driver_use_rgba;
- video_driver_unlock();
- return tmp;
-}
-
-bool video_driver_get_next_video_out(void)
-{
- if (!video_driver_poke)
- return false;
-
- if (!video_driver_poke->get_video_output_next)
- return video_context_driver_get_video_output_next();
- video_driver_poke->get_video_output_next(video_driver_data);
- return true;
-}
-
-bool video_driver_get_prev_video_out(void)
-{
- if (!video_driver_poke)
- return false;
-
- if (!video_driver_poke->get_video_output_prev)
- return video_context_driver_get_video_output_prev();
- video_driver_poke->get_video_output_prev(video_driver_data);
- return true;
-}
-
-bool video_driver_init(bool *video_is_threaded)
-{
- video_driver_lock_new();
- video_driver_filter_free();
- video_driver_set_cached_frame_ptr(NULL);
- return video_driver_init_internal(video_is_threaded);
-}
-
-void video_driver_destroy_data(void)
-{
- video_driver_data = NULL;
-}
-
-void video_driver_free(void)
-{
- video_driver_free_internal();
- video_driver_lock_free();
- video_driver_data = NULL;
- video_driver_set_cached_frame_ptr(NULL);
-}
-
-void video_driver_monitor_reset(void)
-{
- video_driver_frame_time_count = 0;
-}
-
-void video_driver_set_aspect_ratio(void)
-{
- settings_t *settings = config_get_ptr();
-
- switch (settings->uints.video_aspect_ratio_idx)
- {
- case ASPECT_RATIO_SQUARE:
- video_driver_set_viewport_square_pixel();
- break;
-
- case ASPECT_RATIO_CORE:
- video_driver_set_viewport_core();
- break;
-
- case ASPECT_RATIO_CONFIG:
- video_driver_set_viewport_config();
- break;
-
- default:
- break;
- }
-
- video_driver_set_aspect_ratio_value(
- aspectratio_lut[settings->uints.video_aspect_ratio_idx].value);
-
- if (!video_driver_poke || !video_driver_poke->set_aspect_ratio)
- return;
- video_driver_poke->set_aspect_ratio(
- video_driver_data, settings->uints.video_aspect_ratio_idx);
-}
-
-void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bool keep_aspect)
-{
- gfx_ctx_aspect_t aspect_data;
- float device_aspect = (float)vp->full_width / vp->full_height;
- settings_t* settings = config_get_ptr();
-
- aspect_data.aspect = &device_aspect;
- aspect_data.width = vp->full_width;
- aspect_data.height = vp->full_height;
-
- video_context_driver_translate_aspect(&aspect_data);
-
- vp->x = 0;
- vp->y = 0;
- vp->width = vp->full_width;
- vp->height = vp->full_height;
-
- if (settings->bools.video_scale_integer && !force_full)
- {
- video_viewport_get_scaled_integer(
- vp, vp->full_width, vp->full_height, video_driver_get_aspect_ratio(), keep_aspect);
- }
- else if (keep_aspect && !force_full)
- {
- float desired_aspect = video_driver_get_aspect_ratio();
-
-#if defined(HAVE_MENU)
- if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
- {
- const struct video_viewport* custom = video_viewport_get_custom();
-
- vp->x = custom->x;
- vp->y = custom->y;
- vp->width = custom->width;
- vp->height = custom->height;
- }
- else
-#endif
- {
- float delta;
-
- 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;
- vp->x = (int)roundf(vp->full_width * (0.5f - delta));
- vp->width = (unsigned)roundf(2.0f * vp->full_width * delta);
- vp->y = 0;
- vp->height = vp->full_height;
- }
- else
- {
- vp->x = 0;
- vp->width = vp->full_width;
- delta = (device_aspect / desired_aspect - 1.0f)
- / 2.0f + 0.5f;
- vp->y = (int)roundf(vp->full_height * (0.5f - delta));
- vp->height = (unsigned)roundf(2.0f * vp->full_height * delta);
- }
- }
- }
-
-#if defined(RARCH_MOBILE)
- /* In portrait mode, we want viewport to gravitate to top of screen. */
- if (device_aspect < 1.0f)
- vp->y = 0;
-#endif
-}
-
-void video_driver_show_mouse(void)
-{
- if (video_driver_poke && video_driver_poke->show_mouse)
- video_driver_poke->show_mouse(video_driver_data, true);
-}
-
-void video_driver_hide_mouse(void)
-{
- if (video_driver_poke && video_driver_poke->show_mouse)
- video_driver_poke->show_mouse(video_driver_data, false);
-}
-
-void video_driver_set_nonblock_state(bool toggle)
-{
- if (current_video->set_nonblock_state)
- current_video->set_nonblock_state(video_driver_data, toggle);
-}
-
-bool video_driver_find_driver(void)
-{
- int i;
- driver_ctx_info_t drv;
- settings_t *settings = config_get_ptr();
-
- if (video_driver_is_hw_context())
- {
- struct retro_hw_render_callback *hwr = video_driver_get_hw_context();
-
- current_video = NULL;
-
- (void)hwr;
-
-#if defined(HAVE_VULKAN)
- if (hwr && hw_render_context_is_vulkan(hwr->context_type))
- {
- RARCH_LOG("[Video]: Using HW render, Vulkan driver forced.\n");
- current_video = &video_vulkan;
- }
-#endif
-
-#if defined(HAVE_OPENGL)
- if (hwr && hw_render_context_is_gl(hwr->context_type))
- {
- RARCH_LOG("[Video]: Using HW render, OpenGL driver forced.\n");
- current_video = &video_gl;
- }
-#endif
-
- if (current_video)
- return true;
- }
-
- if (frontend_driver_has_get_video_driver_func())
- {
- current_video = (video_driver_t*)frontend_driver_get_video_driver();
-
- if (current_video)
- return true;
- RARCH_WARN("Frontend supports get_video_driver() but did not specify one.\n");
- }
-
- drv.label = "video_driver";
- drv.s = settings->arrays.video_driver;
-
- driver_ctl(RARCH_DRIVER_CTL_FIND_INDEX, &drv);
-
- i = (int)drv.len;
-
- if (i >= 0)
- current_video = (video_driver_t*)video_driver_find_handle(i);
- else
- {
- if (verbosity_is_enabled())
- {
- unsigned d;
- RARCH_ERR("Couldn't find any video driver named \"%s\"\n",
- settings->arrays.video_driver);
- RARCH_LOG_OUTPUT("Available video drivers are:\n");
- for (d = 0; video_driver_find_handle(d); d++)
- RARCH_LOG_OUTPUT("\t%s\n", video_driver_find_ident(d));
- RARCH_WARN("Going to default to first video driver...\n");
- }
-
- current_video = (video_driver_t*)video_driver_find_handle(0);
-
- if (!current_video)
- retroarch_fail(1, "find_video_driver()");
- }
- return true;
-}
-
-void video_driver_apply_state_changes(void)
-{
- if (video_driver_poke &&
- video_driver_poke->apply_state_changes)
- video_driver_poke->apply_state_changes(video_driver_data);
-}
-
-bool video_driver_read_viewport(uint8_t *buffer, bool is_idle)
-{
- if ( current_video->read_viewport
- && current_video->read_viewport(
- video_driver_data, buffer, is_idle))
- return true;
- return false;
-}
-
-bool video_driver_frame_filter_alive(void)
-{
- return !!video_driver_state_filter;
-}
-
-bool video_driver_frame_filter_is_32bit(void)
-{
- return video_driver_state_out_rgb32;
-}
-
-void video_driver_default_settings(void)
-{
- global_t *global = global_get_ptr();
-
- if (!global)
- return;
-
- global->console.screen.gamma_correction = DEFAULT_GAMMA;
- global->console.flickerfilter_enable = false;
- global->console.softfilter_enable = false;
-
- global->console.screen.resolutions.current.id = 0;
-}
-
-void video_driver_load_settings(config_file_t *conf)
-{
- bool tmp_bool = false;
- global_t *global = global_get_ptr();
-
- if (!conf)
- return;
-
-#ifdef _XBOX
- CONFIG_GET_BOOL_BASE(conf, global,
- console.screen.gamma_correction, "gamma_correction");
-#else
- CONFIG_GET_INT_BASE(conf, global,
- console.screen.gamma_correction, "gamma_correction");
-#endif
-
- if (config_get_bool(conf, "flicker_filter_enable",
- &tmp_bool))
- global->console.flickerfilter_enable = tmp_bool;
-
- if (config_get_bool(conf, "soft_filter_enable",
- &tmp_bool))
- global->console.softfilter_enable = tmp_bool;
-
- CONFIG_GET_INT_BASE(conf, global,
- console.screen.soft_filter_index,
- "soft_filter_index");
- CONFIG_GET_INT_BASE(conf, global,
- console.screen.resolutions.current.id,
- "current_resolution_id");
- CONFIG_GET_INT_BASE(conf, global,
- console.screen.flicker_filter_index,
- "flicker_filter_index");
-}
-
-void video_driver_save_settings(config_file_t *conf)
-{
- global_t *global = global_get_ptr();
- if (!conf)
- return;
-
-#ifdef _XBOX
- config_set_bool(conf, "gamma_correction",
- global->console.screen.gamma_correction);
-#else
- config_set_int(conf, "gamma_correction",
- global->console.screen.gamma_correction);
-#endif
- config_set_bool(conf, "flicker_filter_enable",
- global->console.flickerfilter_enable);
- config_set_bool(conf, "soft_filter_enable",
- global->console.softfilter_enable);
-
- config_set_int(conf, "soft_filter_index",
- global->console.screen.soft_filter_index);
- config_set_int(conf, "current_resolution_id",
- global->console.screen.resolutions.current.id);
- config_set_int(conf, "flicker_filter_index",
- global->console.screen.flicker_filter_index);
-}
-
-void video_driver_reinit(void)
-{
- struct retro_hw_render_callback *hwr =
- video_driver_get_hw_context();
-
- if (hwr->cache_context)
- video_driver_cache_context = true;
- else
- video_driver_cache_context = false;
-
- video_driver_cache_context_ack = false;
- command_event(CMD_EVENT_RESET_CONTEXT, NULL);
- video_driver_cache_context = false;
-}
-
-void video_driver_set_own_driver(void)
-{
- video_driver_data_own = true;
-}
-
-void video_driver_unset_own_driver(void)
-{
- video_driver_data_own = false;
-}
-
-bool video_driver_owns_driver(void)
-{
- return video_driver_data_own;
-}
-
-bool video_driver_is_hw_context(void)
-{
- bool is_hw_context = false;
-
- video_driver_context_lock();
- is_hw_context = (hw_render.context_type != RETRO_HW_CONTEXT_NONE);
- video_driver_context_unlock();
-
- return is_hw_context;
-}
-
-void video_driver_free_hw_context(void)
-{
- video_driver_context_lock();
-
- if (hw_render.context_destroy)
- hw_render.context_destroy();
-
- memset(&hw_render, 0, sizeof(hw_render));
-
- video_driver_context_unlock();
-
- hw_render_context_negotiation = NULL;
-}
-
-struct retro_hw_render_callback *video_driver_get_hw_context(void)
-{
- return &hw_render;
-}
-
-const struct retro_hw_render_context_negotiation_interface *
- video_driver_get_context_negotiation_interface(void)
-{
- return hw_render_context_negotiation;
-}
-
-void video_driver_set_context_negotiation_interface(
- const struct retro_hw_render_context_negotiation_interface *iface)
-{
- hw_render_context_negotiation = iface;
-}
-
-bool video_driver_is_video_cache_context(void)
-{
- return video_driver_cache_context;
-}
-
-void video_driver_set_video_cache_context_ack(void)
-{
- video_driver_cache_context_ack = true;
-}
-
-void video_driver_unset_video_cache_context_ack(void)
-{
- video_driver_cache_context_ack = false;
-}
-
-bool video_driver_is_video_cache_context_ack(void)
-{
- return video_driver_cache_context_ack;
-}
-
-void video_driver_set_active(void)
-{
- video_driver_active = true;
-}
-
-void video_driver_unset_active(void)
-{
- video_driver_active = false;
-}
-
-bool video_driver_is_active(void)
-{
- return video_driver_active;
-}
-
-void video_driver_get_record_status(
- bool *has_gpu_record,
- uint8_t **gpu_buf)
-{
- *gpu_buf = video_driver_record_gpu_buffer;
- *has_gpu_record = video_driver_record_gpu_buffer != NULL;
-}
-
-bool video_driver_gpu_record_init(unsigned size)
-{
- video_driver_record_gpu_buffer = (uint8_t*)malloc(size);
- if (!video_driver_record_gpu_buffer)
- return false;
- return true;
-}
-
-void video_driver_gpu_record_deinit(void)
-{
- free(video_driver_record_gpu_buffer);
- video_driver_record_gpu_buffer = NULL;
-}
-
-bool video_driver_get_current_software_framebuffer(
- struct retro_framebuffer *fb)
-{
- if (
- video_driver_poke
- && video_driver_poke->get_current_software_framebuffer
- && video_driver_poke->get_current_software_framebuffer(
- video_driver_data, fb))
- return true;
-
- return false;
-}
-
-bool video_driver_get_hw_render_interface(
- const struct retro_hw_render_interface **iface)
-{
- if (
- video_driver_poke
- && video_driver_poke->get_hw_render_interface
- && video_driver_poke->get_hw_render_interface(
- video_driver_data, iface))
- return true;
-
- return false;
-}
-
-bool video_driver_get_viewport_info(struct video_viewport *viewport)
-{
- if (!current_video || !current_video->viewport_info)
- return false;
- current_video->viewport_info(video_driver_data, viewport);
- return true;
-}
-
-void video_driver_set_title_buf(void)
-{
- struct retro_system_info info;
- core_get_system_info(&info);
-
- fill_pathname_join_concat_noext(
- video_driver_title_buf,
- msg_hash_to_str(MSG_PROGRAM),
- " ",
- info.library_name,
- sizeof(video_driver_title_buf));
- strlcat(video_driver_title_buf,
- " ", sizeof(video_driver_title_buf));
- strlcat(video_driver_title_buf,
- info.library_version,
- sizeof(video_driver_title_buf));
-}
-
-/**
- * video_viewport_get_scaled_integer:
- * @vp : Viewport handle
- * @width : Width.
- * @height : Height.
- * @aspect_ratio : Aspect ratio (in float).
- * @keep_aspect : Preserve aspect ratio?
- *
- * Gets viewport scaling dimensions based on
- * scaled integer aspect ratio.
- **/
-void video_viewport_get_scaled_integer(struct video_viewport *vp,
- unsigned width, unsigned height,
- float aspect_ratio, bool keep_aspect)
-{
- int padding_x = 0;
- int padding_y = 0;
- settings_t *settings = config_get_ptr();
-
- if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
- {
- struct video_viewport *custom = video_viewport_get_custom();
-
- if (custom)
- {
- padding_x = width - custom->width;
- padding_y = height - custom->height;
- width = custom->width;
- height = custom->height;
- }
- }
- else
- {
- unsigned base_width;
- /* Use system reported sizes as these define the
- * geometry for the "normal" case. */
- unsigned base_height =
- video_driver_av_info.geometry.base_height;
-
- if (base_height == 0)
- base_height = 1;
-
- /* Account for non-square pixels.
- * This is sort of contradictory with the goal of integer scale,
- * but it is desirable in some cases.
- *
- * If square pixels are used, base_height will be equal to
- * system->av_info.base_height. */
- base_width = (unsigned)roundf(base_height * aspect_ratio);
-
- /* Make sure that we don't get 0x scale ... */
- if (width >= base_width && height >= base_height)
- {
- if (keep_aspect)
- {
- /* X/Y scale must be same. */
- unsigned max_scale = MIN(width / base_width,
- height / base_height);
- padding_x = width - base_width * max_scale;
- padding_y = height - base_height * max_scale;
- }
- else
- {
- /* X/Y can be independent, each scaled as much as possible. */
- padding_x = width % base_width;
- padding_y = height % base_height;
- }
- }
-
- width -= padding_x;
- height -= padding_y;
- }
-
- vp->width = width;
- vp->height = height;
- vp->x = padding_x / 2;
- vp->y = padding_y / 2;
-}
-
-struct retro_system_av_info *video_viewport_get_system_av_info(void)
-{
- return &video_driver_av_info;
-}
-
-struct video_viewport *video_viewport_get_custom(void)
-{
- settings_t *settings = config_get_ptr();
- return &settings->video_viewport_custom;
-}
-
-unsigned video_pixel_get_alignment(unsigned pitch)
-{
- if (pitch & 1)
- return 1;
- if (pitch & 2)
- return 2;
- if (pitch & 4)
- return 4;
- return 8;
-}
-
-/**
- * video_driver_frame:
- * @data : pointer to data of the video frame.
- * @width : width of the video frame.
- * @height : height of the video frame.
- * @pitch : pitch of the video frame.
- *
- * Video frame render callback function.
- **/
-void video_driver_frame(const void *data, unsigned width,
- unsigned height, size_t pitch)
-{
- static char video_driver_msg[256];
- static char title[256];
- video_frame_info_t video_info;
- static retro_time_t curr_time;
- static retro_time_t fps_time;
- static float last_fps, frame_time;
- unsigned output_width = 0;
- unsigned output_height = 0;
- unsigned output_pitch = 0;
- const char *msg = NULL;
- retro_time_t new_time =
- cpu_features_get_time_usec();
-
- if (!video_driver_active)
- return;
-
- if (video_driver_scaler_ptr && data &&
- (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555) &&
- (data != RETRO_HW_FRAME_BUFFER_VALID))
- {
- if (video_pixel_frame_scale(
- video_driver_scaler_ptr->scaler,
- video_driver_scaler_ptr->scaler_out,
- data, width, height, pitch))
- {
- data = video_driver_scaler_ptr->scaler_out;
- pitch = video_driver_scaler_ptr->scaler->out_stride;
- }
- }
-
- if (data)
- frame_cache_data = data;
- frame_cache_width = width;
- frame_cache_height = height;
- frame_cache_pitch = pitch;
-
- video_driver_build_info(&video_info);
-
- /* Get the amount of frames per seconds. */
- if (video_driver_frame_count)
- {
- unsigned write_index =
- video_driver_frame_time_count++ &
- (MEASURE_FRAME_TIME_SAMPLES_COUNT - 1);
- frame_time = new_time - fps_time;
- video_driver_frame_time_samples[write_index] = frame_time;
- fps_time = new_time;
-
- if (video_driver_frame_count == 1)
- strlcpy(title, video_driver_window_title, sizeof(title));
-
- if ((video_driver_frame_count % FPS_UPDATE_INTERVAL) == 0)
- {
- char frames_text[64];
- last_fps = TIME_TO_FPS(curr_time, new_time, FPS_UPDATE_INTERVAL);
-
- if (video_info.fps_show || video_info.framecount_show)
- {
- if (video_info.fps_show)
- {
- snprintf(video_info.fps_text, sizeof(video_info.fps_text),
- " || FPS: %6.1f ", last_fps);
- }
- if (video_info.framecount_show)
- {
- snprintf(frames_text,
- sizeof(frames_text),
- " || Frames: %" PRIu64,
- (uint64_t)video_driver_frame_count);
- }
- snprintf(video_driver_window_title, sizeof(video_driver_window_title),
- "%s%s%s", title,
- video_info.fps_show ? video_info.fps_text : "",
- video_info.framecount_show ? frames_text : "");
- }
- else
- {
- if (!string_is_equal(video_driver_window_title, title))
- strlcpy(video_driver_window_title, title, sizeof(video_driver_window_title));
- }
-
- curr_time = new_time;
- video_driver_window_title_update = true;
- }
-
- if (video_info.fps_show)
- {
- if (video_info.framecount_show)
- snprintf(
- video_info.fps_text,
- sizeof(video_info.fps_text),
- "FPS: %6.1f || %s: %" PRIu64,
- last_fps,
- msg_hash_to_str(MSG_FRAMES),
- (uint64_t)video_driver_frame_count);
- else
- snprintf(
- video_info.fps_text,
- sizeof(video_info.fps_text),
- "FPS: %6.1f",
- last_fps);
- }
-
- if (video_info.fps_show && video_info.framecount_show)
- snprintf(
- video_info.fps_text,
- sizeof(video_info.fps_text),
- "FPS: %6.1f || %s: %" PRIu64,
- last_fps,
- msg_hash_to_str(MSG_FRAMES),
- (uint64_t)video_driver_frame_count);
- else if (video_info.framecount_show)
- snprintf(
- video_info.fps_text,
- sizeof(video_info.fps_text),
- "%s: %" PRIu64,
- msg_hash_to_str(MSG_FRAMES),
- (uint64_t)video_driver_frame_count);
- else if (video_info.fps_show)
- snprintf(
- video_info.fps_text,
- sizeof(video_info.fps_text),
- "FPS: %6.1f",
- last_fps);
- }
- else
- {
-
- curr_time = fps_time = new_time;
-
- strlcpy(video_driver_window_title,
- video_driver_title_buf,
- sizeof(video_driver_window_title));
-
- if (video_info.fps_show)
- strlcpy(video_info.fps_text,
- msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
- sizeof(video_info.fps_text));
-
- video_driver_window_title_update = true;
- }
-
- video_info.frame_rate = last_fps;
- video_info.frame_time = frame_time / 1000.0f;
- video_info.frame_count = (uint64_t) video_driver_frame_count;
-
- /* Slightly messy code,
- * but we really need to do processing before blocking on VSync
- * for best possible scheduling.
- */
- if (
- (
- !video_driver_state_filter
- || !video_info.post_filter_record
- || !data
- || video_driver_record_gpu_buffer
- ) && recording_data
- )
- recording_dump_frame(data, width, height,
- pitch, video_info.runloop_is_idle);
-
- if (data && video_driver_state_filter &&
- video_driver_frame_filter(data, &video_info, width, height, pitch,
- &output_width, &output_height, &output_pitch))
- {
- data = video_driver_state_buffer;
- width = output_width;
- height = output_height;
- pitch = output_pitch;
- }
-
- video_driver_msg[0] = '\0';
-
- if ( video_info.font_enable
- && runloop_msg_queue_pull((const char**)&msg)
- && msg)
- {
-#ifdef HAVE_THREADS
- /* the msg pointer may point to data modified by another thread */
- runloop_msg_queue_lock();
-#endif
- strlcpy(video_driver_msg, msg, sizeof(video_driver_msg));
-#ifdef HAVE_THREADS
- runloop_msg_queue_unlock();
-#endif
- }
-
- if (video_info.statistics_show)
- {
- audio_statistics_t audio_stats = {0.0f};
- double stddev = 0.0;
- struct retro_system_av_info *av_info = &video_driver_av_info;
- unsigned red = 255;
- unsigned green = 255;
- unsigned blue = 255;
- unsigned alpha = 255;
-
- video_monitor_fps_statistics(NULL, &stddev, NULL);
-
- video_info.osd_stat_params.x = 0.010f;
- video_info.osd_stat_params.y = 0.950f;
- video_info.osd_stat_params.scale = 1.0f;
- video_info.osd_stat_params.full_screen = true;
- video_info.osd_stat_params.drop_x = -2;
- video_info.osd_stat_params.drop_y = -2;
- video_info.osd_stat_params.drop_mod = 0.3f;
- video_info.osd_stat_params.drop_alpha = 1.0f;
- video_info.osd_stat_params.color = COLOR_ABGR(
- red, green, blue, alpha);
-
- compute_audio_buffer_statistics(&audio_stats);
-
- snprintf(video_info.stat_text,
- sizeof(video_info.stat_text),
- "Video Statistics:\n -Frame rate: %6.2f fps\n -Frame time: %6.2f ms\n -Frame time deviation: %.3f %%\n"
- " -Frame count: %" PRIu64"\n -Viewport: %d x %d x %3.2f\n"
- "Audio Statistics:\n -Average buffer saturation: %.2f %%\n -Standard deviation: %.2f %%\n -Time spent close to underrun: %.2f %%\n -Time spent close to blocking: %.2f %%\n -Sample count: %d\n"
- "Core Geometry:\n -Size: %u x %u\n -Max Size: %u x %u\n -Aspect: %3.2f\nCore Timing:\n -FPS: %3.2f\n -Sample Rate: %6.2f\n",
- video_info.frame_rate,
- video_info.frame_time,
- 100.0 * stddev,
- video_info.frame_count,
- video_info.width,
- video_info.height,
- video_info.refresh_rate,
- audio_stats.average_buffer_saturation,
- audio_stats.std_deviation_percentage,
- audio_stats.close_to_underrun,
- audio_stats.close_to_blocking,
- audio_stats.samples,
- av_info->geometry.base_width,
- av_info->geometry.base_height,
- av_info->geometry.max_width,
- av_info->geometry.max_height,
- av_info->geometry.aspect_ratio,
- av_info->timing.fps,
- av_info->timing.sample_rate);
-
- /* TODO/FIXME - add OSD chat text here */
-#if 0
- snprintf(video_info.chat_text, sizeof(video_info.chat_text),
- "anon: does retroarch netplay have in-game chat?\nradius: I don't know \u2605");
-#endif
- }
-
- video_driver_active = current_video->frame(
- video_driver_data, data, width, height,
- video_driver_frame_count,
- (unsigned)pitch, video_driver_msg, &video_info);
-
- video_driver_frame_count++;
-
- /* Display the FPS, with a higher priority. */
- if (video_info.fps_show || video_info.framecount_show)
- runloop_msg_queue_push(video_info.fps_text, 2, 1, true);
-
- /* trigger set resolution*/
- if (video_info.crt_switch_resolution)
- {
- video_driver_crt_switching_active = true;
-
- if (video_info.crt_switch_resolution_super == 2560)
- width = 2560;
- if (video_info.crt_switch_resolution_super == 3840)
- width = 3840;
- if (video_info.crt_switch_resolution_super == 1920)
- width = 1920;
- crt_switch_res_core(width, height, video_driver_core_hz, video_info.crt_switch_resolution, video_info.crt_switch_center_adjust);
- }
- else if (!video_info.crt_switch_resolution)
- video_driver_crt_switching_active = false;
-
- /* trigger set resolution*/
-}
-
-void video_driver_display_type_set(enum rarch_display_type type)
-{
- video_driver_display_type = type;
-}
-
-uintptr_t video_driver_display_get(void)
-{
- return video_driver_display;
-}
-
-void video_driver_display_set(uintptr_t idx)
-{
- video_driver_display = idx;
-}
-
-enum rarch_display_type video_driver_display_type_get(void)
-{
- return video_driver_display_type;
-}
-
-void video_driver_window_set(uintptr_t idx)
-{
- video_driver_window = idx;
-}
-
-uintptr_t video_driver_window_get(void)
-{
- return video_driver_window;
-}
-
-bool video_driver_texture_load(void *data,
- enum texture_filter_type filter_type,
- uintptr_t *id)
-{
- if (!id || !video_driver_poke || !video_driver_poke->load_texture)
- return false;
-
- *id = video_driver_poke->load_texture(video_driver_data, data,
- video_driver_is_threaded_internal(),
- filter_type);
-
- return true;
-}
-
-bool video_driver_texture_unload(uintptr_t *id)
-{
- if (!video_driver_poke || !video_driver_poke->unload_texture)
- return false;
-
- video_driver_poke->unload_texture(video_driver_data, *id);
- *id = 0;
- return true;
-}
-
-static void video_shader_driver_use_null(void *data,
- void *shader_data, unsigned idx, bool set_active)
-{
- (void)data;
- (void)idx;
- (void)set_active;
-}
-
-static bool video_driver_cb_set_coords(void *handle_data,
- void *shader_data, const struct video_coords *coords)
-{
- video_shader_ctx_coords_t ctx_coords;
- ctx_coords.handle_data = handle_data;
- ctx_coords.data = coords;
-
- video_driver_set_coords(&ctx_coords);
- return true;
-}
-
-void video_driver_build_info(video_frame_info_t *video_info)
-{
- bool is_perfcnt_enable = false;
- bool is_paused = false;
- bool is_idle = false;
- bool is_slowmotion = false;
- settings_t *settings = NULL;
- video_viewport_t *custom_vp = NULL;
- struct retro_hw_render_callback *hwr =
- video_driver_get_hw_context();
-#ifdef HAVE_THREADS
- bool is_threaded = video_driver_is_threaded_internal();
- video_driver_threaded_lock(is_threaded);
-#endif
- settings = config_get_ptr();
- custom_vp = &settings->video_viewport_custom;
- video_info->refresh_rate = settings->floats.video_refresh_rate;
- video_info->crt_switch_resolution = settings->uints.crt_switch_resolution;
- video_info->crt_switch_resolution_super = settings->uints.crt_switch_resolution_super;
- video_info->crt_switch_center_adjust = settings->ints.crt_switch_center_adjust;
- video_info->black_frame_insertion = settings->bools.video_black_frame_insertion;
- video_info->hard_sync = settings->bools.video_hard_sync;
- video_info->hard_sync_frames = settings->uints.video_hard_sync_frames;
- video_info->fps_show = settings->bools.video_fps_show;
- video_info->statistics_show = settings->bools.video_statistics_show;
- video_info->framecount_show = settings->bools.video_framecount_show;
- video_info->scale_integer = settings->bools.video_scale_integer;
- video_info->aspect_ratio_idx = settings->uints.video_aspect_ratio_idx;
- video_info->post_filter_record = settings->bools.video_post_filter_record;
- video_info->input_menu_swap_ok_cancel_buttons = settings->bools.input_menu_swap_ok_cancel_buttons;
- video_info->max_swapchain_images = settings->uints.video_max_swapchain_images;
- video_info->windowed_fullscreen = settings->bools.video_windowed_fullscreen;
- video_info->fullscreen = settings->bools.video_fullscreen || retroarch_is_forced_fullscreen();
- video_info->monitor_index = settings->uints.video_monitor_index;
- video_info->shared_context = settings->bools.video_shared_context;
-
- if (libretro_get_shared_context() && hwr && hwr->context_type != RETRO_HW_CONTEXT_NONE)
- video_info->shared_context = true;
-
- video_info->font_enable = settings->bools.video_font_enable;
- video_info->font_msg_pos_x = settings->floats.video_msg_pos_x;
- video_info->font_msg_pos_y = settings->floats.video_msg_pos_y;
- video_info->font_msg_color_r = settings->floats.video_msg_color_r;
- video_info->font_msg_color_g = settings->floats.video_msg_color_g;
- video_info->font_msg_color_b = settings->floats.video_msg_color_b;
- video_info->custom_vp_x = custom_vp->x;
- video_info->custom_vp_y = custom_vp->y;
- video_info->custom_vp_width = custom_vp->width;
- video_info->custom_vp_height = custom_vp->height;
- video_info->custom_vp_full_width = custom_vp->full_width;
- video_info->custom_vp_full_height = custom_vp->full_height;
-
- video_info->fps_text[0] = '\0';
-
- video_info->width = video_driver_width;
- video_info->height = video_driver_height;
-
- video_info->use_rgba = video_driver_use_rgba;
-
- video_info->libretro_running = false;
- video_info->msg_bgcolor_enable = settings->bools.video_msg_bgcolor_enable;
-
-#ifdef HAVE_MENU
- video_info->menu_is_alive = menu_driver_is_alive();
- video_info->menu_footer_opacity = settings->floats.menu_footer_opacity;
- video_info->menu_header_opacity = settings->floats.menu_header_opacity;
- video_info->materialui_color_theme = settings->uints.menu_materialui_color_theme;
- video_info->ozone_color_theme = settings->uints.menu_ozone_color_theme;
- video_info->menu_shader_pipeline = settings->uints.menu_xmb_shader_pipeline;
- video_info->xmb_theme = settings->uints.menu_xmb_theme;
- video_info->xmb_color_theme = settings->uints.menu_xmb_color_theme;
- video_info->timedate_enable = settings->bools.menu_timedate_enable;
- video_info->battery_level_enable = settings->bools.menu_battery_level_enable;
- video_info->xmb_shadows_enable = settings->bools.menu_xmb_shadows_enable;
- video_info->xmb_alpha_factor = settings->uints.menu_xmb_alpha_factor;
- video_info->menu_wallpaper_opacity = settings->floats.menu_wallpaper_opacity;
- video_info->menu_framebuffer_opacity = settings->floats.menu_framebuffer_opacity;
-
- video_info->libretro_running = core_is_game_loaded();
-#else
- video_info->menu_is_alive = false;
- video_info->menu_footer_opacity = 0.0f;
- video_info->menu_header_opacity = 0.0f;
- video_info->materialui_color_theme = 0;
- video_info->menu_shader_pipeline = 0;
- video_info->xmb_color_theme = 0;
- video_info->xmb_theme = 0;
- video_info->timedate_enable = false;
- video_info->battery_level_enable = false;
- video_info->xmb_shadows_enable = false;
- video_info->xmb_alpha_factor = 0.0f;
- video_info->menu_framebuffer_opacity = 0.0f;
- video_info->menu_wallpaper_opacity = 0.0f;
-#endif
-
- runloop_get_status(&is_paused, &is_idle, &is_slowmotion, &is_perfcnt_enable);
-
- video_info->is_perfcnt_enable = is_perfcnt_enable;
- video_info->runloop_is_paused = is_paused;
- video_info->runloop_is_idle = is_idle;
- video_info->runloop_is_slowmotion = is_slowmotion;
-
- video_info->input_driver_nonblock_state = input_driver_is_nonblock_state();
-
- video_info->context_data = video_context_data;
- video_info->shader_driver = current_shader;
- video_info->shader_data = current_shader_data;
-
- video_info->cb_update_window_title = current_video_context.update_window_title;
- video_info->cb_swap_buffers = current_video_context.swap_buffers;
- video_info->cb_get_metrics = current_video_context.get_metrics;
- video_info->cb_set_resize = current_video_context.set_resize;
-
- video_info->cb_set_mvp = video_driver_cb_shader_set_mvp;
-
- video_info->userdata = video_driver_get_ptr(false);
-
-#ifdef HAVE_THREADS
- video_driver_threaded_unlock(is_threaded);
-#endif
-}
-
-/**
- * video_driver_translate_coord_viewport:
- * @mouse_x : Pointer X coordinate.
- * @mouse_y : Pointer Y coordinate.
- * @res_x : Scaled X coordinate.
- * @res_y : Scaled Y coordinate.
- * @res_screen_x : Scaled screen X coordinate.
- * @res_screen_y : Scaled screen Y coordinate.
- *
- * Translates pointer [X,Y] coordinates into scaled screen
- * coordinates based on viewport info.
- *
- * Returns: true (1) if successful, false if video driver doesn't support
- * viewport info.
- **/
-bool video_driver_translate_coord_viewport(
- struct video_viewport *vp,
- int mouse_x, int mouse_y,
- int16_t *res_x, int16_t *res_y,
- int16_t *res_screen_x, int16_t *res_screen_y)
-{
- int scaled_screen_x, scaled_screen_y, scaled_x, scaled_y;
- int norm_vp_width = (int)vp->width;
- int norm_vp_height = (int)vp->height;
- int norm_full_vp_width = (int)vp->full_width;
- int norm_full_vp_height = (int)vp->full_height;
-
- if (norm_full_vp_width <= 0 || norm_full_vp_height <= 0)
- return false;
-
- if (mouse_x >= 0 && mouse_x <= norm_full_vp_width)
- scaled_screen_x = ((2 * mouse_x * 0x7fff)
- / norm_full_vp_width) - 0x7fff;
- else
- scaled_screen_x = -0x8000; /* OOB */
-
- if (mouse_y >= 0 && mouse_y <= norm_full_vp_height)
- scaled_screen_y = ((2 * mouse_y * 0x7fff)
- / norm_full_vp_height) - 0x7fff;
- else
- scaled_screen_y = -0x8000; /* OOB */
-
- mouse_x -= vp->x;
- mouse_y -= vp->y;
-
- if (mouse_x >= 0 && mouse_x <= norm_vp_width)
- scaled_x = ((2 * mouse_x * 0x7fff)
- / norm_vp_width) - 0x7fff;
- else
- scaled_x = -0x8000; /* OOB */
-
- if (mouse_y >= 0 && mouse_y <= norm_vp_height)
- scaled_y = ((2 * mouse_y * 0x7fff)
- / norm_vp_height) - 0x7fff;
- else
- scaled_y = -0x8000; /* OOB */
-
- *res_x = scaled_x;
- *res_y = scaled_y;
- *res_screen_x = scaled_screen_x;
- *res_screen_y = scaled_screen_y;
-
- return true;
-}
-
-void video_driver_get_window_title(char *buf, unsigned len)
-{
- if (buf && video_driver_window_title_update)
- {
- strlcpy(buf, video_driver_window_title, len);
- video_driver_window_title_update = false;
- }
-}
-
-void video_driver_get_status(uint64_t *frame_count, bool * is_alive,
- bool *is_focused)
-{
- *frame_count = video_driver_frame_count;
- *is_alive = current_video ?
- current_video->alive(video_driver_data) : true;
- *is_focused = video_driver_cb_has_focus();
-}
-
-/**
- * find_video_context_driver_driver_index:
- * @ident : Identifier of resampler driver to find.
- *
- * Finds graphics context driver index by @ident name.
- *
- * Returns: graphics context driver index if driver was found, otherwise
- * -1.
- **/
-static int find_video_context_driver_index(const char *ident)
-{
- unsigned i;
- for (i = 0; gfx_ctx_drivers[i]; i++)
- if (string_is_equal_noncase(ident, gfx_ctx_drivers[i]->ident))
- return i;
- return -1;
-}
-
-/**
- * find_prev_context_driver:
- *
- * Finds previous driver in graphics context driver array.
- **/
-bool video_context_driver_find_prev_driver(void)
-{
- settings_t *settings = config_get_ptr();
- int i = find_video_context_driver_index(
- settings->arrays.video_context_driver);
-
- if (i > 0)
- {
- strlcpy(settings->arrays.video_context_driver,
- gfx_ctx_drivers[i - 1]->ident,
- sizeof(settings->arrays.video_context_driver));
- return true;
- }
-
- RARCH_WARN("Couldn't find any previous video context driver.\n");
- return false;
-}
-
-/**
- * find_next_context_driver:
- *
- * Finds next driver in graphics context driver array.
- **/
-bool video_context_driver_find_next_driver(void)
-{
- settings_t *settings = config_get_ptr();
- int i = find_video_context_driver_index(
- settings->arrays.video_context_driver);
-
- if (i >= 0 && gfx_ctx_drivers[i + 1])
- {
- strlcpy(settings->arrays.video_context_driver,
- gfx_ctx_drivers[i + 1]->ident,
- sizeof(settings->arrays.video_context_driver));
- return true;
- }
-
- RARCH_WARN("Couldn't find any next video context driver.\n");
- return false;
-}
-
-/**
- * video_context_driver_init:
- * @data : Input data.
- * @ctx : Graphics context driver to initialize.
- * @ident : Identifier of graphics context driver to find.
- * @api : API of higher-level graphics API.
- * @major : Major version number of higher-level graphics API.
- * @minor : Minor version number of higher-level graphics API.
- * @hw_render_ctx : Request a graphics context driver capable of
- * hardware rendering?
- *
- * Initialize graphics context driver.
- *
- * Returns: graphics context driver if successfully initialized,
- * otherwise NULL.
- **/
-static const gfx_ctx_driver_t *video_context_driver_init(
- void *data,
- const gfx_ctx_driver_t *ctx,
- const char *ident,
- enum gfx_ctx_api api, unsigned major,
- unsigned minor, bool hw_render_ctx,
- void **ctx_data)
-{
- video_frame_info_t video_info;
-
- if (!ctx->bind_api(data, api, major, minor))
- {
- RARCH_WARN("Failed to bind API (#%u, version %u.%u)"
- " on context driver \"%s\".\n",
- (unsigned)api, major, minor, ctx->ident);
-
- return NULL;
- }
-
- video_driver_build_info(&video_info);
-
- if (!(*ctx_data = ctx->init(&video_info, data)))
- return NULL;
-
- if (ctx->bind_hw_render)
- ctx->bind_hw_render(*ctx_data,
- video_info.shared_context && hw_render_ctx);
-
- return ctx;
-}
-
-/**
- * video_context_driver_init_first:
- * @data : Input data.
- * @ident : Identifier of graphics context driver to find.
- * @api : API of higher-level graphics API.
- * @major : Major version number of higher-level graphics API.
- * @minor : Minor version number of higher-level graphics API.
- * @hw_render_ctx : Request a graphics context driver capable of
- * hardware rendering?
- *
- * Finds first suitable graphics context driver and initializes.
- *
- * Returns: graphics context driver if found, otherwise NULL.
- **/
-const gfx_ctx_driver_t *video_context_driver_init_first(void *data,
- const char *ident, enum gfx_ctx_api api, unsigned major,
- unsigned minor, bool hw_render_ctx, void **ctx_data)
-{
- int i = find_video_context_driver_index(ident);
-
- if (i >= 0)
- {
- const gfx_ctx_driver_t *ctx = video_context_driver_init(data, gfx_ctx_drivers[i], ident,
- api, major, minor, hw_render_ctx, ctx_data);
- if (ctx)
- {
- video_context_data = *ctx_data;
- return ctx;
- }
- }
-
- for (i = 0; gfx_ctx_drivers[i]; i++)
- {
- const gfx_ctx_driver_t *ctx =
- video_context_driver_init(data, gfx_ctx_drivers[i], ident,
- api, major, minor, hw_render_ctx, ctx_data);
-
- if (ctx)
- {
- video_context_data = *ctx_data;
- return ctx;
- }
- }
-
- return NULL;
-}
-
-bool video_context_driver_init_image_buffer(const video_info_t *data)
-{
- if (
- current_video_context.image_buffer_init
- && current_video_context.image_buffer_init(
- video_context_data, data))
- return true;
- return false;
-}
-
-bool video_context_driver_write_to_image_buffer(gfx_ctx_image_t *img)
-{
- if (
- current_video_context.image_buffer_write
- && current_video_context.image_buffer_write(video_context_data,
- img->frame, img->width, img->height, img->pitch,
- img->rgb32, img->index, img->handle))
- return true;
- return false;
-}
-
-bool video_context_driver_get_video_output_prev(void)
-{
- if (!current_video_context.get_video_output_prev)
- return false;
- current_video_context.get_video_output_prev(video_context_data);
- return true;
-}
-
-bool video_context_driver_get_video_output_next(void)
-{
- if (!current_video_context.get_video_output_next)
- return false;
- current_video_context.get_video_output_next(video_context_data);
- return true;
-}
-
-void video_context_driver_make_current(bool release)
-{
- if (current_video_context.make_current)
- current_video_context.make_current(release);
-}
-
-bool video_context_driver_translate_aspect(gfx_ctx_aspect_t *aspect)
-{
- if (!video_context_data || !aspect)
- return false;
- if (!current_video_context.translate_aspect)
- return false;
- *aspect->aspect = current_video_context.translate_aspect(
- video_context_data, aspect->width, aspect->height);
- return true;
-}
-
-void video_context_driver_free(void)
-{
- if (current_video_context.destroy)
- current_video_context.destroy(video_context_data);
- video_context_driver_destroy();
- video_context_data = NULL;
-}
-
-bool video_context_driver_get_video_output_size(gfx_ctx_size_t *size_data)
-{
- if (!size_data)
- return false;
- if (!current_video_context.get_video_output_size)
- return false;
- current_video_context.get_video_output_size(video_context_data,
- size_data->width, size_data->height);
- return true;
-}
-
-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 = 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)
- current_interval = -1;
- current_video_context.swap_interval(video_context_data, current_interval);
- return true;
-}
-
-bool video_context_driver_get_proc_address(gfx_ctx_proc_address_t *proc)
-{
- if (!current_video_context.get_proc_address)
- return false;
-
- proc->addr = current_video_context.get_proc_address(proc->sym);
-
- return true;
-}
-
-bool video_context_driver_get_metrics(gfx_ctx_metrics_t *metrics)
-{
- if (
- current_video_context.get_metrics(video_context_data,
- metrics->type,
- metrics->value))
- return true;
- return false;
-}
-
-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 (!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;
-}
-
-bool video_context_driver_input_driver(gfx_ctx_input_t *inp)
-{
- settings_t *settings = config_get_ptr();
- const char *joypad_name = settings ?
- settings->arrays.input_joypad_driver : NULL;
-
- if (!current_video_context.input_driver)
- return false;
- current_video_context.input_driver(
- video_context_data, joypad_name,
- inp->input, inp->input_data);
- return true;
-}
-
-bool video_context_driver_suppress_screensaver(bool *bool_data)
-{
- if ( video_context_data
- && current_video_context.suppress_screensaver(
- video_context_data, *bool_data))
- return true;
- return false;
-}
-
-bool video_context_driver_get_ident(gfx_ctx_ident_t *ident)
-{
- if (!ident)
- return false;
- ident->ident = current_video_context.ident;
- return true;
-}
-
-bool video_context_driver_set_video_mode(gfx_ctx_mode_t *mode_info)
-{
- video_frame_info_t video_info;
-
- if (!current_video_context.set_video_mode)
- return false;
-
- video_driver_build_info(&video_info);
-
- if (!current_video_context.set_video_mode(
- video_context_data, &video_info, mode_info->width,
- mode_info->height, mode_info->fullscreen))
- return false;
- return true;
-}
-
-bool video_context_driver_get_video_size(gfx_ctx_mode_t *mode_info)
-{
- if (!current_video_context.get_video_size)
- return false;
- current_video_context.get_video_size(video_context_data,
- &mode_info->width, &mode_info->height);
- return true;
-}
-
-bool video_context_driver_show_mouse(bool *bool_data)
-{
- if (!current_video_context.show_mouse)
- return false;
- current_video_context.show_mouse(video_context_data, *bool_data);
- return true;
-}
-
-static bool video_context_driver_get_flags(gfx_ctx_flags_t *flags)
-{
- 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;
-
- flags->flags = 0;
-
- if (video_context_driver_get_flags(flags))
- if (BIT32_GET(flags->flags, flag))
- return true;
-
- return false;
-}
-
-bool video_context_driver_set_flags(gfx_ctx_flags_t *flags)
-{
- if (!flags)
- return false;
- if (!current_video_context.set_flags)
- {
- deferred_flag_data.flags = flags->flags;
- deferred_video_context_driver_set_flags = true;
- return false;
- }
-
- current_video_context.set_flags(video_context_data, flags->flags);
- return true;
-}
-
-enum gfx_ctx_api video_context_driver_get_api(void)
-{
- enum gfx_ctx_api ctx_api = video_context_data ?
- current_video_context.get_api(video_context_data) : GFX_CTX_NONE;
-
- if (ctx_api == GFX_CTX_NONE)
- {
- const char *video_driver = video_driver_get_ident();
- if (string_is_equal(video_driver, "d3d9"))
- return GFX_CTX_DIRECT3D9_API;
- else if (string_is_equal(video_driver, "d3d10"))
- return GFX_CTX_DIRECT3D10_API;
- else if (string_is_equal(video_driver, "d3d11"))
- return GFX_CTX_DIRECT3D11_API;
- else if (string_is_equal(video_driver, "d3d12"))
- return GFX_CTX_DIRECT3D12_API;
- else if (string_is_equal(video_driver, "gx2"))
- return GFX_CTX_GX2_API;
- else if (string_is_equal(video_driver, "gx"))
- return GFX_CTX_GX_API;
- else if (string_is_equal(video_driver, "gl"))
- return GFX_CTX_OPENGL_API;
- else if (string_is_equal(video_driver, "vulkan"))
- return GFX_CTX_VULKAN_API;
- else if (string_is_equal(video_driver, "metal"))
- return GFX_CTX_METAL_API;
-
- return GFX_CTX_NONE;
- }
-
- return ctx_api;
-}
-
-bool video_driver_has_windowed(void)
-{
-#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
- if (video_driver_data && current_video->has_windowed)
- return current_video->has_windowed(video_driver_data);
- else if (video_context_data && current_video_context.has_windowed)
- return current_video_context.has_windowed(video_context_data);
-#endif
- return false;
-}
-
-bool video_driver_cached_frame_has_valid_framebuffer(void)
-{
- if (frame_cache_data)
- return (frame_cache_data == RETRO_HW_FRAME_BUFFER_VALID);
- return false;
-}
-
-static const shader_backend_t *video_shader_set_backend(
- enum rarch_shader_type type)
-{
- switch (type)
- {
- case RARCH_SHADER_CG:
- {
-#ifdef HAVE_CG
- gfx_ctx_flags_t flags;
- flags.flags = 0;
- video_context_driver_get_flags(&flags);
-
- if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT))
- {
- RARCH_ERR("[Shader driver]: Cg cannot be used with core"
- " GL context. Trying to fall back to GLSL...\n");
- return video_shader_set_backend(RARCH_SHADER_GLSL);
- }
-
- RARCH_LOG("[Shader driver]: Using Cg shader backend.\n");
- return &gl_cg_backend;
-#else
- break;
-#endif
- }
- case RARCH_SHADER_GLSL:
-#ifdef HAVE_GLSL
- RARCH_LOG("[Shader driver]: Using GLSL shader backend.\n");
- return &gl_glsl_backend;
-#else
- break;
-#endif
- case RARCH_SHADER_HLSL:
- case RARCH_SHADER_NONE:
- default:
- break;
- }
-
- return NULL;
-}
-
-void video_shader_driver_use(video_shader_ctx_info_t *shader_info)
-{
- if (current_shader && current_shader->use)
- current_shader->use(shader_info->data, current_shader_data,
- shader_info->idx, shader_info->set_active);
-}
-
-void video_shader_driver_set_parameter(struct uniform_info *param)
-{
- if (current_shader && current_shader->set_uniform_parameter)
- current_shader->set_uniform_parameter(current_shader_data,
- param, NULL);
-}
-
-void video_shader_driver_set_parameters(video_shader_ctx_params_t *params)
-{
- if (current_shader && current_shader->set_params)
- current_shader->set_params(params, current_shader_data);
-}
-
-bool video_shader_driver_get_prev_textures(
- video_shader_ctx_texture_t *texture)
-{
- if (!texture || !current_shader)
- return false;
- texture->id = current_shader->get_prev_textures(current_shader_data);
-
- return true;
-}
-
-bool video_shader_driver_get_ident(video_shader_ctx_ident_t *ident)
-{
- if (!ident || !current_shader)
- return false;
- ident->ident = current_shader->ident;
- return true;
-}
-
-bool video_shader_driver_get_current_shader(video_shader_ctx_t *shader)
-{
- void *video_driver = video_driver_get_ptr(true);
- const video_poke_interface_t *video_poke = video_driver_get_poke();
-
- shader->data = NULL;
- if (!video_poke || !video_driver || !video_poke->get_current_shader)
- return false;
- shader->data = video_poke->get_current_shader(video_driver);
- return true;
-}
-
-bool video_shader_driver_direct_get_current_shader(
- video_shader_ctx_t *shader)
-{
- if (!current_shader)
- return false;
-
- shader->data = current_shader->get_current_shader(current_shader_data);
-
- return true;
-}
-
-bool video_shader_driver_deinit(void)
-{
- if (!current_shader)
- return false;
-
- if (current_shader->deinit)
- current_shader->deinit(current_shader_data);
-
- current_shader_data = NULL;
- current_shader = NULL;
- return true;
-}
-
-static enum gfx_wrap_type video_shader_driver_wrap_type_null(
- void *data, unsigned index)
-{
- return RARCH_WRAP_BORDER;
-}
-
-static bool video_driver_cb_set_mvp(void *data,
- void *shader_data, const void *mat_data)
-{
- video_shader_ctx_mvp_t mvp;
- mvp.data = data;
- mvp.matrix = mat_data;
-
- video_driver_set_mvp(&mvp);
- return true;
-}
-
-static struct video_shader *
-video_shader_driver_get_current_shader_null(void *data)
-{
- return NULL;
-}
-
-static void video_shader_driver_set_params_null(
- void *data, void *shader_data)
-{
-}
-
-static void video_shader_driver_scale_null(void *data,
- unsigned idx, struct gfx_fbo_scale *scale)
-{
- (void)idx;
- (void)scale;
-}
-
-static bool video_shader_driver_mipmap_input_null(
- void *data, unsigned idx)
-{
- (void)idx;
- return false;
-}
-
-static bool video_shader_driver_filter_type_null(
- void *data, unsigned idx, bool *smooth)
-{
- (void)idx;
- (void)smooth;
- return false;
-}
-
-static unsigned video_shader_driver_num_null(void *data)
-{
- return 0;
-}
-
-static bool video_shader_driver_get_feedback_pass_null(
- void *data, unsigned *idx)
-{
- (void)idx;
- return false;
-}
-
-static void video_shader_driver_reset_to_defaults(void)
-{
- if (!current_shader)
- return;
-
- if (!current_shader->wrap_type)
- current_shader->wrap_type = video_shader_driver_wrap_type_null;
- if (current_shader->set_mvp)
- video_driver_cb_shader_set_mvp = current_shader->set_mvp;
- else
- {
- current_shader->set_mvp = video_driver_cb_set_mvp;
- video_driver_cb_shader_set_mvp = video_driver_cb_set_mvp;
- }
- if (!current_shader->set_coords)
- current_shader->set_coords = video_driver_cb_set_coords;
-
- if (current_shader->use)
- video_driver_cb_shader_use = current_shader->use;
- else
- {
- current_shader->use = video_shader_driver_use_null;
- video_driver_cb_shader_use = video_shader_driver_use_null;
- }
- if (!current_shader->set_params)
- current_shader->set_params = video_shader_driver_set_params_null;
- if (!current_shader->shader_scale)
- current_shader->shader_scale = video_shader_driver_scale_null;
- if (!current_shader->mipmap_input)
- current_shader->mipmap_input = video_shader_driver_mipmap_input_null;
- if (!current_shader->filter_type)
- current_shader->filter_type = video_shader_driver_filter_type_null;
- if (!current_shader->num_shaders)
- current_shader->num_shaders = video_shader_driver_num_null;
- if (!current_shader->get_current_shader)
- current_shader->get_current_shader= video_shader_driver_get_current_shader_null;
- if (!current_shader->get_feedback_pass)
- current_shader->get_feedback_pass = video_shader_driver_get_feedback_pass_null;
-}
-
-/* Finds first suitable shader context driver. */
-bool video_shader_driver_init_first(void)
-{
- current_shader = (shader_backend_t*)shader_ctx_drivers[0];
- video_shader_driver_reset_to_defaults();
- return true;
-}
-
-bool video_shader_driver_init(video_shader_ctx_init_t *init)
-{
- void *tmp = NULL;
- settings_t *settings = config_get_ptr();
-
- if (!init->shader || !init->shader->init)
- {
- init->shader = video_shader_set_backend(init->shader_type);
-
- if (!init->shader)
- return false;
- }
-
- tmp = init->shader->init(init->data, init->path);
-
- if (!tmp)
- return false;
-
- if (string_is_equal(settings->arrays.menu_driver, "xmb")
- && init->shader->init_menu_shaders)
- {
- RARCH_LOG("Setting up menu pipeline shaders for XMB ... \n");
- init->shader->init_menu_shaders(tmp);
- }
-
- current_shader_data = tmp;
-
- RARCH_LOG("Resetting shader to defaults ... \n");
-
- current_shader = (shader_backend_t*)init->shader;
- video_shader_driver_reset_to_defaults();
-
- return true;
-}
-
-bool video_shader_driver_get_feedback_pass(unsigned *data)
-{
- return current_shader->get_feedback_pass(current_shader_data, data);
-}
-
-bool video_shader_driver_mipmap_input(unsigned *index)
-{
- return current_shader->mipmap_input(current_shader_data, *index);
-}
-
-bool video_shader_driver_scale(video_shader_ctx_scale_t *scaler)
-{
- if (!scaler || !scaler->scale)
- return false;
-
- scaler->scale->valid = false;
-
- current_shader->shader_scale(current_shader_data,
- scaler->idx, scaler->scale);
- return true;
-}
-
-bool video_shader_driver_info(video_shader_ctx_info_t *shader_info)
-{
- if (!shader_info)
- return false;
-
- shader_info->num = current_shader->num_shaders(current_shader_data);
-
- return true;
-}
-
-bool video_shader_driver_filter_type(video_shader_ctx_filter_t *filter)
-{
- if (filter)
- return current_shader->filter_type(current_shader_data,
- filter->index, filter->smooth);
- return false;
-}
-
-bool video_shader_driver_compile_program(
- struct shader_program_info *program_info)
-{
- if (program_info)
- return current_shader->compile_program(program_info->data,
- program_info->idx, NULL, program_info);
- return false;
-}
-
-bool video_shader_driver_wrap_type(video_shader_ctx_wrap_t *wrap)
-{
- wrap->type = current_shader->wrap_type(
- current_shader_data, wrap->idx);
- return true;
-}
-
-void video_driver_set_coords(video_shader_ctx_coords_t *coords)
-{
- if (current_shader && current_shader->set_coords)
- current_shader->set_coords(coords->handle_data,
- current_shader_data,
- (const struct video_coords*)coords->data);
- else
- {
- if (video_driver_poke && video_driver_poke->set_coords)
- video_driver_poke->set_coords(coords->handle_data,
- current_shader_data,
- (const struct video_coords*)coords->data);
- }
-}
-
-void video_driver_set_mvp(video_shader_ctx_mvp_t *mvp)
-{
- if (!mvp || !mvp->matrix)
- return;
-
- if (current_shader && current_shader->set_mvp)
- current_shader->set_mvp(mvp->data,
- current_shader_data, mvp->matrix);
- else
- {
- if (video_driver_poke && video_driver_poke->set_mvp)
- video_driver_poke->set_mvp(mvp->data,
- current_shader_data, mvp->matrix);
- }
-}
-
-float video_driver_get_refresh_rate(void)
-{
- if (video_driver_poke && video_driver_poke->get_refresh_rate)
- return video_driver_poke->get_refresh_rate(video_driver_data);
-
- return 0.0f;
-}
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ *
+ * 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
+#include
+#include
+#include
+
+#include "../audio/audio_driver.h"
+#include "../menu/menu_shader.h"
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#include "../dynamic.h"
+
+#ifdef HAVE_THREADS
+#include
+#endif
+
+#ifdef HAVE_MENU
+#include "../menu/menu_driver.h"
+#include "../menu/menu_setting.h"
+#endif
+
+#include "video_thread_wrapper.h"
+#include "video_driver.h"
+#include "video_display_server.h"
+#include "video_crt_switch.h"
+
+#include "../frontend/frontend_driver.h"
+#include "../record/record_driver.h"
+#include "../config.def.h"
+#include "../configuration.h"
+#include "../driver.h"
+#include "../retroarch.h"
+#include "../input/input_driver.h"
+#include "../list_special.h"
+#include "../core.h"
+#include "../command.h"
+#include "../msg_hash.h"
+#include "../verbosity.h"
+
+#define MEASURE_FRAME_TIME_SAMPLES_COUNT (2 * 1024)
+
+#define TIME_TO_FPS(last_time, new_time, frames) ((1000000.0f * (frames)) / ((new_time) - (last_time)))
+
+#define FPS_UPDATE_INTERVAL 256
+
+#ifdef HAVE_THREADS
+#define video_driver_is_threaded_internal() ((!video_driver_is_hw_context() && video_driver_threaded) ? true : false)
+#else
+#define video_driver_is_threaded_internal() (false)
+#endif
+
+#ifdef HAVE_THREADS
+#define video_driver_lock() \
+ if (display_lock) \
+ slock_lock(display_lock)
+
+#define video_driver_unlock() \
+ if (display_lock) \
+ slock_unlock(display_lock)
+
+#define video_driver_context_lock() \
+ if (context_lock) \
+ slock_lock(context_lock)
+
+#define video_driver_context_unlock() \
+ if (context_lock) \
+ slock_unlock(context_lock)
+
+#define video_driver_lock_free() \
+ slock_free(display_lock); \
+ slock_free(context_lock); \
+ display_lock = NULL; \
+ context_lock = NULL
+
+#define video_driver_threaded_lock(is_threaded) \
+ if (is_threaded) \
+ video_driver_lock()
+
+#define video_driver_threaded_unlock(is_threaded) \
+ if (is_threaded) \
+ video_driver_unlock()
+#else
+#define video_driver_lock() ((void)0)
+#define video_driver_unlock() ((void)0)
+#define video_driver_lock_free() ((void)0)
+#define video_driver_threaded_lock(is_threaded) ((void)0)
+#define video_driver_threaded_unlock(is_threaded) ((void)0)
+#define video_driver_context_lock() ((void)0)
+#define video_driver_context_unlock() ((void)0)
+#endif
+
+typedef struct video_pixel_scaler
+{
+ struct scaler_ctx *scaler;
+ void *scaler_out;
+} video_pixel_scaler_t;
+
+static void (*video_driver_cb_shader_use)(void *data,
+ void *shader_data, unsigned index, bool set_active);
+static bool (*video_driver_cb_shader_set_mvp)(void *data,
+ void *shader_data, const void *mat_data);
+bool (*video_driver_cb_has_focus)(void);
+
+/* Opaque handles to currently running window.
+ * Used by e.g. input drivers which bind to a window.
+ * Drivers are responsible for setting these if an input driver
+ * could potentially make use of this. */
+static uintptr_t video_driver_display = 0;
+static uintptr_t video_driver_window = 0;
+
+static rarch_softfilter_t *video_driver_state_filter = NULL;
+static void *video_driver_state_buffer = NULL;
+static unsigned video_driver_state_scale = 0;
+static unsigned video_driver_state_out_bpp = 0;
+static bool video_driver_state_out_rgb32 = false;
+static bool video_driver_crt_switching_active = false;
+
+static struct retro_system_av_info video_driver_av_info;
+
+static enum retro_pixel_format video_driver_pix_fmt = RETRO_PIXEL_FORMAT_0RGB1555;
+
+static const void *frame_cache_data = NULL;
+static unsigned frame_cache_width = 0;
+static unsigned frame_cache_height = 0;
+static size_t frame_cache_pitch = 0;
+static bool video_driver_threaded = false;
+
+static float video_driver_core_hz = 0.0f;
+static float video_driver_aspect_ratio = 0.0f;
+static unsigned video_driver_width = 0;
+static unsigned video_driver_height = 0;
+
+static enum rarch_display_type video_driver_display_type = RARCH_DISPLAY_NONE;
+static char video_driver_title_buf[64] = {0};
+static char video_driver_window_title[512] = {0};
+static bool video_driver_window_title_update = true;
+
+static retro_time_t video_driver_frame_time_samples[MEASURE_FRAME_TIME_SAMPLES_COUNT];
+static uint64_t video_driver_frame_time_count = 0;
+static uint64_t video_driver_frame_count = 0;
+
+static void *video_driver_data = NULL;
+static video_driver_t *current_video = NULL;
+
+/* Interface for "poking". */
+static const video_poke_interface_t *video_driver_poke = NULL;
+
+/* Used for 15-bit -> 16-bit conversions that take place before
+ * being passed to video driver. */
+static video_pixel_scaler_t *video_driver_scaler_ptr = NULL;
+
+static struct retro_hw_render_callback hw_render;
+
+static const struct
+retro_hw_render_context_negotiation_interface *
+hw_render_context_negotiation = NULL;
+
+/* Graphics driver requires RGBA byte order data (ABGR on little-endian)
+ * for 32-bit.
+ * This takes effect for overlay and shader cores that wants to load
+ * data into graphics driver. Kinda hackish to place it here, it is only
+ * used for GLES.
+ * TODO: Refactor this better. */
+static bool video_driver_use_rgba = false;
+static bool video_driver_data_own = false;
+static bool video_driver_active = false;
+
+static video_driver_frame_t frame_bak = NULL;
+
+/* If set during context deinit, the driver should keep
+ * graphics context alive to avoid having to reset all
+ * context state. */
+static bool video_driver_cache_context = false;
+
+/* Set to true by driver if context caching succeeded. */
+static bool video_driver_cache_context_ack = false;
+static uint8_t *video_driver_record_gpu_buffer = NULL;
+
+#ifdef HAVE_THREADS
+static slock_t *display_lock = NULL;
+static slock_t *context_lock = NULL;
+#endif
+
+static gfx_ctx_driver_t current_video_context;
+
+static void *video_context_data = NULL;
+
+/**
+ * dynamic.c:dynamic_request_hw_context will try to set flag data when the context
+ * is in the middle of being rebuilt; in these cases we will save flag
+ * data and set this to true.
+ * When the context is reinit, it checks this, reads from
+ * deferred_flag_data and cleans it.
+ *
+ * TODO - Dirty hack, fix it better
+ */
+static bool deferred_video_context_driver_set_flags = false;
+static gfx_ctx_flags_t deferred_flag_data = {0};
+
+static bool video_started_fullscreen = false;
+
+static shader_backend_t *current_shader = NULL;
+static void *current_shader_data = NULL;
+
+struct aspect_ratio_elem aspectratio_lut[ASPECT_RATIO_END] = {
+ { "4:3", 1.3333f },
+ { "16:9", 1.7778f },
+ { "16:10", 1.6f },
+ { "16:15", 16.0f / 15.0f },
+ { "21:9", 21.0f / 9.0f },
+ { "1:1", 1.0f },
+ { "2:1", 2.0f },
+ { "3:2", 1.5f },
+ { "3:4", 0.75f },
+ { "4:1", 4.0f },
+ { "9:16", 0.5625f },
+ { "5:4", 1.25f },
+ { "6:5", 1.2f },
+ { "7:9", 0.7777f },
+ { "8:3", 2.6666f },
+ { "8:7", 1.1428f },
+ { "19:12", 1.5833f },
+ { "19:14", 1.3571f },
+ { "30:17", 1.7647f },
+ { "32:9", 3.5555f },
+ { "Config", 0.0f },
+ { "Square pixel", 1.0f },
+ { "Core provided", 1.0f },
+ { "Custom", 0.0f }
+};
+
+static const video_driver_t *video_drivers[] = {
+#ifdef HAVE_OPENGL
+ &video_gl,
+#endif
+#ifdef HAVE_VULKAN
+ &video_vulkan,
+#endif
+#ifdef HAVE_METAL
+ &video_metal,
+#endif
+#ifdef XENON
+ &video_xenon360,
+#endif
+#if defined(HAVE_D3D12)
+ &video_d3d12,
+#endif
+#if defined(HAVE_D3D11)
+ &video_d3d11,
+#endif
+#if defined(HAVE_D3D10)
+ &video_d3d10,
+#endif
+#if defined(HAVE_D3D9)
+ &video_d3d9,
+#endif
+#if defined(HAVE_D3D8)
+ &video_d3d8,
+#endif
+#ifdef HAVE_VITA2D
+ &video_vita2d,
+#endif
+#ifdef PSP
+ &video_psp1,
+#endif
+#ifdef PS2
+ &video_ps2,
+#endif
+#ifdef _3DS
+ &video_ctr,
+#endif
+#ifdef SWITCH
+ &video_switch,
+#endif
+#ifdef HAVE_SDL
+ &video_sdl,
+#endif
+#ifdef HAVE_SDL2
+ &video_sdl2,
+#endif
+#ifdef HAVE_XVIDEO
+ &video_xvideo,
+#endif
+#ifdef GEKKO
+ &video_gx,
+#endif
+#ifdef WIIU
+ &video_wiiu,
+#endif
+#ifdef HAVE_VG
+ &video_vg,
+#endif
+#ifdef HAVE_OMAP
+ &video_omap,
+#endif
+#ifdef HAVE_EXYNOS
+ &video_exynos,
+#endif
+#ifdef HAVE_DISPMANX
+ &video_dispmanx,
+#endif
+#ifdef HAVE_SUNXI
+ &video_sunxi,
+#endif
+#ifdef HAVE_PLAIN_DRM
+ &video_drm,
+#endif
+#ifdef HAVE_XSHM
+ &video_xshm,
+#endif
+#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
+ &video_gdi,
+#endif
+#ifdef DJGPP
+ &video_vga,
+#endif
+#ifdef HAVE_SIXEL
+ &video_sixel,
+#endif
+#ifdef HAVE_CACA
+ &video_caca,
+#endif
+ &video_null,
+ NULL,
+};
+
+static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
+#if defined(ORBIS)
+ &orbis_ctx,
+#endif
+#if defined(HAVE_LIBNX) && defined(HAVE_OPENGL)
+ &switch_ctx,
+#endif
+#if defined(__CELLOS_LV2__)
+ &gfx_ctx_ps3,
+#endif
+#if defined(HAVE_VIDEOCORE)
+ &gfx_ctx_videocore,
+#endif
+#if defined(HAVE_MALI_FBDEV)
+ &gfx_ctx_mali_fbdev,
+#endif
+#if defined(HAVE_VIVANTE_FBDEV)
+ &gfx_ctx_vivante_fbdev,
+#endif
+#if defined(HAVE_OPENDINGUX_FBDEV)
+ &gfx_ctx_opendingux_fbdev,
+#endif
+#if defined(_WIN32) && (defined(HAVE_OPENGL) || defined(HAVE_VULKAN))
+ &gfx_ctx_wgl,
+#endif
+#if defined(HAVE_WAYLAND)
+ &gfx_ctx_wayland,
+#endif
+#if defined(HAVE_X11) && !defined(HAVE_OPENGLES)
+#if defined(HAVE_OPENGL) || defined(HAVE_VULKAN)
+ &gfx_ctx_x,
+#endif
+#endif
+#if defined(HAVE_X11) && defined(HAVE_OPENGL) && defined(HAVE_EGL)
+ &gfx_ctx_x_egl,
+#endif
+#if defined(HAVE_KMS)
+ &gfx_ctx_drm,
+#endif
+#if defined(ANDROID)
+ &gfx_ctx_android,
+#endif
+#if defined(__QNX__)
+ &gfx_ctx_qnx,
+#endif
+#if defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH) || defined(HAVE_COCOA_METAL)
+ &gfx_ctx_cocoagl,
+#endif
+#if defined(__APPLE__) && !defined(TARGET_IPHONE_SIMULATOR) && !defined(TARGET_OS_IPHONE)
+ &gfx_ctx_cgl,
+#endif
+#if (defined(HAVE_SDL) || defined(HAVE_SDL2)) && defined(HAVE_OPENGL)
+ &gfx_ctx_sdl_gl,
+#endif
+#ifdef HAVE_OSMESA
+ &gfx_ctx_osmesa,
+#endif
+#ifdef EMSCRIPTEN
+ &gfx_ctx_emscripten,
+#endif
+#if defined(HAVE_VULKAN) && defined(HAVE_VULKAN_DISPLAY)
+ &gfx_ctx_khr_display,
+#endif
+#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
+ &gfx_ctx_gdi,
+#endif
+#ifdef HAVE_SIXEL
+ &gfx_ctx_sixel,
+#endif
+ &gfx_ctx_null,
+ NULL
+};
+
+static const shader_backend_t *shader_ctx_drivers[] = {
+#ifdef HAVE_GLSL
+ &gl_glsl_backend,
+#endif
+#ifdef HAVE_CG
+ &gl_cg_backend,
+#endif
+ &shader_null_backend,
+ NULL
+};
+
+bool video_driver_started_fullscreen(void)
+{
+ return video_started_fullscreen;
+}
+
+/* Stub functions */
+
+static void update_window_title_null(void *data, void *data2)
+{
+}
+
+static void swap_buffers_null(void *data, void *data2)
+{
+}
+
+static bool get_metrics_null(void *data, enum display_metric_types type,
+ float *value)
+{
+ return false;
+}
+
+static bool set_resize_null(void *a, unsigned b, unsigned c)
+{
+ return false;
+}
+
+/**
+ * video_driver_find_handle:
+ * @idx : index of driver to get handle to.
+ *
+ * Returns: handle to video driver at index. Can be NULL
+ * if nothing found.
+ **/
+const void *video_driver_find_handle(int idx)
+{
+ const void *drv = video_drivers[idx];
+ if (!drv)
+ return NULL;
+ return drv;
+}
+
+/**
+ * video_driver_find_ident:
+ * @idx : index of driver to get handle to.
+ *
+ * Returns: Human-readable identifier of video driver at index. Can be NULL
+ * if nothing found.
+ **/
+const char *video_driver_find_ident(int idx)
+{
+ const video_driver_t *drv = video_drivers[idx];
+ if (!drv)
+ return NULL;
+ return drv->ident;
+}
+
+/**
+ * config_get_video_driver_options:
+ *
+ * Get an enumerated list of all video driver names, separated by '|'.
+ *
+ * Returns: string listing of all video driver names, separated by '|'.
+ **/
+const char* config_get_video_driver_options(void)
+{
+ return char_list_new_special(STRING_LIST_VIDEO_DRIVERS, NULL);
+}
+
+bool video_driver_is_threaded(void)
+{
+ return video_driver_is_threaded_internal();
+}
+
+#ifdef HAVE_VULKAN
+static bool hw_render_context_is_vulkan(enum retro_hw_context_type type)
+{
+ return type == RETRO_HW_CONTEXT_VULKAN;
+}
+#endif
+
+#if defined(HAVE_OPENGL)
+static bool hw_render_context_is_gl(enum retro_hw_context_type type)
+{
+ switch (type)
+ {
+ case RETRO_HW_CONTEXT_OPENGL:
+ case RETRO_HW_CONTEXT_OPENGLES2:
+ case RETRO_HW_CONTEXT_OPENGL_CORE:
+ case RETRO_HW_CONTEXT_OPENGLES3:
+ case RETRO_HW_CONTEXT_OPENGLES_VERSION:
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+#endif
+
+bool *video_driver_get_threaded(void)
+{
+ return &video_driver_threaded;
+}
+
+void video_driver_set_threaded(bool val)
+{
+ video_driver_threaded = val;
+}
+
+/**
+ * video_driver_get_ptr:
+ *
+ * Use this if you need the real video driver
+ * and driver data pointers.
+ *
+ * Returns: video driver's userdata.
+ **/
+void *video_driver_get_ptr(bool force_nonthreaded_data)
+{
+#ifdef HAVE_THREADS
+ if (video_driver_is_threaded_internal() && !force_nonthreaded_data)
+ return video_thread_get_ptr(NULL);
+#endif
+
+ return video_driver_data;
+}
+
+const char *video_driver_get_ident(void)
+{
+ return (current_video) ? current_video->ident : NULL;
+}
+
+const video_poke_interface_t *video_driver_get_poke(void)
+{
+ return video_driver_poke;
+}
+
+static bool video_context_has_focus(void)
+{
+ return current_video_context.has_focus && current_video_context.has_focus(video_context_data);
+}
+
+static bool video_driver_has_focus(void)
+{
+ return current_video && current_video->focus && current_video->focus(video_driver_data);
+}
+
+static bool null_driver_has_focus(void)
+{
+ return true;
+}
+
+static void video_context_driver_reset(void)
+{
+ if (!current_video_context.get_metrics)
+ current_video_context.get_metrics = get_metrics_null;
+
+ if (!current_video_context.update_window_title)
+ current_video_context.update_window_title = update_window_title_null;
+
+ if (!current_video_context.set_resize)
+ current_video_context.set_resize = set_resize_null;
+
+ if (!current_video_context.swap_buffers)
+ current_video_context.swap_buffers = swap_buffers_null;
+
+ if (current_video_context.has_focus)
+ video_driver_cb_has_focus = video_context_has_focus;
+
+}
+
+bool video_context_driver_set(const gfx_ctx_driver_t *data)
+{
+ if (!data)
+ return false;
+ current_video_context = *data;
+ video_context_driver_reset();
+ return true;
+}
+
+void video_context_driver_destroy(void)
+{
+ current_video_context.init = NULL;
+ current_video_context.bind_api = NULL;
+ current_video_context.swap_interval = NULL;
+ current_video_context.set_video_mode = NULL;
+ current_video_context.get_video_size = NULL;
+ current_video_context.get_video_output_size = NULL;
+ current_video_context.get_video_output_prev = NULL;
+ current_video_context.get_video_output_next = NULL;
+ current_video_context.get_metrics = get_metrics_null;
+ current_video_context.translate_aspect = NULL;
+ current_video_context.update_window_title = update_window_title_null;
+ current_video_context.check_window = NULL;
+ current_video_context.set_resize = set_resize_null;
+ current_video_context.has_focus = NULL;
+ current_video_context.suppress_screensaver = NULL;
+ current_video_context.has_windowed = NULL;
+ current_video_context.swap_buffers = swap_buffers_null;
+ current_video_context.input_driver = NULL;
+ current_video_context.get_proc_address = NULL;
+ current_video_context.image_buffer_init = NULL;
+ current_video_context.image_buffer_write = NULL;
+ current_video_context.show_mouse = NULL;
+ current_video_context.ident = NULL;
+ current_video_context.get_flags = NULL;
+ current_video_context.set_flags = NULL;
+ current_video_context.bind_hw_render = NULL;
+ current_video_context.get_context_data = NULL;
+ current_video_context.make_current = NULL;
+}
+
+/**
+ * video_driver_get_current_framebuffer:
+ *
+ * Gets pointer to current hardware renderer framebuffer object.
+ * Used by RETRO_ENVIRONMENT_SET_HW_RENDER.
+ *
+ * Returns: pointer to hardware framebuffer object, otherwise 0.
+ **/
+uintptr_t video_driver_get_current_framebuffer(void)
+{
+ if (video_driver_poke && video_driver_poke->get_current_framebuffer)
+ return video_driver_poke->get_current_framebuffer(video_driver_data);
+ return 0;
+}
+
+retro_proc_address_t video_driver_get_proc_address(const char *sym)
+{
+ if (video_driver_poke && video_driver_poke->get_proc_address)
+ return video_driver_poke->get_proc_address(video_driver_data, sym);
+ return NULL;
+}
+
+bool video_driver_set_shader(enum rarch_shader_type type,
+ const char *path)
+{
+ if (current_video->set_shader)
+ return current_video->set_shader(video_driver_data, type, path);
+ return false;
+}
+
+static void video_driver_filter_free(void)
+{
+ if (video_driver_state_filter)
+ rarch_softfilter_free(video_driver_state_filter);
+ video_driver_state_filter = NULL;
+
+ if (video_driver_state_buffer)
+ {
+#ifdef _3DS
+ linearFree(video_driver_state_buffer);
+#else
+ free(video_driver_state_buffer);
+#endif
+ }
+ video_driver_state_buffer = NULL;
+
+ video_driver_state_scale = 0;
+ video_driver_state_out_bpp = 0;
+ video_driver_state_out_rgb32 = false;
+}
+
+static void video_driver_init_filter(enum retro_pixel_format colfmt_int)
+{
+ unsigned pow2_x, pow2_y, maxsize;
+ void *buf = NULL;
+ settings_t *settings = config_get_ptr();
+ struct retro_game_geometry *geom = &video_driver_av_info.geometry;
+ unsigned width = geom->max_width;
+ unsigned height = geom->max_height;
+ /* Deprecated format. Gets pre-converted. */
+ enum retro_pixel_format colfmt =
+ (colfmt_int == RETRO_PIXEL_FORMAT_0RGB1555) ?
+ RETRO_PIXEL_FORMAT_RGB565 : colfmt_int;
+
+ if (video_driver_is_hw_context())
+ {
+ RARCH_WARN("Cannot use CPU filters when hardware rendering is used.\n");
+ return;
+ }
+
+ video_driver_state_filter = rarch_softfilter_new(
+ settings->paths.path_softfilter_plugin,
+ RARCH_SOFTFILTER_THREADS_AUTO, colfmt, width, height);
+
+ if (!video_driver_state_filter)
+ {
+ RARCH_ERR("[Video]: Failed to load filter.\n");
+ return;
+ }
+
+ rarch_softfilter_get_max_output_size(video_driver_state_filter,
+ &width, &height);
+
+ pow2_x = next_pow2(width);
+ pow2_y = next_pow2(height);
+ maxsize = MAX(pow2_x, pow2_y);
+ video_driver_state_scale = maxsize / RARCH_SCALE_BASE;
+ video_driver_state_out_rgb32 = rarch_softfilter_get_output_format(
+ video_driver_state_filter) ==
+ RETRO_PIXEL_FORMAT_XRGB8888;
+
+ video_driver_state_out_bpp = video_driver_state_out_rgb32 ?
+ sizeof(uint32_t) :
+ sizeof(uint16_t);
+
+ /* TODO: Aligned output. */
+#ifdef _3DS
+ buf = linearMemAlign(
+ width * height * video_driver_state_out_bpp, 0x80);
+#else
+ buf = malloc(
+ width * height * video_driver_state_out_bpp);
+#endif
+ if (!buf)
+ {
+ RARCH_ERR("[Video]: Softfilter initialization failed.\n");
+ video_driver_filter_free();
+ return;
+ }
+
+ video_driver_state_buffer = buf;
+}
+
+static void video_driver_init_input(const input_driver_t *tmp)
+{
+ const input_driver_t **input = input_get_double_ptr();
+ if (*input)
+ return;
+
+ /* Video driver didn't provide an input driver,
+ * so we use configured one. */
+ RARCH_LOG("[Video]: Graphics driver did not initialize an input driver."
+ " Attempting to pick a suitable driver.\n");
+
+ if (tmp)
+ *input = tmp;
+ else
+ input_driver_find_driver();
+
+ /* This should never really happen as tmp (driver.input) is always
+ * found before this in find_driver_input(), or we have aborted
+ * in a similar fashion anyways. */
+ if (!input_get_ptr())
+ goto error;
+
+ if (input_driver_init())
+ return;
+
+error:
+ RARCH_ERR("[Video]: Cannot initialize input driver. Exiting ...\n");
+ retroarch_fail(1, "video_driver_init_input()");
+}
+
+/**
+ * video_driver_monitor_compute_fps_statistics:
+ *
+ * Computes monitor FPS statistics.
+ **/
+static void video_driver_monitor_compute_fps_statistics(void)
+{
+ double avg_fps = 0.0;
+ double stddev = 0.0;
+ unsigned samples = 0;
+
+ if (video_driver_frame_time_count <
+ (2 * MEASURE_FRAME_TIME_SAMPLES_COUNT))
+ {
+ RARCH_LOG(
+ "[Video]: Does not have enough samples for monitor refresh rate"
+ " estimation. Requires to run for at least %u frames.\n",
+ 2 * MEASURE_FRAME_TIME_SAMPLES_COUNT);
+ return;
+ }
+
+ if (video_monitor_fps_statistics(&avg_fps, &stddev, &samples))
+ {
+ RARCH_LOG("[Video]: Average monitor Hz: %.6f Hz. (%.3f %% frame time"
+ " deviation, based on %u last samples).\n",
+ avg_fps, 100.0 * stddev, samples);
+ }
+}
+
+static void video_driver_pixel_converter_free(void)
+{
+ if (!video_driver_scaler_ptr)
+ return;
+
+ scaler_ctx_gen_reset(video_driver_scaler_ptr->scaler);
+
+ if (video_driver_scaler_ptr->scaler)
+ free(video_driver_scaler_ptr->scaler);
+ video_driver_scaler_ptr->scaler = NULL;
+
+ if (video_driver_scaler_ptr->scaler_out)
+ free(video_driver_scaler_ptr->scaler_out);
+ video_driver_scaler_ptr->scaler_out = NULL;
+
+ if (video_driver_scaler_ptr)
+ free(video_driver_scaler_ptr);
+ video_driver_scaler_ptr = NULL;
+}
+
+static void video_driver_free_internal(void)
+{
+#ifdef HAVE_THREADS
+ bool is_threaded = video_driver_is_threaded_internal();
+#endif
+
+ command_event(CMD_EVENT_OVERLAY_DEINIT, NULL);
+
+ if (!video_driver_is_video_cache_context())
+ video_driver_free_hw_context();
+
+ if (
+ !input_driver_owns_driver() &&
+ !input_driver_is_data_ptr_same(video_driver_data)
+ )
+ input_driver_deinit();
+
+ if (
+ !video_driver_data_own
+ && video_driver_data
+ && current_video && current_video->free
+ )
+ current_video->free(video_driver_data);
+
+ video_driver_pixel_converter_free();
+ video_driver_filter_free();
+
+ command_event(CMD_EVENT_SHADER_DIR_DEINIT, NULL);
+
+#ifdef HAVE_THREADS
+ if (is_threaded)
+ return;
+#endif
+
+ video_driver_monitor_compute_fps_statistics();
+}
+
+static bool video_driver_pixel_converter_init(unsigned size)
+{
+ struct retro_hw_render_callback *hwr =
+ video_driver_get_hw_context();
+ void *scalr_out = NULL;
+ video_pixel_scaler_t *scalr = NULL;
+ struct scaler_ctx *scalr_ctx = NULL;
+
+ /* If pixel format is not 0RGB1555, we don't need to do
+ * any internal pixel conversion. */
+ if (video_driver_pix_fmt != RETRO_PIXEL_FORMAT_0RGB1555)
+ return true;
+
+ /* No need to perform pixel conversion for HW rendering contexts. */
+ if (hwr && hwr->context_type != RETRO_HW_CONTEXT_NONE)
+ return true;
+
+ RARCH_WARN("0RGB1555 pixel format is deprecated,"
+ " and will be slower. For 15/16-bit, RGB565"
+ " format is preferred.\n");
+
+ scalr = (video_pixel_scaler_t*)calloc(1, sizeof(*scalr));
+
+ if (!scalr)
+ goto error;
+
+ video_driver_scaler_ptr = scalr;
+
+ scalr_ctx = (struct scaler_ctx*)calloc(1, sizeof(*scalr_ctx));
+
+ if (!scalr_ctx)
+ goto error;
+
+ video_driver_scaler_ptr->scaler = scalr_ctx;
+ video_driver_scaler_ptr->scaler->scaler_type = SCALER_TYPE_POINT;
+ video_driver_scaler_ptr->scaler->in_fmt = SCALER_FMT_0RGB1555;
+
+ /* TODO: Pick either ARGB8888 or RGB565 depending on driver. */
+ video_driver_scaler_ptr->scaler->out_fmt = SCALER_FMT_RGB565;
+
+ if (!scaler_ctx_gen_filter(scalr_ctx))
+ goto error;
+
+ scalr_out = calloc(sizeof(uint16_t), size * size);
+
+ if (!scalr_out)
+ goto error;
+
+ video_driver_scaler_ptr->scaler_out = scalr_out;
+
+ return true;
+
+error:
+ video_driver_pixel_converter_free();
+ video_driver_filter_free();
+
+ return false;
+}
+
+static bool video_driver_init_internal(bool *video_is_threaded)
+{
+ video_info_t video;
+ unsigned max_dim, scale, width, height;
+ video_viewport_t *custom_vp = NULL;
+ const input_driver_t *tmp = NULL;
+ rarch_system_info_t *system = NULL;
+ static uint16_t dummy_pixels[32] = {0};
+ settings_t *settings = config_get_ptr();
+ struct retro_game_geometry *geom = &video_driver_av_info.geometry;
+
+ if (!string_is_empty(settings->paths.path_softfilter_plugin))
+ video_driver_init_filter(video_driver_pix_fmt);
+
+ max_dim = MAX(geom->max_width, geom->max_height);
+ scale = next_pow2(max_dim) / RARCH_SCALE_BASE;
+ scale = MAX(scale, 1);
+
+ if (video_driver_state_filter)
+ scale = video_driver_state_scale;
+
+ /* Update core-dependent aspect ratio values. */
+ video_driver_set_viewport_square_pixel();
+ video_driver_set_viewport_core();
+ video_driver_set_viewport_config();
+
+ /* Update CUSTOM viewport. */
+ custom_vp = video_viewport_get_custom();
+
+ if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
+ {
+ float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value;
+ aspectratio_lut[ASPECT_RATIO_CUSTOM].value =
+ (custom_vp->width && custom_vp->height) ?
+ (float)custom_vp->width / custom_vp->height : default_aspect;
+ }
+
+ video_driver_set_aspect_ratio_value(
+ aspectratio_lut[settings->uints.video_aspect_ratio_idx].value);
+
+ if (settings->bools.video_fullscreen|| retroarch_is_forced_fullscreen())
+ {
+ width = settings->uints.video_fullscreen_x;
+ height = settings->uints.video_fullscreen_y;
+ }
+ else
+ {
+ /* To-Do: remove when the new window resizing core is hooked */
+ if (settings->bools.video_window_save_positions &&
+ (settings->uints.window_position_width || settings->uints.window_position_height))
+ {
+ width = settings->uints.window_position_width;
+ height = settings->uints.window_position_height;
+ }
+ else
+ {
+ if (settings->bools.video_force_aspect)
+ {
+ /* Do rounding here to simplify integer scale correctness. */
+ unsigned base_width =
+ roundf(geom->base_height * video_driver_get_aspect_ratio());
+ width = roundf(base_width * settings->floats.video_scale);
+ }
+ else
+ width = roundf(geom->base_width * settings->floats.video_scale);
+ height = roundf(geom->base_height * settings->floats.video_scale);
+}
+ }
+
+ if (width && height)
+ RARCH_LOG("[Video]: Video @ %ux%u\n", width, height);
+ else
+ RARCH_LOG("[Video]: Video @ fullscreen\n");
+
+ video_driver_display_type_set(RARCH_DISPLAY_NONE);
+ video_driver_display_set(0);
+ video_driver_window_set(0);
+
+ if (!video_driver_pixel_converter_init(RARCH_SCALE_BASE * scale))
+ {
+ RARCH_ERR("[Video]: Failed to initialize pixel converter.\n");
+ goto error;
+ }
+
+ video.width = width;
+ video.height = height;
+ video.fullscreen = settings->bools.video_fullscreen || retroarch_is_forced_fullscreen();
+ video.vsync = settings->bools.video_vsync && !rarch_ctl(RARCH_CTL_IS_NONBLOCK_FORCED, NULL);
+ video.force_aspect = settings->bools.video_force_aspect;
+ video.font_enable = settings->bools.video_font_enable;
+ video.swap_interval = settings->uints.video_swap_interval;
+#ifdef GEKKO
+ video.viwidth = settings->uints.video_viwidth;
+ video.vfilter = settings->bools.video_vfilter;
+#endif
+ video.smooth = settings->bools.video_smooth;
+ video.input_scale = scale;
+ video.rgb32 = video_driver_state_filter ?
+ video_driver_state_out_rgb32 :
+ (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);
+ video.parent = 0;
+
+ video_started_fullscreen = video.fullscreen;
+
+ /* Reset video frame count */
+ video_driver_frame_count = 0;
+
+ tmp = input_get_ptr();
+ /* Need to grab the "real" video driver interface on a reinit. */
+ video_driver_find_driver();
+
+#ifdef HAVE_THREADS
+ video.is_threaded = video_driver_is_threaded_internal();
+ *video_is_threaded = video.is_threaded;
+
+ if (video.is_threaded)
+ {
+ /* Can't do hardware rendering with threaded driver currently. */
+ RARCH_LOG("[Video]: Starting threaded video driver ...\n");
+
+ if (!video_init_thread((const video_driver_t**)¤t_video,
+ &video_driver_data,
+ input_get_double_ptr(), input_driver_get_data_ptr(),
+ current_video, video))
+ {
+ RARCH_ERR("[Video]: Cannot open threaded video driver ... Exiting ...\n");
+ goto error;
+ }
+ }
+ else
+#endif
+ video_driver_data = current_video->init(
+ &video, input_get_double_ptr(),
+ input_driver_get_data_ptr());
+
+ if (!video_driver_data)
+ {
+ RARCH_ERR("[Video]: Cannot open video driver ... Exiting ...\n");
+ goto error;
+ }
+
+ if (current_video->focus)
+ video_driver_cb_has_focus = video_driver_has_focus;
+
+ video_driver_poke = NULL;
+ if (current_video->poke_interface)
+ current_video->poke_interface(video_driver_data, &video_driver_poke);
+
+ if (current_video->viewport_info &&
+ (!custom_vp->width ||
+ !custom_vp->height))
+ {
+ /* Force custom viewport to have sane parameters. */
+ custom_vp->width = width;
+ custom_vp->height = height;
+
+ video_driver_get_viewport_info(custom_vp);
+ }
+
+ system = runloop_get_system_info();
+
+ video_driver_set_rotation(
+ (settings->uints.video_rotation + system->rotation) % 4);
+
+ current_video->suppress_screensaver(video_driver_data,
+ settings->bools.ui_suspend_screensaver_enable);
+
+ video_driver_init_input(tmp);
+
+ command_event(CMD_EVENT_OVERLAY_DEINIT, NULL);
+ command_event(CMD_EVENT_OVERLAY_INIT, NULL);
+
+ if (!core_is_game_loaded())
+ video_driver_cached_frame_set(&dummy_pixels, 4, 4, 8);
+
+#if defined(PSP)
+ video_driver_set_texture_frame(&dummy_pixels, false, 1, 1, 1.0f);
+#endif
+
+ video_context_driver_reset();
+
+ video_display_server_init();
+
+ command_event(CMD_EVENT_SHADER_DIR_INIT, NULL);
+
+ return true;
+
+error:
+ retroarch_fail(1, "init_video()");
+ return false;
+}
+
+bool video_driver_set_viewport(unsigned width, unsigned height,
+ bool force_fullscreen, bool allow_rotate)
+{
+ if (!current_video || !current_video->set_viewport)
+ return false;
+ current_video->set_viewport(video_driver_data, width, height,
+ force_fullscreen, allow_rotate);
+ return true;
+}
+
+bool video_driver_set_rotation(unsigned rotation)
+{
+ if (!current_video || !current_video->set_rotation)
+ return false;
+ current_video->set_rotation(video_driver_data, rotation);
+ return true;
+}
+
+bool video_driver_set_video_mode(unsigned width,
+ unsigned height, bool fullscreen)
+{
+ gfx_ctx_mode_t mode;
+
+ if (video_driver_poke && video_driver_poke->set_video_mode)
+ {
+ video_driver_poke->set_video_mode(video_driver_data,
+ width, height, fullscreen);
+ return true;
+ }
+
+ mode.width = width;
+ mode.height = height;
+ mode.fullscreen = fullscreen;
+
+ return video_context_driver_set_video_mode(&mode);
+}
+
+bool video_driver_get_video_output_size(unsigned *width, unsigned *height)
+{
+ if (!video_driver_poke || !video_driver_poke->get_video_output_size)
+ return false;
+ video_driver_poke->get_video_output_size(video_driver_data,
+ width, height);
+ return true;
+}
+
+void video_driver_set_osd_msg(const char *msg, const void *data, void *font)
+{
+ video_frame_info_t video_info;
+ video_driver_build_info(&video_info);
+ if (video_driver_poke && video_driver_poke->set_osd_msg)
+ video_driver_poke->set_osd_msg(video_driver_data, &video_info, msg, data, font);
+}
+
+void video_driver_set_texture_enable(bool enable, bool fullscreen)
+{
+ if (video_driver_poke && video_driver_poke->set_texture_enable)
+ video_driver_poke->set_texture_enable(video_driver_data,
+ enable, fullscreen);
+}
+
+void video_driver_set_texture_frame(const void *frame, bool rgb32,
+ unsigned width, unsigned height, float alpha)
+{
+ if (video_driver_poke && video_driver_poke->set_texture_frame)
+ video_driver_poke->set_texture_frame(video_driver_data,
+ frame, rgb32, width, height, alpha);
+}
+
+#ifdef HAVE_OVERLAY
+bool video_driver_overlay_interface(const video_overlay_interface_t **iface)
+{
+ if (!current_video || !current_video->overlay_interface)
+ return false;
+ current_video->overlay_interface(video_driver_data, iface);
+ return true;
+}
+#endif
+
+void *video_driver_read_frame_raw(unsigned *width,
+ unsigned *height, size_t *pitch)
+{
+ if (!current_video || !current_video->read_frame_raw)
+ return NULL;
+ return current_video->read_frame_raw(video_driver_data, width,
+ height, pitch);
+}
+
+void video_driver_set_filtering(unsigned index, bool smooth)
+{
+ if (video_driver_poke && video_driver_poke->set_filtering)
+ video_driver_poke->set_filtering(video_driver_data, index, smooth);
+}
+
+void video_driver_cached_frame_set(const void *data, unsigned width,
+ unsigned height, size_t pitch)
+{
+ if (data)
+ frame_cache_data = data;
+ frame_cache_width = width;
+ frame_cache_height = height;
+ frame_cache_pitch = pitch;
+}
+
+void video_driver_cached_frame_get(const void **data, unsigned *width,
+ unsigned *height, size_t *pitch)
+{
+ if (data)
+ *data = frame_cache_data;
+ if (width)
+ *width = frame_cache_width;
+ if (height)
+ *height = frame_cache_height;
+ if (pitch)
+ *pitch = frame_cache_pitch;
+}
+
+void video_driver_get_size(unsigned *width, unsigned *height)
+{
+#ifdef HAVE_THREADS
+ bool is_threaded = video_driver_is_threaded_internal();
+ video_driver_threaded_lock(is_threaded);
+#endif
+ if (width)
+ *width = video_driver_width;
+ if (height)
+ *height = video_driver_height;
+#ifdef HAVE_THREADS
+ video_driver_threaded_unlock(is_threaded);
+#endif
+}
+
+void video_driver_set_size(unsigned *width, unsigned *height)
+{
+#ifdef HAVE_THREADS
+ bool is_threaded = video_driver_is_threaded_internal();
+ video_driver_threaded_lock(is_threaded);
+#endif
+ if (width)
+ video_driver_width = *width;
+ if (height)
+ video_driver_height = *height;
+#ifdef HAVE_THREADS
+ video_driver_threaded_unlock(is_threaded);
+#endif
+}
+
+/**
+ * video_monitor_set_refresh_rate:
+ * @hz : New refresh rate for monitor.
+ *
+ * Sets monitor refresh rate to new value.
+ **/
+void video_monitor_set_refresh_rate(float hz)
+{
+ char msg[128];
+ settings_t *settings = config_get_ptr();
+
+ snprintf(msg, sizeof(msg),
+ "Setting refresh rate to: %.3f Hz.", hz);
+ runloop_msg_queue_push(msg, 1, 180, false);
+ RARCH_LOG("%s\n", msg);
+
+ configuration_set_float(settings,
+ settings->floats.video_refresh_rate,
+ hz);
+}
+
+/**
+ * video_monitor_fps_statistics
+ * @refresh_rate : Monitor refresh rate.
+ * @deviation : Deviation from measured refresh rate.
+ * @sample_points : Amount of sampled points.
+ *
+ * Gets the monitor FPS statistics based on the current
+ * runtime.
+ *
+ * Returns: true (1) on success.
+ * false (0) if:
+ * a) threaded video mode is enabled
+ * b) less than 2 frame time samples.
+ * c) FPS monitor enable is off.
+ **/
+bool video_monitor_fps_statistics(double *refresh_rate,
+ double *deviation, unsigned *sample_points)
+{
+ unsigned i;
+ retro_time_t accum = 0;
+ retro_time_t avg = 0;
+ retro_time_t accum_var = 0;
+ unsigned samples = 0;
+
+#ifdef HAVE_THREADS
+ if (video_driver_is_threaded_internal())
+ return false;
+#endif
+
+ samples = MIN(MEASURE_FRAME_TIME_SAMPLES_COUNT,
+ (unsigned)video_driver_frame_time_count);
+
+ if (samples < 2)
+ return false;
+
+ /* Measure statistics on frame time (microsecs), *not* FPS. */
+ for (i = 0; i < samples; i++)
+ {
+ accum += video_driver_frame_time_samples[i];
+#if 0
+ RARCH_LOG("[Video]: Interval #%u: %d usec / frame.\n",
+ i, (int)frame_time_samples[i]);
+#endif
+ }
+
+ avg = accum / samples;
+
+ /* Drop first measurement. It is likely to be bad. */
+ for (i = 0; i < samples; i++)
+ {
+ retro_time_t diff = video_driver_frame_time_samples[i] - avg;
+ accum_var += diff * diff;
+ }
+
+ *deviation = sqrt((double)accum_var / (samples - 1)) / avg;
+
+ if (refresh_rate)
+ *refresh_rate = 1000000.0 / avg;
+
+ if (sample_points)
+ *sample_points = samples;
+
+ return true;
+}
+
+float video_driver_get_aspect_ratio(void)
+{
+ return video_driver_aspect_ratio;
+}
+
+void video_driver_set_aspect_ratio_value(float value)
+{
+ video_driver_aspect_ratio = value;
+}
+
+static bool video_driver_frame_filter(
+ const void *data,
+ video_frame_info_t *video_info,
+ unsigned width, unsigned height,
+ size_t pitch,
+ unsigned *output_width, unsigned *output_height,
+ unsigned *output_pitch)
+{
+ rarch_softfilter_get_output_size(video_driver_state_filter,
+ output_width, output_height, width, height);
+
+ *output_pitch = (*output_width) * video_driver_state_out_bpp;
+
+ rarch_softfilter_process(video_driver_state_filter,
+ video_driver_state_buffer, *output_pitch,
+ data, width, height, pitch);
+
+ if (video_info->post_filter_record && recording_data)
+ recording_dump_frame(video_driver_state_buffer,
+ *output_width, *output_height, *output_pitch,
+ video_info->runloop_is_idle);
+
+ return true;
+}
+
+rarch_softfilter_t *video_driver_frame_filter_get_ptr(void)
+{
+ return video_driver_state_filter;
+}
+
+enum retro_pixel_format video_driver_get_pixel_format(void)
+{
+ return video_driver_pix_fmt;
+}
+
+void video_driver_set_pixel_format(enum retro_pixel_format fmt)
+{
+ video_driver_pix_fmt = fmt;
+}
+
+/**
+ * video_driver_cached_frame:
+ *
+ * Renders the current video frame.
+ **/
+bool video_driver_cached_frame(void)
+{
+ void *recording = recording_driver_get_data_ptr();
+
+ recording_driver_lock();
+
+ /* Cannot allow recording when pushing duped frames. */
+ recording_data = NULL;
+
+ retro_ctx.frame_cb(
+ (frame_cache_data != RETRO_HW_FRAME_BUFFER_VALID)
+ ? frame_cache_data : NULL,
+ frame_cache_width,
+ frame_cache_height, frame_cache_pitch);
+
+ recording_data = recording;
+
+ recording_driver_unlock();
+
+ return true;
+}
+
+void video_driver_monitor_adjust_system_rates(void)
+{
+ float timing_skew = 0.0f;
+ settings_t *settings = config_get_ptr();
+ float video_refresh_rate = settings->floats.video_refresh_rate;
+ float timing_skew_hz = video_refresh_rate;
+ const struct retro_system_timing *info = (const struct retro_system_timing*)&video_driver_av_info.timing;
+
+ rarch_ctl(RARCH_CTL_UNSET_NONBLOCK_FORCED, NULL);
+
+ if (!info || info->fps <= 0.0)
+ return;
+
+ video_driver_core_hz = info->fps;
+
+ if (video_driver_crt_switching_active)
+ timing_skew_hz = video_driver_core_hz;
+ timing_skew = fabs(
+ 1.0f - info->fps / timing_skew_hz);
+
+ if (!settings->bools.vrr_runloop_enable)
+ {
+ /* We don't want to adjust pitch too much. If we have extreme cases,
+ * just don't readjust at all. */
+ if (timing_skew <= settings->floats.audio_max_timing_skew)
+ return;
+
+ RARCH_LOG("[Video]: Timings deviate too much. Will not adjust."
+ " (Display = %.2f Hz, Game = %.2f Hz)\n",
+ video_refresh_rate,
+ (float)info->fps);
+ }
+
+ if (info->fps <= timing_skew_hz)
+ return;
+
+ /* We won't be able to do VSync reliably when game FPS > monitor FPS. */
+ rarch_ctl(RARCH_CTL_SET_NONBLOCK_FORCED, NULL);
+ RARCH_LOG("[Video]: Game FPS > Monitor FPS. Cannot rely on VSync.\n");
+}
+
+void video_driver_menu_settings(void **list_data, void *list_info_data,
+ void *group_data, void *subgroup_data, const char *parent_group)
+{
+#ifdef HAVE_MENU
+ rarch_setting_t **list = (rarch_setting_t**)list_data;
+ rarch_setting_info_t *list_info = (rarch_setting_info_t*)list_info_data;
+ rarch_setting_group_info_t *group_info = (rarch_setting_group_info_t*)group_data;
+ rarch_setting_group_info_t *subgroup_info = (rarch_setting_group_info_t*)subgroup_data;
+ global_t *global = global_get_ptr();
+
+ (void)list;
+ (void)list_info;
+ (void)group_info;
+ (void)subgroup_info;
+ (void)global;
+
+#if defined(__CELLOS_LV2__)
+ CONFIG_BOOL(
+ list, list_info,
+ &global->console.screen.pal60_enable,
+ MENU_ENUM_LABEL_PAL60_ENABLE,
+ MENU_ENUM_LABEL_VALUE_PAL60_ENABLE,
+ 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);
+#endif
+#if defined(GEKKO) || defined(_XBOX360)
+ CONFIG_UINT(
+ list, list_info,
+ &global->console.screen.gamma_correction,
+ MENU_ENUM_LABEL_VIDEO_GAMMA,
+ MENU_ENUM_LABEL_VALUE_VIDEO_GAMMA,
+ 0,
+ group_info,
+ subgroup_info,
+ parent_group,
+ general_write_handler,
+ general_read_handler);
+ menu_settings_list_current_add_cmd(
+ list,
+ list_info,
+ CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
+ menu_settings_list_current_add_range(
+ list,
+ list_info,
+ 0,
+ MAX_GAMMA_SETTING,
+ 1,
+ true,
+ true);
+ settings_data_list_current_add_flags(list, list_info,
+ SD_FLAG_CMD_APPLY_AUTO|SD_FLAG_ADVANCED);
+#endif
+#if defined(_XBOX1) || defined(HW_RVL)
+ CONFIG_BOOL(
+ list, list_info,
+ &global->console.softfilter_enable,
+ MENU_ENUM_LABEL_VIDEO_SOFT_FILTER,
+ MENU_ENUM_LABEL_VALUE_VIDEO_SOFT_FILTER,
+ 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);
+ menu_settings_list_current_add_cmd(
+ list,
+ list_info,
+ CMD_EVENT_VIDEO_APPLY_STATE_CHANGES);
+#endif
+#ifdef _XBOX1
+ CONFIG_UINT(
+ list, list_info,
+ &global->console.screen.flicker_filter_index,
+ MENU_ENUM_LABEL_VIDEO_FILTER_FLICKER,
+ MENU_ENUM_LABEL_VALUE_VIDEO_FILTER_FLICKER,
+ 0,
+ group_info,
+ subgroup_info,
+ parent_group,
+ general_write_handler,
+ general_read_handler);
+ menu_settings_list_current_add_range(list, list_info,
+ 0, 5, 1, true, true);
+#endif
+#endif
+}
+
+static void video_driver_lock_new(void)
+{
+ video_driver_lock_free();
+#ifdef HAVE_THREADS
+ if (!display_lock)
+ display_lock = slock_new();
+ retro_assert(display_lock);
+
+ if (!context_lock)
+ context_lock = slock_new();
+ retro_assert(context_lock);
+#endif
+}
+
+void video_driver_destroy(void)
+{
+ video_display_server_destroy();
+ crt_video_restore();
+
+ video_driver_cb_has_focus = null_driver_has_focus;
+ video_driver_use_rgba = false;
+ video_driver_data_own = false;
+ video_driver_active = false;
+ video_driver_cache_context = false;
+ video_driver_cache_context_ack = false;
+ video_driver_record_gpu_buffer = NULL;
+ current_video = NULL;
+ video_driver_set_cached_frame_ptr(NULL);
+}
+
+void video_driver_set_cached_frame_ptr(const void *data)
+{
+ if (data)
+ frame_cache_data = data;
+}
+
+void video_driver_set_stub_frame(void)
+{
+ frame_bak = current_video->frame;
+ current_video->frame = video_null.frame;
+}
+
+void video_driver_unset_stub_frame(void)
+{
+ if (frame_bak != NULL)
+ current_video->frame = frame_bak;
+
+ frame_bak = NULL;
+}
+
+bool video_driver_is_stub_frame(void)
+{
+ return current_video->frame == video_null.frame;
+}
+
+bool video_driver_supports_recording(void)
+{
+ settings_t *settings = config_get_ptr();
+ return settings->bools.video_gpu_record
+ && current_video->read_viewport;
+}
+
+bool video_driver_supports_viewport_read(void)
+{
+ settings_t *settings = config_get_ptr();
+ return (settings->bools.video_gpu_screenshot ||
+ (video_driver_is_hw_context() && !current_video->read_frame_raw))
+ && current_video->read_viewport && current_video->viewport_info;
+}
+
+bool video_driver_supports_read_frame_raw(void)
+{
+ if (current_video->read_frame_raw)
+ return true;
+ return false;
+}
+
+void video_driver_set_viewport_config(void)
+{
+ settings_t *settings = config_get_ptr();
+
+ if (settings->floats.video_aspect_ratio < 0.0f)
+ {
+ struct retro_game_geometry *geom = &video_driver_av_info.geometry;
+
+ if (geom->aspect_ratio > 0.0f &&
+ settings->bools.video_aspect_ratio_auto)
+ aspectratio_lut[ASPECT_RATIO_CONFIG].value = geom->aspect_ratio;
+ else
+ {
+ unsigned base_width = geom->base_width;
+ unsigned base_height = geom->base_height;
+
+ /* Get around division by zero errors */
+ if (base_width == 0)
+ base_width = 1;
+ if (base_height == 0)
+ base_height = 1;
+ aspectratio_lut[ASPECT_RATIO_CONFIG].value =
+ (float)base_width / base_height; /* 1:1 PAR. */
+ }
+ }
+ else
+ {
+ aspectratio_lut[ASPECT_RATIO_CONFIG].value =
+ settings->floats.video_aspect_ratio;
+ }
+}
+
+void video_driver_set_viewport_square_pixel(void)
+{
+ unsigned len, highest, i, aspect_x, aspect_y;
+ struct retro_game_geometry *geom = &video_driver_av_info.geometry;
+ unsigned width = geom->base_width;
+ unsigned height = geom->base_height;
+
+ if (width == 0 || height == 0)
+ return;
+
+ len = MIN(width, height);
+ highest = 1;
+
+ for (i = 1; i < len; i++)
+ {
+ if ((width % i) == 0 && (height % i) == 0)
+ highest = i;
+ }
+
+ aspect_x = width / highest;
+ aspect_y = height / highest;
+
+ snprintf(aspectratio_lut[ASPECT_RATIO_SQUARE].name,
+ sizeof(aspectratio_lut[ASPECT_RATIO_SQUARE].name),
+ "1:1 PAR (%u:%u DAR)", aspect_x, aspect_y);
+
+ aspectratio_lut[ASPECT_RATIO_SQUARE].value = (float)aspect_x / aspect_y;
+}
+
+void video_driver_set_viewport_core(void)
+{
+ struct retro_game_geometry *geom = &video_driver_av_info.geometry;
+
+ if (!geom || geom->base_width <= 0.0f || geom->base_height <= 0.0f)
+ return;
+
+ /* Fallback to 1:1 pixel ratio if none provided */
+ if (geom->aspect_ratio > 0.0f)
+ aspectratio_lut[ASPECT_RATIO_CORE].value = geom->aspect_ratio;
+ else
+ aspectratio_lut[ASPECT_RATIO_CORE].value =
+ (float)geom->base_width / geom->base_height;
+}
+
+void video_driver_reset_custom_viewport(void)
+{
+ struct video_viewport *custom_vp = video_viewport_get_custom();
+
+ custom_vp->width = 0;
+ custom_vp->height = 0;
+ custom_vp->x = 0;
+ custom_vp->y = 0;
+}
+
+void video_driver_set_rgba(void)
+{
+ video_driver_lock();
+ video_driver_use_rgba = true;
+ video_driver_unlock();
+}
+
+void video_driver_unset_rgba(void)
+{
+ video_driver_lock();
+ video_driver_use_rgba = false;
+ video_driver_unlock();
+}
+
+bool video_driver_supports_rgba(void)
+{
+ bool tmp;
+ video_driver_lock();
+ tmp = video_driver_use_rgba;
+ video_driver_unlock();
+ return tmp;
+}
+
+bool video_driver_get_next_video_out(void)
+{
+ if (!video_driver_poke)
+ return false;
+
+ if (!video_driver_poke->get_video_output_next)
+ return video_context_driver_get_video_output_next();
+ video_driver_poke->get_video_output_next(video_driver_data);
+ return true;
+}
+
+bool video_driver_get_prev_video_out(void)
+{
+ if (!video_driver_poke)
+ return false;
+
+ if (!video_driver_poke->get_video_output_prev)
+ return video_context_driver_get_video_output_prev();
+ video_driver_poke->get_video_output_prev(video_driver_data);
+ return true;
+}
+
+bool video_driver_init(bool *video_is_threaded)
+{
+ video_driver_lock_new();
+ video_driver_filter_free();
+ video_driver_set_cached_frame_ptr(NULL);
+ return video_driver_init_internal(video_is_threaded);
+}
+
+void video_driver_destroy_data(void)
+{
+ video_driver_data = NULL;
+}
+
+void video_driver_free(void)
+{
+ video_driver_free_internal();
+ video_driver_lock_free();
+ video_driver_data = NULL;
+ video_driver_set_cached_frame_ptr(NULL);
+}
+
+void video_driver_monitor_reset(void)
+{
+ video_driver_frame_time_count = 0;
+}
+
+void video_driver_set_aspect_ratio(void)
+{
+ settings_t *settings = config_get_ptr();
+
+ switch (settings->uints.video_aspect_ratio_idx)
+ {
+ case ASPECT_RATIO_SQUARE:
+ video_driver_set_viewport_square_pixel();
+ break;
+
+ case ASPECT_RATIO_CORE:
+ video_driver_set_viewport_core();
+ break;
+
+ case ASPECT_RATIO_CONFIG:
+ video_driver_set_viewport_config();
+ break;
+
+ default:
+ break;
+ }
+
+ video_driver_set_aspect_ratio_value(
+ aspectratio_lut[settings->uints.video_aspect_ratio_idx].value);
+
+ if (!video_driver_poke || !video_driver_poke->set_aspect_ratio)
+ return;
+ video_driver_poke->set_aspect_ratio(
+ video_driver_data, settings->uints.video_aspect_ratio_idx);
+}
+
+void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bool keep_aspect)
+{
+ gfx_ctx_aspect_t aspect_data;
+ float device_aspect = (float)vp->full_width / vp->full_height;
+ settings_t* settings = config_get_ptr();
+
+ aspect_data.aspect = &device_aspect;
+ aspect_data.width = vp->full_width;
+ aspect_data.height = vp->full_height;
+
+ video_context_driver_translate_aspect(&aspect_data);
+
+ vp->x = 0;
+ vp->y = 0;
+ vp->width = vp->full_width;
+ vp->height = vp->full_height;
+
+ if (settings->bools.video_scale_integer && !force_full)
+ {
+ video_viewport_get_scaled_integer(
+ vp, vp->full_width, vp->full_height, video_driver_get_aspect_ratio(), keep_aspect);
+ }
+ else if (keep_aspect && !force_full)
+ {
+ float desired_aspect = video_driver_get_aspect_ratio();
+
+#if defined(HAVE_MENU)
+ if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
+ {
+ const struct video_viewport* custom = video_viewport_get_custom();
+
+ vp->x = custom->x;
+ vp->y = custom->y;
+ vp->width = custom->width;
+ vp->height = custom->height;
+ }
+ else
+#endif
+ {
+ float delta;
+
+ 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;
+ vp->x = (int)roundf(vp->full_width * (0.5f - delta));
+ vp->width = (unsigned)roundf(2.0f * vp->full_width * delta);
+ vp->y = 0;
+ vp->height = vp->full_height;
+ }
+ else
+ {
+ vp->x = 0;
+ vp->width = vp->full_width;
+ delta = (device_aspect / desired_aspect - 1.0f)
+ / 2.0f + 0.5f;
+ vp->y = (int)roundf(vp->full_height * (0.5f - delta));
+ vp->height = (unsigned)roundf(2.0f * vp->full_height * delta);
+ }
+ }
+ }
+
+#if defined(RARCH_MOBILE)
+ /* In portrait mode, we want viewport to gravitate to top of screen. */
+ if (device_aspect < 1.0f)
+ vp->y = 0;
+#endif
+}
+
+void video_driver_show_mouse(void)
+{
+ if (video_driver_poke && video_driver_poke->show_mouse)
+ video_driver_poke->show_mouse(video_driver_data, true);
+}
+
+void video_driver_hide_mouse(void)
+{
+ if (video_driver_poke && video_driver_poke->show_mouse)
+ video_driver_poke->show_mouse(video_driver_data, false);
+}
+
+void video_driver_set_nonblock_state(bool toggle)
+{
+ if (current_video->set_nonblock_state)
+ current_video->set_nonblock_state(video_driver_data, toggle);
+}
+
+bool video_driver_find_driver(void)
+{
+ int i;
+ driver_ctx_info_t drv;
+ settings_t *settings = config_get_ptr();
+
+ if (video_driver_is_hw_context())
+ {
+ struct retro_hw_render_callback *hwr = video_driver_get_hw_context();
+
+ current_video = NULL;
+
+ (void)hwr;
+
+#if defined(HAVE_VULKAN)
+ if (hwr && hw_render_context_is_vulkan(hwr->context_type))
+ {
+ RARCH_LOG("[Video]: Using HW render, Vulkan driver forced.\n");
+ current_video = &video_vulkan;
+ }
+#endif
+
+#if defined(HAVE_OPENGL)
+ if (hwr && hw_render_context_is_gl(hwr->context_type))
+ {
+ RARCH_LOG("[Video]: Using HW render, OpenGL driver forced.\n");
+ current_video = &video_gl;
+ }
+#endif
+
+ if (current_video)
+ return true;
+ }
+
+ if (frontend_driver_has_get_video_driver_func())
+ {
+ current_video = (video_driver_t*)frontend_driver_get_video_driver();
+
+ if (current_video)
+ return true;
+ RARCH_WARN("Frontend supports get_video_driver() but did not specify one.\n");
+ }
+
+ drv.label = "video_driver";
+ drv.s = settings->arrays.video_driver;
+
+ driver_ctl(RARCH_DRIVER_CTL_FIND_INDEX, &drv);
+
+ i = (int)drv.len;
+
+ if (i >= 0)
+ current_video = (video_driver_t*)video_driver_find_handle(i);
+ else
+ {
+ if (verbosity_is_enabled())
+ {
+ unsigned d;
+ RARCH_ERR("Couldn't find any video driver named \"%s\"\n",
+ settings->arrays.video_driver);
+ RARCH_LOG_OUTPUT("Available video drivers are:\n");
+ for (d = 0; video_driver_find_handle(d); d++)
+ RARCH_LOG_OUTPUT("\t%s\n", video_driver_find_ident(d));
+ RARCH_WARN("Going to default to first video driver...\n");
+ }
+
+ current_video = (video_driver_t*)video_driver_find_handle(0);
+
+ if (!current_video)
+ retroarch_fail(1, "find_video_driver()");
+ }
+ return true;
+}
+
+void video_driver_apply_state_changes(void)
+{
+ if (video_driver_poke &&
+ video_driver_poke->apply_state_changes)
+ video_driver_poke->apply_state_changes(video_driver_data);
+}
+
+bool video_driver_read_viewport(uint8_t *buffer, bool is_idle)
+{
+ if ( current_video->read_viewport
+ && current_video->read_viewport(
+ video_driver_data, buffer, is_idle))
+ return true;
+ return false;
+}
+
+bool video_driver_frame_filter_alive(void)
+{
+ return !!video_driver_state_filter;
+}
+
+bool video_driver_frame_filter_is_32bit(void)
+{
+ return video_driver_state_out_rgb32;
+}
+
+void video_driver_default_settings(void)
+{
+ global_t *global = global_get_ptr();
+
+ if (!global)
+ return;
+
+ global->console.screen.gamma_correction = DEFAULT_GAMMA;
+ global->console.flickerfilter_enable = false;
+ global->console.softfilter_enable = false;
+
+ global->console.screen.resolutions.current.id = 0;
+}
+
+void video_driver_load_settings(config_file_t *conf)
+{
+ bool tmp_bool = false;
+ global_t *global = global_get_ptr();
+
+ if (!conf)
+ return;
+
+#ifdef _XBOX
+ CONFIG_GET_BOOL_BASE(conf, global,
+ console.screen.gamma_correction, "gamma_correction");
+#else
+ CONFIG_GET_INT_BASE(conf, global,
+ console.screen.gamma_correction, "gamma_correction");
+#endif
+
+ if (config_get_bool(conf, "flicker_filter_enable",
+ &tmp_bool))
+ global->console.flickerfilter_enable = tmp_bool;
+
+ if (config_get_bool(conf, "soft_filter_enable",
+ &tmp_bool))
+ global->console.softfilter_enable = tmp_bool;
+
+ CONFIG_GET_INT_BASE(conf, global,
+ console.screen.soft_filter_index,
+ "soft_filter_index");
+ CONFIG_GET_INT_BASE(conf, global,
+ console.screen.resolutions.current.id,
+ "current_resolution_id");
+ CONFIG_GET_INT_BASE(conf, global,
+ console.screen.flicker_filter_index,
+ "flicker_filter_index");
+}
+
+void video_driver_save_settings(config_file_t *conf)
+{
+ global_t *global = global_get_ptr();
+ if (!conf)
+ return;
+
+#ifdef _XBOX
+ config_set_bool(conf, "gamma_correction",
+ global->console.screen.gamma_correction);
+#else
+ config_set_int(conf, "gamma_correction",
+ global->console.screen.gamma_correction);
+#endif
+ config_set_bool(conf, "flicker_filter_enable",
+ global->console.flickerfilter_enable);
+ config_set_bool(conf, "soft_filter_enable",
+ global->console.softfilter_enable);
+
+ config_set_int(conf, "soft_filter_index",
+ global->console.screen.soft_filter_index);
+ config_set_int(conf, "current_resolution_id",
+ global->console.screen.resolutions.current.id);
+ config_set_int(conf, "flicker_filter_index",
+ global->console.screen.flicker_filter_index);
+}
+
+void video_driver_reinit(void)
+{
+ struct retro_hw_render_callback *hwr =
+ video_driver_get_hw_context();
+
+ if (hwr->cache_context)
+ video_driver_cache_context = true;
+ else
+ video_driver_cache_context = false;
+
+ video_driver_cache_context_ack = false;
+ command_event(CMD_EVENT_RESET_CONTEXT, NULL);
+ video_driver_cache_context = false;
+}
+
+void video_driver_set_own_driver(void)
+{
+ video_driver_data_own = true;
+}
+
+void video_driver_unset_own_driver(void)
+{
+ video_driver_data_own = false;
+}
+
+bool video_driver_owns_driver(void)
+{
+ return video_driver_data_own;
+}
+
+bool video_driver_is_hw_context(void)
+{
+ bool is_hw_context = false;
+
+ video_driver_context_lock();
+ is_hw_context = (hw_render.context_type != RETRO_HW_CONTEXT_NONE);
+ video_driver_context_unlock();
+
+ return is_hw_context;
+}
+
+void video_driver_free_hw_context(void)
+{
+ video_driver_context_lock();
+
+ if (hw_render.context_destroy)
+ hw_render.context_destroy();
+
+ memset(&hw_render, 0, sizeof(hw_render));
+
+ video_driver_context_unlock();
+
+ hw_render_context_negotiation = NULL;
+}
+
+struct retro_hw_render_callback *video_driver_get_hw_context(void)
+{
+ return &hw_render;
+}
+
+const struct retro_hw_render_context_negotiation_interface *
+ video_driver_get_context_negotiation_interface(void)
+{
+ return hw_render_context_negotiation;
+}
+
+void video_driver_set_context_negotiation_interface(
+ const struct retro_hw_render_context_negotiation_interface *iface)
+{
+ hw_render_context_negotiation = iface;
+}
+
+bool video_driver_is_video_cache_context(void)
+{
+ return video_driver_cache_context;
+}
+
+void video_driver_set_video_cache_context_ack(void)
+{
+ video_driver_cache_context_ack = true;
+}
+
+void video_driver_unset_video_cache_context_ack(void)
+{
+ video_driver_cache_context_ack = false;
+}
+
+bool video_driver_is_video_cache_context_ack(void)
+{
+ return video_driver_cache_context_ack;
+}
+
+void video_driver_set_active(void)
+{
+ video_driver_active = true;
+}
+
+void video_driver_unset_active(void)
+{
+ video_driver_active = false;
+}
+
+bool video_driver_is_active(void)
+{
+ return video_driver_active;
+}
+
+void video_driver_get_record_status(
+ bool *has_gpu_record,
+ uint8_t **gpu_buf)
+{
+ *gpu_buf = video_driver_record_gpu_buffer;
+ *has_gpu_record = video_driver_record_gpu_buffer != NULL;
+}
+
+bool video_driver_gpu_record_init(unsigned size)
+{
+ video_driver_record_gpu_buffer = (uint8_t*)malloc(size);
+ if (!video_driver_record_gpu_buffer)
+ return false;
+ return true;
+}
+
+void video_driver_gpu_record_deinit(void)
+{
+ free(video_driver_record_gpu_buffer);
+ video_driver_record_gpu_buffer = NULL;
+}
+
+bool video_driver_get_current_software_framebuffer(
+ struct retro_framebuffer *fb)
+{
+ if (
+ video_driver_poke
+ && video_driver_poke->get_current_software_framebuffer
+ && video_driver_poke->get_current_software_framebuffer(
+ video_driver_data, fb))
+ return true;
+
+ return false;
+}
+
+bool video_driver_get_hw_render_interface(
+ const struct retro_hw_render_interface **iface)
+{
+ if (
+ video_driver_poke
+ && video_driver_poke->get_hw_render_interface
+ && video_driver_poke->get_hw_render_interface(
+ video_driver_data, iface))
+ return true;
+
+ return false;
+}
+
+bool video_driver_get_viewport_info(struct video_viewport *viewport)
+{
+ if (!current_video || !current_video->viewport_info)
+ return false;
+ current_video->viewport_info(video_driver_data, viewport);
+ return true;
+}
+
+void video_driver_set_title_buf(void)
+{
+ struct retro_system_info info;
+ core_get_system_info(&info);
+
+ fill_pathname_join_concat_noext(
+ video_driver_title_buf,
+ msg_hash_to_str(MSG_PROGRAM),
+ " ",
+ info.library_name,
+ sizeof(video_driver_title_buf));
+ strlcat(video_driver_title_buf,
+ " ", sizeof(video_driver_title_buf));
+ strlcat(video_driver_title_buf,
+ info.library_version,
+ sizeof(video_driver_title_buf));
+}
+
+/**
+ * video_viewport_get_scaled_integer:
+ * @vp : Viewport handle
+ * @width : Width.
+ * @height : Height.
+ * @aspect_ratio : Aspect ratio (in float).
+ * @keep_aspect : Preserve aspect ratio?
+ *
+ * Gets viewport scaling dimensions based on
+ * scaled integer aspect ratio.
+ **/
+void video_viewport_get_scaled_integer(struct video_viewport *vp,
+ unsigned width, unsigned height,
+ float aspect_ratio, bool keep_aspect)
+{
+ int padding_x = 0;
+ int padding_y = 0;
+ settings_t *settings = config_get_ptr();
+
+ if (settings->uints.video_aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
+ {
+ struct video_viewport *custom = video_viewport_get_custom();
+
+ if (custom)
+ {
+ padding_x = width - custom->width;
+ padding_y = height - custom->height;
+ width = custom->width;
+ height = custom->height;
+ }
+ }
+ else
+ {
+ unsigned base_width;
+ /* Use system reported sizes as these define the
+ * geometry for the "normal" case. */
+ unsigned base_height =
+ video_driver_av_info.geometry.base_height;
+
+ if (base_height == 0)
+ base_height = 1;
+
+ /* Account for non-square pixels.
+ * This is sort of contradictory with the goal of integer scale,
+ * but it is desirable in some cases.
+ *
+ * If square pixels are used, base_height will be equal to
+ * system->av_info.base_height. */
+ base_width = (unsigned)roundf(base_height * aspect_ratio);
+
+ /* Make sure that we don't get 0x scale ... */
+ if (width >= base_width && height >= base_height)
+ {
+ if (keep_aspect)
+ {
+ /* X/Y scale must be same. */
+ unsigned max_scale = MIN(width / base_width,
+ height / base_height);
+ padding_x = width - base_width * max_scale;
+ padding_y = height - base_height * max_scale;
+ }
+ else
+ {
+ /* X/Y can be independent, each scaled as much as possible. */
+ padding_x = width % base_width;
+ padding_y = height % base_height;
+ }
+ }
+
+ width -= padding_x;
+ height -= padding_y;
+ }
+
+ vp->width = width;
+ vp->height = height;
+ vp->x = padding_x / 2;
+ vp->y = padding_y / 2;
+}
+
+struct retro_system_av_info *video_viewport_get_system_av_info(void)
+{
+ return &video_driver_av_info;
+}
+
+struct video_viewport *video_viewport_get_custom(void)
+{
+ settings_t *settings = config_get_ptr();
+ return &settings->video_viewport_custom;
+}
+
+unsigned video_pixel_get_alignment(unsigned pitch)
+{
+ if (pitch & 1)
+ return 1;
+ if (pitch & 2)
+ return 2;
+ if (pitch & 4)
+ return 4;
+ return 8;
+}
+
+/**
+ * video_driver_frame:
+ * @data : pointer to data of the video frame.
+ * @width : width of the video frame.
+ * @height : height of the video frame.
+ * @pitch : pitch of the video frame.
+ *
+ * Video frame render callback function.
+ **/
+void video_driver_frame(const void *data, unsigned width,
+ unsigned height, size_t pitch)
+{
+ static char video_driver_msg[256];
+ static char title[256];
+ video_frame_info_t video_info;
+ static retro_time_t curr_time;
+ static retro_time_t fps_time;
+ static float last_fps, frame_time;
+ unsigned output_width = 0;
+ unsigned output_height = 0;
+ unsigned output_pitch = 0;
+ const char *msg = NULL;
+ retro_time_t new_time =
+ cpu_features_get_time_usec();
+
+ if (!video_driver_active)
+ return;
+
+ if (video_driver_scaler_ptr && data &&
+ (video_driver_pix_fmt == RETRO_PIXEL_FORMAT_0RGB1555) &&
+ (data != RETRO_HW_FRAME_BUFFER_VALID))
+ {
+ if (video_pixel_frame_scale(
+ video_driver_scaler_ptr->scaler,
+ video_driver_scaler_ptr->scaler_out,
+ data, width, height, pitch))
+ {
+ data = video_driver_scaler_ptr->scaler_out;
+ pitch = video_driver_scaler_ptr->scaler->out_stride;
+ }
+ }
+
+ if (data)
+ frame_cache_data = data;
+ frame_cache_width = width;
+ frame_cache_height = height;
+ frame_cache_pitch = pitch;
+
+ video_driver_build_info(&video_info);
+
+ /* Get the amount of frames per seconds. */
+ if (video_driver_frame_count)
+ {
+ unsigned write_index =
+ video_driver_frame_time_count++ &
+ (MEASURE_FRAME_TIME_SAMPLES_COUNT - 1);
+ frame_time = new_time - fps_time;
+ video_driver_frame_time_samples[write_index] = frame_time;
+ fps_time = new_time;
+
+ if (video_driver_frame_count == 1)
+ strlcpy(title, video_driver_window_title, sizeof(title));
+
+ if ((video_driver_frame_count % FPS_UPDATE_INTERVAL) == 0)
+ {
+ char frames_text[64];
+ last_fps = TIME_TO_FPS(curr_time, new_time, FPS_UPDATE_INTERVAL);
+
+ if (video_info.fps_show || video_info.framecount_show)
+ {
+ if (video_info.fps_show)
+ {
+ snprintf(video_info.fps_text, sizeof(video_info.fps_text),
+ " || FPS: %6.1f ", last_fps);
+ }
+ if (video_info.framecount_show)
+ {
+ snprintf(frames_text,
+ sizeof(frames_text),
+ " || Frames: %" PRIu64,
+ (uint64_t)video_driver_frame_count);
+ }
+ snprintf(video_driver_window_title, sizeof(video_driver_window_title),
+ "%s%s%s", title,
+ video_info.fps_show ? video_info.fps_text : "",
+ video_info.framecount_show ? frames_text : "");
+ }
+ else
+ {
+ if (!string_is_equal(video_driver_window_title, title))
+ strlcpy(video_driver_window_title, title, sizeof(video_driver_window_title));
+ }
+
+ curr_time = new_time;
+ video_driver_window_title_update = true;
+ }
+
+ if (video_info.fps_show)
+ {
+ if (video_info.framecount_show)
+ snprintf(
+ video_info.fps_text,
+ sizeof(video_info.fps_text),
+ "FPS: %6.1f || %s: %" PRIu64,
+ last_fps,
+ msg_hash_to_str(MSG_FRAMES),
+ (uint64_t)video_driver_frame_count);
+ else
+ snprintf(
+ video_info.fps_text,
+ sizeof(video_info.fps_text),
+ "FPS: %6.1f",
+ last_fps);
+ }
+
+ if (video_info.fps_show && video_info.framecount_show)
+ snprintf(
+ video_info.fps_text,
+ sizeof(video_info.fps_text),
+ "FPS: %6.1f || %s: %" PRIu64,
+ last_fps,
+ msg_hash_to_str(MSG_FRAMES),
+ (uint64_t)video_driver_frame_count);
+ else if (video_info.framecount_show)
+ snprintf(
+ video_info.fps_text,
+ sizeof(video_info.fps_text),
+ "%s: %" PRIu64,
+ msg_hash_to_str(MSG_FRAMES),
+ (uint64_t)video_driver_frame_count);
+ else if (video_info.fps_show)
+ snprintf(
+ video_info.fps_text,
+ sizeof(video_info.fps_text),
+ "FPS: %6.1f",
+ last_fps);
+ }
+ else
+ {
+
+ curr_time = fps_time = new_time;
+
+ strlcpy(video_driver_window_title,
+ video_driver_title_buf,
+ sizeof(video_driver_window_title));
+
+ if (video_info.fps_show)
+ strlcpy(video_info.fps_text,
+ msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NOT_AVAILABLE),
+ sizeof(video_info.fps_text));
+
+ video_driver_window_title_update = true;
+ }
+
+ video_info.frame_rate = last_fps;
+ video_info.frame_time = frame_time / 1000.0f;
+ video_info.frame_count = (uint64_t) video_driver_frame_count;
+
+ /* Slightly messy code,
+ * but we really need to do processing before blocking on VSync
+ * for best possible scheduling.
+ */
+ if (
+ (
+ !video_driver_state_filter
+ || !video_info.post_filter_record
+ || !data
+ || video_driver_record_gpu_buffer
+ ) && recording_data
+ )
+ recording_dump_frame(data, width, height,
+ pitch, video_info.runloop_is_idle);
+
+ if (data && video_driver_state_filter &&
+ video_driver_frame_filter(data, &video_info, width, height, pitch,
+ &output_width, &output_height, &output_pitch))
+ {
+ data = video_driver_state_buffer;
+ width = output_width;
+ height = output_height;
+ pitch = output_pitch;
+ }
+
+ video_driver_msg[0] = '\0';
+
+ if ( video_info.font_enable
+ && runloop_msg_queue_pull((const char**)&msg)
+ && msg)
+ {
+#ifdef HAVE_THREADS
+ /* the msg pointer may point to data modified by another thread */
+ runloop_msg_queue_lock();
+#endif
+ strlcpy(video_driver_msg, msg, sizeof(video_driver_msg));
+#ifdef HAVE_THREADS
+ runloop_msg_queue_unlock();
+#endif
+ }
+
+ if (video_info.statistics_show)
+ {
+ audio_statistics_t audio_stats = {0.0f};
+ double stddev = 0.0;
+ struct retro_system_av_info *av_info = &video_driver_av_info;
+ unsigned red = 255;
+ unsigned green = 255;
+ unsigned blue = 255;
+ unsigned alpha = 255;
+
+ video_monitor_fps_statistics(NULL, &stddev, NULL);
+
+ video_info.osd_stat_params.x = 0.010f;
+ video_info.osd_stat_params.y = 0.950f;
+ video_info.osd_stat_params.scale = 1.0f;
+ video_info.osd_stat_params.full_screen = true;
+ video_info.osd_stat_params.drop_x = -2;
+ video_info.osd_stat_params.drop_y = -2;
+ video_info.osd_stat_params.drop_mod = 0.3f;
+ video_info.osd_stat_params.drop_alpha = 1.0f;
+ video_info.osd_stat_params.color = COLOR_ABGR(
+ red, green, blue, alpha);
+
+ compute_audio_buffer_statistics(&audio_stats);
+
+ snprintf(video_info.stat_text,
+ sizeof(video_info.stat_text),
+ "Video Statistics:\n -Frame rate: %6.2f fps\n -Frame time: %6.2f ms\n -Frame time deviation: %.3f %%\n"
+ " -Frame count: %" PRIu64"\n -Viewport: %d x %d x %3.2f\n"
+ "Audio Statistics:\n -Average buffer saturation: %.2f %%\n -Standard deviation: %.2f %%\n -Time spent close to underrun: %.2f %%\n -Time spent close to blocking: %.2f %%\n -Sample count: %d\n"
+ "Core Geometry:\n -Size: %u x %u\n -Max Size: %u x %u\n -Aspect: %3.2f\nCore Timing:\n -FPS: %3.2f\n -Sample Rate: %6.2f\n",
+ video_info.frame_rate,
+ video_info.frame_time,
+ 100.0 * stddev,
+ video_info.frame_count,
+ video_info.width,
+ video_info.height,
+ video_info.refresh_rate,
+ audio_stats.average_buffer_saturation,
+ audio_stats.std_deviation_percentage,
+ audio_stats.close_to_underrun,
+ audio_stats.close_to_blocking,
+ audio_stats.samples,
+ av_info->geometry.base_width,
+ av_info->geometry.base_height,
+ av_info->geometry.max_width,
+ av_info->geometry.max_height,
+ av_info->geometry.aspect_ratio,
+ av_info->timing.fps,
+ av_info->timing.sample_rate);
+
+ /* TODO/FIXME - add OSD chat text here */
+#if 0
+ snprintf(video_info.chat_text, sizeof(video_info.chat_text),
+ "anon: does retroarch netplay have in-game chat?\nradius: I don't know \u2605");
+#endif
+ }
+
+ video_driver_active = current_video->frame(
+ video_driver_data, data, width, height,
+ video_driver_frame_count,
+ (unsigned)pitch, video_driver_msg, &video_info);
+
+ video_driver_frame_count++;
+
+ /* Display the FPS, with a higher priority. */
+ if (video_info.fps_show || video_info.framecount_show)
+ runloop_msg_queue_push(video_info.fps_text, 2, 1, true);
+
+ /* trigger set resolution*/
+ if (video_info.crt_switch_resolution)
+ {
+ video_driver_crt_switching_active = true;
+
+ if (video_info.crt_switch_resolution_super == 2560)
+ width = 2560;
+ if (video_info.crt_switch_resolution_super == 3840)
+ width = 3840;
+ if (video_info.crt_switch_resolution_super == 1920)
+ width = 1920;
+ crt_switch_res_core(width, height, video_driver_core_hz, video_info.crt_switch_resolution, video_info.crt_switch_center_adjust, video_info.monitor_index);
+ }
+ else if (!video_info.crt_switch_resolution)
+ video_driver_crt_switching_active = false;
+
+ /* trigger set resolution*/
+}
+
+void crt_switch_driver_reinit(void)
+{
+ video_driver_reinit();
+}
+
+void video_driver_display_type_set(enum rarch_display_type type)
+{
+ video_driver_display_type = type;
+}
+
+uintptr_t video_driver_display_get(void)
+{
+ return video_driver_display;
+}
+
+void video_driver_display_set(uintptr_t idx)
+{
+ video_driver_display = idx;
+}
+
+enum rarch_display_type video_driver_display_type_get(void)
+{
+ return video_driver_display_type;
+}
+
+void video_driver_window_set(uintptr_t idx)
+{
+ video_driver_window = idx;
+}
+
+uintptr_t video_driver_window_get(void)
+{
+ return video_driver_window;
+}
+
+bool video_driver_texture_load(void *data,
+ enum texture_filter_type filter_type,
+ uintptr_t *id)
+{
+ if (!id || !video_driver_poke || !video_driver_poke->load_texture)
+ return false;
+
+ *id = video_driver_poke->load_texture(video_driver_data, data,
+ video_driver_is_threaded_internal(),
+ filter_type);
+
+ return true;
+}
+
+bool video_driver_texture_unload(uintptr_t *id)
+{
+ if (!video_driver_poke || !video_driver_poke->unload_texture)
+ return false;
+
+ video_driver_poke->unload_texture(video_driver_data, *id);
+ *id = 0;
+ return true;
+}
+
+static void video_shader_driver_use_null(void *data,
+ void *shader_data, unsigned idx, bool set_active)
+{
+ (void)data;
+ (void)idx;
+ (void)set_active;
+}
+
+static bool video_driver_cb_set_coords(void *handle_data,
+ void *shader_data, const struct video_coords *coords)
+{
+ video_shader_ctx_coords_t ctx_coords;
+ ctx_coords.handle_data = handle_data;
+ ctx_coords.data = coords;
+
+ video_driver_set_coords(&ctx_coords);
+ return true;
+}
+
+void video_driver_build_info(video_frame_info_t *video_info)
+{
+ bool is_perfcnt_enable = false;
+ bool is_paused = false;
+ bool is_idle = false;
+ bool is_slowmotion = false;
+ settings_t *settings = NULL;
+ video_viewport_t *custom_vp = NULL;
+ struct retro_hw_render_callback *hwr =
+ video_driver_get_hw_context();
+#ifdef HAVE_THREADS
+ bool is_threaded = video_driver_is_threaded_internal();
+ video_driver_threaded_lock(is_threaded);
+#endif
+ settings = config_get_ptr();
+ custom_vp = &settings->video_viewport_custom;
+ video_info->refresh_rate = settings->floats.video_refresh_rate;
+ video_info->crt_switch_resolution = settings->uints.crt_switch_resolution;
+ video_info->crt_switch_resolution_super = settings->uints.crt_switch_resolution_super;
+ video_info->crt_switch_center_adjust = settings->ints.crt_switch_center_adjust;
+ video_info->black_frame_insertion = settings->bools.video_black_frame_insertion;
+ video_info->hard_sync = settings->bools.video_hard_sync;
+ video_info->hard_sync_frames = settings->uints.video_hard_sync_frames;
+ video_info->fps_show = settings->bools.video_fps_show;
+ video_info->statistics_show = settings->bools.video_statistics_show;
+ video_info->framecount_show = settings->bools.video_framecount_show;
+ video_info->scale_integer = settings->bools.video_scale_integer;
+ video_info->aspect_ratio_idx = settings->uints.video_aspect_ratio_idx;
+ video_info->post_filter_record = settings->bools.video_post_filter_record;
+ video_info->input_menu_swap_ok_cancel_buttons = settings->bools.input_menu_swap_ok_cancel_buttons;
+ video_info->max_swapchain_images = settings->uints.video_max_swapchain_images;
+ video_info->windowed_fullscreen = settings->bools.video_windowed_fullscreen;
+ video_info->fullscreen = settings->bools.video_fullscreen || retroarch_is_forced_fullscreen();
+ video_info->monitor_index = settings->uints.video_monitor_index;
+ video_info->shared_context = settings->bools.video_shared_context;
+
+ if (libretro_get_shared_context() && hwr && hwr->context_type != RETRO_HW_CONTEXT_NONE)
+ video_info->shared_context = true;
+
+ video_info->font_enable = settings->bools.video_font_enable;
+ video_info->font_msg_pos_x = settings->floats.video_msg_pos_x;
+ video_info->font_msg_pos_y = settings->floats.video_msg_pos_y;
+ video_info->font_msg_color_r = settings->floats.video_msg_color_r;
+ video_info->font_msg_color_g = settings->floats.video_msg_color_g;
+ video_info->font_msg_color_b = settings->floats.video_msg_color_b;
+ video_info->custom_vp_x = custom_vp->x;
+ video_info->custom_vp_y = custom_vp->y;
+ video_info->custom_vp_width = custom_vp->width;
+ video_info->custom_vp_height = custom_vp->height;
+ video_info->custom_vp_full_width = custom_vp->full_width;
+ video_info->custom_vp_full_height = custom_vp->full_height;
+
+ video_info->fps_text[0] = '\0';
+
+ video_info->width = video_driver_width;
+ video_info->height = video_driver_height;
+
+ video_info->use_rgba = video_driver_use_rgba;
+
+ video_info->libretro_running = false;
+ video_info->msg_bgcolor_enable = settings->bools.video_msg_bgcolor_enable;
+
+#ifdef HAVE_MENU
+ video_info->menu_is_alive = menu_driver_is_alive();
+ video_info->menu_footer_opacity = settings->floats.menu_footer_opacity;
+ video_info->menu_header_opacity = settings->floats.menu_header_opacity;
+ video_info->materialui_color_theme = settings->uints.menu_materialui_color_theme;
+ video_info->ozone_color_theme = settings->uints.menu_ozone_color_theme;
+ video_info->menu_shader_pipeline = settings->uints.menu_xmb_shader_pipeline;
+ video_info->xmb_theme = settings->uints.menu_xmb_theme;
+ video_info->xmb_color_theme = settings->uints.menu_xmb_color_theme;
+ video_info->timedate_enable = settings->bools.menu_timedate_enable;
+ video_info->battery_level_enable = settings->bools.menu_battery_level_enable;
+ video_info->xmb_shadows_enable = settings->bools.menu_xmb_shadows_enable;
+ video_info->xmb_alpha_factor = settings->uints.menu_xmb_alpha_factor;
+ video_info->menu_wallpaper_opacity = settings->floats.menu_wallpaper_opacity;
+ video_info->menu_framebuffer_opacity = settings->floats.menu_framebuffer_opacity;
+
+ video_info->libretro_running = core_is_game_loaded();
+#else
+ video_info->menu_is_alive = false;
+ video_info->menu_footer_opacity = 0.0f;
+ video_info->menu_header_opacity = 0.0f;
+ video_info->materialui_color_theme = 0;
+ video_info->menu_shader_pipeline = 0;
+ video_info->xmb_color_theme = 0;
+ video_info->xmb_theme = 0;
+ video_info->timedate_enable = false;
+ video_info->battery_level_enable = false;
+ video_info->xmb_shadows_enable = false;
+ video_info->xmb_alpha_factor = 0.0f;
+ video_info->menu_framebuffer_opacity = 0.0f;
+ video_info->menu_wallpaper_opacity = 0.0f;
+#endif
+
+ runloop_get_status(&is_paused, &is_idle, &is_slowmotion, &is_perfcnt_enable);
+
+ video_info->is_perfcnt_enable = is_perfcnt_enable;
+ video_info->runloop_is_paused = is_paused;
+ video_info->runloop_is_idle = is_idle;
+ video_info->runloop_is_slowmotion = is_slowmotion;
+
+ video_info->input_driver_nonblock_state = input_driver_is_nonblock_state();
+
+ video_info->context_data = video_context_data;
+ video_info->shader_driver = current_shader;
+ video_info->shader_data = current_shader_data;
+
+ video_info->cb_update_window_title = current_video_context.update_window_title;
+ video_info->cb_swap_buffers = current_video_context.swap_buffers;
+ video_info->cb_get_metrics = current_video_context.get_metrics;
+ video_info->cb_set_resize = current_video_context.set_resize;
+
+ video_info->cb_set_mvp = video_driver_cb_shader_set_mvp;
+
+ video_info->userdata = video_driver_get_ptr(false);
+
+#ifdef HAVE_THREADS
+ video_driver_threaded_unlock(is_threaded);
+#endif
+}
+
+/**
+ * video_driver_translate_coord_viewport:
+ * @mouse_x : Pointer X coordinate.
+ * @mouse_y : Pointer Y coordinate.
+ * @res_x : Scaled X coordinate.
+ * @res_y : Scaled Y coordinate.
+ * @res_screen_x : Scaled screen X coordinate.
+ * @res_screen_y : Scaled screen Y coordinate.
+ *
+ * Translates pointer [X,Y] coordinates into scaled screen
+ * coordinates based on viewport info.
+ *
+ * Returns: true (1) if successful, false if video driver doesn't support
+ * viewport info.
+ **/
+bool video_driver_translate_coord_viewport(
+ struct video_viewport *vp,
+ int mouse_x, int mouse_y,
+ int16_t *res_x, int16_t *res_y,
+ int16_t *res_screen_x, int16_t *res_screen_y)
+{
+ int scaled_screen_x, scaled_screen_y, scaled_x, scaled_y;
+ int norm_vp_width = (int)vp->width;
+ int norm_vp_height = (int)vp->height;
+ int norm_full_vp_width = (int)vp->full_width;
+ int norm_full_vp_height = (int)vp->full_height;
+
+ if (norm_full_vp_width <= 0 || norm_full_vp_height <= 0)
+ return false;
+
+ if (mouse_x >= 0 && mouse_x <= norm_full_vp_width)
+ scaled_screen_x = ((2 * mouse_x * 0x7fff)
+ / norm_full_vp_width) - 0x7fff;
+ else
+ scaled_screen_x = -0x8000; /* OOB */
+
+ if (mouse_y >= 0 && mouse_y <= norm_full_vp_height)
+ scaled_screen_y = ((2 * mouse_y * 0x7fff)
+ / norm_full_vp_height) - 0x7fff;
+ else
+ scaled_screen_y = -0x8000; /* OOB */
+
+ mouse_x -= vp->x;
+ mouse_y -= vp->y;
+
+ if (mouse_x >= 0 && mouse_x <= norm_vp_width)
+ scaled_x = ((2 * mouse_x * 0x7fff)
+ / norm_vp_width) - 0x7fff;
+ else
+ scaled_x = -0x8000; /* OOB */
+
+ if (mouse_y >= 0 && mouse_y <= norm_vp_height)
+ scaled_y = ((2 * mouse_y * 0x7fff)
+ / norm_vp_height) - 0x7fff;
+ else
+ scaled_y = -0x8000; /* OOB */
+
+ *res_x = scaled_x;
+ *res_y = scaled_y;
+ *res_screen_x = scaled_screen_x;
+ *res_screen_y = scaled_screen_y;
+
+ return true;
+}
+
+void video_driver_get_window_title(char *buf, unsigned len)
+{
+ if (buf && video_driver_window_title_update)
+ {
+ strlcpy(buf, video_driver_window_title, len);
+ video_driver_window_title_update = false;
+ }
+}
+
+void video_driver_get_status(uint64_t *frame_count, bool * is_alive,
+ bool *is_focused)
+{
+ *frame_count = video_driver_frame_count;
+ *is_alive = current_video ?
+ current_video->alive(video_driver_data) : true;
+ *is_focused = video_driver_cb_has_focus();
+}
+
+/**
+ * find_video_context_driver_driver_index:
+ * @ident : Identifier of resampler driver to find.
+ *
+ * Finds graphics context driver index by @ident name.
+ *
+ * Returns: graphics context driver index if driver was found, otherwise
+ * -1.
+ **/
+static int find_video_context_driver_index(const char *ident)
+{
+ unsigned i;
+ for (i = 0; gfx_ctx_drivers[i]; i++)
+ if (string_is_equal_noncase(ident, gfx_ctx_drivers[i]->ident))
+ return i;
+ return -1;
+}
+
+/**
+ * find_prev_context_driver:
+ *
+ * Finds previous driver in graphics context driver array.
+ **/
+bool video_context_driver_find_prev_driver(void)
+{
+ settings_t *settings = config_get_ptr();
+ int i = find_video_context_driver_index(
+ settings->arrays.video_context_driver);
+
+ if (i > 0)
+ {
+ strlcpy(settings->arrays.video_context_driver,
+ gfx_ctx_drivers[i - 1]->ident,
+ sizeof(settings->arrays.video_context_driver));
+ return true;
+ }
+
+ RARCH_WARN("Couldn't find any previous video context driver.\n");
+ return false;
+}
+
+/**
+ * find_next_context_driver:
+ *
+ * Finds next driver in graphics context driver array.
+ **/
+bool video_context_driver_find_next_driver(void)
+{
+ settings_t *settings = config_get_ptr();
+ int i = find_video_context_driver_index(
+ settings->arrays.video_context_driver);
+
+ if (i >= 0 && gfx_ctx_drivers[i + 1])
+ {
+ strlcpy(settings->arrays.video_context_driver,
+ gfx_ctx_drivers[i + 1]->ident,
+ sizeof(settings->arrays.video_context_driver));
+ return true;
+ }
+
+ RARCH_WARN("Couldn't find any next video context driver.\n");
+ return false;
+}
+
+/**
+ * video_context_driver_init:
+ * @data : Input data.
+ * @ctx : Graphics context driver to initialize.
+ * @ident : Identifier of graphics context driver to find.
+ * @api : API of higher-level graphics API.
+ * @major : Major version number of higher-level graphics API.
+ * @minor : Minor version number of higher-level graphics API.
+ * @hw_render_ctx : Request a graphics context driver capable of
+ * hardware rendering?
+ *
+ * Initialize graphics context driver.
+ *
+ * Returns: graphics context driver if successfully initialized,
+ * otherwise NULL.
+ **/
+static const gfx_ctx_driver_t *video_context_driver_init(
+ void *data,
+ const gfx_ctx_driver_t *ctx,
+ const char *ident,
+ enum gfx_ctx_api api, unsigned major,
+ unsigned minor, bool hw_render_ctx,
+ void **ctx_data)
+{
+ video_frame_info_t video_info;
+
+ if (!ctx->bind_api(data, api, major, minor))
+ {
+ RARCH_WARN("Failed to bind API (#%u, version %u.%u)"
+ " on context driver \"%s\".\n",
+ (unsigned)api, major, minor, ctx->ident);
+
+ return NULL;
+ }
+
+ video_driver_build_info(&video_info);
+
+ if (!(*ctx_data = ctx->init(&video_info, data)))
+ return NULL;
+
+ if (ctx->bind_hw_render)
+ ctx->bind_hw_render(*ctx_data,
+ video_info.shared_context && hw_render_ctx);
+
+ return ctx;
+}
+
+/**
+ * video_context_driver_init_first:
+ * @data : Input data.
+ * @ident : Identifier of graphics context driver to find.
+ * @api : API of higher-level graphics API.
+ * @major : Major version number of higher-level graphics API.
+ * @minor : Minor version number of higher-level graphics API.
+ * @hw_render_ctx : Request a graphics context driver capable of
+ * hardware rendering?
+ *
+ * Finds first suitable graphics context driver and initializes.
+ *
+ * Returns: graphics context driver if found, otherwise NULL.
+ **/
+const gfx_ctx_driver_t *video_context_driver_init_first(void *data,
+ const char *ident, enum gfx_ctx_api api, unsigned major,
+ unsigned minor, bool hw_render_ctx, void **ctx_data)
+{
+ int i = find_video_context_driver_index(ident);
+
+ if (i >= 0)
+ {
+ const gfx_ctx_driver_t *ctx = video_context_driver_init(data, gfx_ctx_drivers[i], ident,
+ api, major, minor, hw_render_ctx, ctx_data);
+ if (ctx)
+ {
+ video_context_data = *ctx_data;
+ return ctx;
+ }
+ }
+
+ for (i = 0; gfx_ctx_drivers[i]; i++)
+ {
+ const gfx_ctx_driver_t *ctx =
+ video_context_driver_init(data, gfx_ctx_drivers[i], ident,
+ api, major, minor, hw_render_ctx, ctx_data);
+
+ if (ctx)
+ {
+ video_context_data = *ctx_data;
+ return ctx;
+ }
+ }
+
+ return NULL;
+}
+
+bool video_context_driver_init_image_buffer(const video_info_t *data)
+{
+ if (
+ current_video_context.image_buffer_init
+ && current_video_context.image_buffer_init(
+ video_context_data, data))
+ return true;
+ return false;
+}
+
+bool video_context_driver_write_to_image_buffer(gfx_ctx_image_t *img)
+{
+ if (
+ current_video_context.image_buffer_write
+ && current_video_context.image_buffer_write(video_context_data,
+ img->frame, img->width, img->height, img->pitch,
+ img->rgb32, img->index, img->handle))
+ return true;
+ return false;
+}
+
+bool video_context_driver_get_video_output_prev(void)
+{
+ if (!current_video_context.get_video_output_prev)
+ return false;
+ current_video_context.get_video_output_prev(video_context_data);
+ return true;
+}
+
+bool video_context_driver_get_video_output_next(void)
+{
+ if (!current_video_context.get_video_output_next)
+ return false;
+ current_video_context.get_video_output_next(video_context_data);
+ return true;
+}
+
+void video_context_driver_make_current(bool release)
+{
+ if (current_video_context.make_current)
+ current_video_context.make_current(release);
+}
+
+bool video_context_driver_translate_aspect(gfx_ctx_aspect_t *aspect)
+{
+ if (!video_context_data || !aspect)
+ return false;
+ if (!current_video_context.translate_aspect)
+ return false;
+ *aspect->aspect = current_video_context.translate_aspect(
+ video_context_data, aspect->width, aspect->height);
+ return true;
+}
+
+void video_context_driver_free(void)
+{
+ if (current_video_context.destroy)
+ current_video_context.destroy(video_context_data);
+ video_context_driver_destroy();
+ video_context_data = NULL;
+}
+
+bool video_context_driver_get_video_output_size(gfx_ctx_size_t *size_data)
+{
+ if (!size_data)
+ return false;
+ if (!current_video_context.get_video_output_size)
+ return false;
+ current_video_context.get_video_output_size(video_context_data,
+ size_data->width, size_data->height);
+ return true;
+}
+
+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 = 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)
+ current_interval = -1;
+ current_video_context.swap_interval(video_context_data, current_interval);
+ return true;
+}
+
+bool video_context_driver_get_proc_address(gfx_ctx_proc_address_t *proc)
+{
+ if (!current_video_context.get_proc_address)
+ return false;
+
+ proc->addr = current_video_context.get_proc_address(proc->sym);
+
+ return true;
+}
+
+bool video_context_driver_get_metrics(gfx_ctx_metrics_t *metrics)
+{
+ if (
+ current_video_context.get_metrics(video_context_data,
+ metrics->type,
+ metrics->value))
+ return true;
+ return false;
+}
+
+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 (!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;
+}
+
+bool video_context_driver_input_driver(gfx_ctx_input_t *inp)
+{
+ settings_t *settings = config_get_ptr();
+ const char *joypad_name = settings ?
+ settings->arrays.input_joypad_driver : NULL;
+
+ if (!current_video_context.input_driver)
+ return false;
+ current_video_context.input_driver(
+ video_context_data, joypad_name,
+ inp->input, inp->input_data);
+ return true;
+}
+
+bool video_context_driver_suppress_screensaver(bool *bool_data)
+{
+ if ( video_context_data
+ && current_video_context.suppress_screensaver(
+ video_context_data, *bool_data))
+ return true;
+ return false;
+}
+
+bool video_context_driver_get_ident(gfx_ctx_ident_t *ident)
+{
+ if (!ident)
+ return false;
+ ident->ident = current_video_context.ident;
+ return true;
+}
+
+bool video_context_driver_set_video_mode(gfx_ctx_mode_t *mode_info)
+{
+ video_frame_info_t video_info;
+
+ if (!current_video_context.set_video_mode)
+ return false;
+
+ video_driver_build_info(&video_info);
+
+ if (!current_video_context.set_video_mode(
+ video_context_data, &video_info, mode_info->width,
+ mode_info->height, mode_info->fullscreen))
+ return false;
+ return true;
+}
+
+bool video_context_driver_get_video_size(gfx_ctx_mode_t *mode_info)
+{
+ if (!current_video_context.get_video_size)
+ return false;
+ current_video_context.get_video_size(video_context_data,
+ &mode_info->width, &mode_info->height);
+ return true;
+}
+
+bool video_context_driver_show_mouse(bool *bool_data)
+{
+ if (!current_video_context.show_mouse)
+ return false;
+ current_video_context.show_mouse(video_context_data, *bool_data);
+ return true;
+}
+
+static bool video_context_driver_get_flags(gfx_ctx_flags_t *flags)
+{
+ 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;
+
+ flags->flags = 0;
+
+ if (video_context_driver_get_flags(flags))
+ if (BIT32_GET(flags->flags, flag))
+ return true;
+
+ return false;
+}
+
+bool video_context_driver_set_flags(gfx_ctx_flags_t *flags)
+{
+ if (!flags)
+ return false;
+ if (!current_video_context.set_flags)
+ {
+ deferred_flag_data.flags = flags->flags;
+ deferred_video_context_driver_set_flags = true;
+ return false;
+ }
+
+ current_video_context.set_flags(video_context_data, flags->flags);
+ return true;
+}
+
+enum gfx_ctx_api video_context_driver_get_api(void)
+{
+ enum gfx_ctx_api ctx_api = video_context_data ?
+ current_video_context.get_api(video_context_data) : GFX_CTX_NONE;
+
+ if (ctx_api == GFX_CTX_NONE)
+ {
+ const char *video_driver = video_driver_get_ident();
+ if (string_is_equal(video_driver, "d3d9"))
+ return GFX_CTX_DIRECT3D9_API;
+ else if (string_is_equal(video_driver, "d3d10"))
+ return GFX_CTX_DIRECT3D10_API;
+ else if (string_is_equal(video_driver, "d3d11"))
+ return GFX_CTX_DIRECT3D11_API;
+ else if (string_is_equal(video_driver, "d3d12"))
+ return GFX_CTX_DIRECT3D12_API;
+ else if (string_is_equal(video_driver, "gx2"))
+ return GFX_CTX_GX2_API;
+ else if (string_is_equal(video_driver, "gx"))
+ return GFX_CTX_GX_API;
+ else if (string_is_equal(video_driver, "gl"))
+ return GFX_CTX_OPENGL_API;
+ else if (string_is_equal(video_driver, "vulkan"))
+ return GFX_CTX_VULKAN_API;
+ else if (string_is_equal(video_driver, "metal"))
+ return GFX_CTX_METAL_API;
+
+ return GFX_CTX_NONE;
+ }
+
+ return ctx_api;
+}
+
+bool video_driver_has_windowed(void)
+{
+#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
+ if (video_driver_data && current_video->has_windowed)
+ return current_video->has_windowed(video_driver_data);
+ else if (video_context_data && current_video_context.has_windowed)
+ return current_video_context.has_windowed(video_context_data);
+#endif
+ return false;
+}
+
+bool video_driver_cached_frame_has_valid_framebuffer(void)
+{
+ if (frame_cache_data)
+ return (frame_cache_data == RETRO_HW_FRAME_BUFFER_VALID);
+ return false;
+}
+
+static const shader_backend_t *video_shader_set_backend(
+ enum rarch_shader_type type)
+{
+ switch (type)
+ {
+ case RARCH_SHADER_CG:
+ {
+#ifdef HAVE_CG
+ gfx_ctx_flags_t flags;
+ flags.flags = 0;
+ video_context_driver_get_flags(&flags);
+
+ if (BIT32_GET(flags.flags, GFX_CTX_FLAGS_GL_CORE_CONTEXT))
+ {
+ RARCH_ERR("[Shader driver]: Cg cannot be used with core"
+ " GL context. Trying to fall back to GLSL...\n");
+ return video_shader_set_backend(RARCH_SHADER_GLSL);
+ }
+
+ RARCH_LOG("[Shader driver]: Using Cg shader backend.\n");
+ return &gl_cg_backend;
+#else
+ break;
+#endif
+ }
+ case RARCH_SHADER_GLSL:
+#ifdef HAVE_GLSL
+ RARCH_LOG("[Shader driver]: Using GLSL shader backend.\n");
+ return &gl_glsl_backend;
+#else
+ break;
+#endif
+ case RARCH_SHADER_HLSL:
+ case RARCH_SHADER_NONE:
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+void video_shader_driver_use(video_shader_ctx_info_t *shader_info)
+{
+ if (current_shader && current_shader->use)
+ current_shader->use(shader_info->data, current_shader_data,
+ shader_info->idx, shader_info->set_active);
+}
+
+void video_shader_driver_set_parameter(struct uniform_info *param)
+{
+ if (current_shader && current_shader->set_uniform_parameter)
+ current_shader->set_uniform_parameter(current_shader_data,
+ param, NULL);
+}
+
+void video_shader_driver_set_parameters(video_shader_ctx_params_t *params)
+{
+ if (current_shader && current_shader->set_params)
+ current_shader->set_params(params, current_shader_data);
+}
+
+bool video_shader_driver_get_prev_textures(
+ video_shader_ctx_texture_t *texture)
+{
+ if (!texture || !current_shader)
+ return false;
+ texture->id = current_shader->get_prev_textures(current_shader_data);
+
+ return true;
+}
+
+bool video_shader_driver_get_ident(video_shader_ctx_ident_t *ident)
+{
+ if (!ident || !current_shader)
+ return false;
+ ident->ident = current_shader->ident;
+ return true;
+}
+
+bool video_shader_driver_get_current_shader(video_shader_ctx_t *shader)
+{
+ void *video_driver = video_driver_get_ptr(true);
+ const video_poke_interface_t *video_poke = video_driver_get_poke();
+
+ shader->data = NULL;
+ if (!video_poke || !video_driver || !video_poke->get_current_shader)
+ return false;
+ shader->data = video_poke->get_current_shader(video_driver);
+ return true;
+}
+
+bool video_shader_driver_direct_get_current_shader(
+ video_shader_ctx_t *shader)
+{
+ if (!current_shader)
+ return false;
+
+ shader->data = current_shader->get_current_shader(current_shader_data);
+
+ return true;
+}
+
+bool video_shader_driver_deinit(void)
+{
+ if (!current_shader)
+ return false;
+
+ if (current_shader->deinit)
+ current_shader->deinit(current_shader_data);
+
+ current_shader_data = NULL;
+ current_shader = NULL;
+ return true;
+}
+
+static enum gfx_wrap_type video_shader_driver_wrap_type_null(
+ void *data, unsigned index)
+{
+ return RARCH_WRAP_BORDER;
+}
+
+static bool video_driver_cb_set_mvp(void *data,
+ void *shader_data, const void *mat_data)
+{
+ video_shader_ctx_mvp_t mvp;
+ mvp.data = data;
+ mvp.matrix = mat_data;
+
+ video_driver_set_mvp(&mvp);
+ return true;
+}
+
+static struct video_shader *
+video_shader_driver_get_current_shader_null(void *data)
+{
+ return NULL;
+}
+
+static void video_shader_driver_set_params_null(
+ void *data, void *shader_data)
+{
+}
+
+static void video_shader_driver_scale_null(void *data,
+ unsigned idx, struct gfx_fbo_scale *scale)
+{
+ (void)idx;
+ (void)scale;
+}
+
+static bool video_shader_driver_mipmap_input_null(
+ void *data, unsigned idx)
+{
+ (void)idx;
+ return false;
+}
+
+static bool video_shader_driver_filter_type_null(
+ void *data, unsigned idx, bool *smooth)
+{
+ (void)idx;
+ (void)smooth;
+ return false;
+}
+
+static unsigned video_shader_driver_num_null(void *data)
+{
+ return 0;
+}
+
+static bool video_shader_driver_get_feedback_pass_null(
+ void *data, unsigned *idx)
+{
+ (void)idx;
+ return false;
+}
+
+static void video_shader_driver_reset_to_defaults(void)
+{
+ if (!current_shader)
+ return;
+
+ if (!current_shader->wrap_type)
+ current_shader->wrap_type = video_shader_driver_wrap_type_null;
+ if (current_shader->set_mvp)
+ video_driver_cb_shader_set_mvp = current_shader->set_mvp;
+ else
+ {
+ current_shader->set_mvp = video_driver_cb_set_mvp;
+ video_driver_cb_shader_set_mvp = video_driver_cb_set_mvp;
+ }
+ if (!current_shader->set_coords)
+ current_shader->set_coords = video_driver_cb_set_coords;
+
+ if (current_shader->use)
+ video_driver_cb_shader_use = current_shader->use;
+ else
+ {
+ current_shader->use = video_shader_driver_use_null;
+ video_driver_cb_shader_use = video_shader_driver_use_null;
+ }
+ if (!current_shader->set_params)
+ current_shader->set_params = video_shader_driver_set_params_null;
+ if (!current_shader->shader_scale)
+ current_shader->shader_scale = video_shader_driver_scale_null;
+ if (!current_shader->mipmap_input)
+ current_shader->mipmap_input = video_shader_driver_mipmap_input_null;
+ if (!current_shader->filter_type)
+ current_shader->filter_type = video_shader_driver_filter_type_null;
+ if (!current_shader->num_shaders)
+ current_shader->num_shaders = video_shader_driver_num_null;
+ if (!current_shader->get_current_shader)
+ current_shader->get_current_shader= video_shader_driver_get_current_shader_null;
+ if (!current_shader->get_feedback_pass)
+ current_shader->get_feedback_pass = video_shader_driver_get_feedback_pass_null;
+}
+
+/* Finds first suitable shader context driver. */
+bool video_shader_driver_init_first(void)
+{
+ current_shader = (shader_backend_t*)shader_ctx_drivers[0];
+ video_shader_driver_reset_to_defaults();
+ return true;
+}
+
+bool video_shader_driver_init(video_shader_ctx_init_t *init)
+{
+ void *tmp = NULL;
+ settings_t *settings = config_get_ptr();
+
+ if (!init->shader || !init->shader->init)
+ {
+ init->shader = video_shader_set_backend(init->shader_type);
+
+ if (!init->shader)
+ return false;
+ }
+
+ tmp = init->shader->init(init->data, init->path);
+
+ if (!tmp)
+ return false;
+
+ if (string_is_equal(settings->arrays.menu_driver, "xmb")
+ && init->shader->init_menu_shaders)
+ {
+ RARCH_LOG("Setting up menu pipeline shaders for XMB ... \n");
+ init->shader->init_menu_shaders(tmp);
+ }
+
+ current_shader_data = tmp;
+
+ RARCH_LOG("Resetting shader to defaults ... \n");
+
+ current_shader = (shader_backend_t*)init->shader;
+ video_shader_driver_reset_to_defaults();
+
+ return true;
+}
+
+bool video_shader_driver_get_feedback_pass(unsigned *data)
+{
+ return current_shader->get_feedback_pass(current_shader_data, data);
+}
+
+bool video_shader_driver_mipmap_input(unsigned *index)
+{
+ return current_shader->mipmap_input(current_shader_data, *index);
+}
+
+bool video_shader_driver_scale(video_shader_ctx_scale_t *scaler)
+{
+ if (!scaler || !scaler->scale)
+ return false;
+
+ scaler->scale->valid = false;
+
+ current_shader->shader_scale(current_shader_data,
+ scaler->idx, scaler->scale);
+ return true;
+}
+
+bool video_shader_driver_info(video_shader_ctx_info_t *shader_info)
+{
+ if (!shader_info)
+ return false;
+
+ shader_info->num = current_shader->num_shaders(current_shader_data);
+
+ return true;
+}
+
+bool video_shader_driver_filter_type(video_shader_ctx_filter_t *filter)
+{
+ if (filter)
+ return current_shader->filter_type(current_shader_data,
+ filter->index, filter->smooth);
+ return false;
+}
+
+bool video_shader_driver_compile_program(
+ struct shader_program_info *program_info)
+{
+ if (program_info)
+ return current_shader->compile_program(program_info->data,
+ program_info->idx, NULL, program_info);
+ return false;
+}
+
+bool video_shader_driver_wrap_type(video_shader_ctx_wrap_t *wrap)
+{
+ wrap->type = current_shader->wrap_type(
+ current_shader_data, wrap->idx);
+ return true;
+}
+
+void video_driver_set_coords(video_shader_ctx_coords_t *coords)
+{
+ if (current_shader && current_shader->set_coords)
+ current_shader->set_coords(coords->handle_data,
+ current_shader_data,
+ (const struct video_coords*)coords->data);
+ else
+ {
+ if (video_driver_poke && video_driver_poke->set_coords)
+ video_driver_poke->set_coords(coords->handle_data,
+ current_shader_data,
+ (const struct video_coords*)coords->data);
+ }
+}
+
+void video_driver_set_mvp(video_shader_ctx_mvp_t *mvp)
+{
+ if (!mvp || !mvp->matrix)
+ return;
+
+ if (current_shader && current_shader->set_mvp)
+ current_shader->set_mvp(mvp->data,
+ current_shader_data, mvp->matrix);
+ else
+ {
+ if (video_driver_poke && video_driver_poke->set_mvp)
+ video_driver_poke->set_mvp(mvp->data,
+ current_shader_data, mvp->matrix);
+ }
+}
+
+float video_driver_get_refresh_rate(void)
+{
+ if (video_driver_poke && video_driver_poke->get_refresh_rate)
+ return video_driver_poke->get_refresh_rate(video_driver_data);
+
+ return 0.0f;
+}
diff --git a/gfx/video_driver.h b/gfx/video_driver.h
index eea9ef14e4..2e5340ffbf 100644
--- a/gfx/video_driver.h
+++ b/gfx/video_driver.h
@@ -1,1308 +1,1310 @@
-/* RetroArch - A frontend for libretro.
- * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
- * Copyright (C) 2011-2017 - Daniel De Matteis
- *
- * 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 .
- */
-
-#ifndef __VIDEO_DRIVER__H
-#define __VIDEO_DRIVER__H
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-#ifdef HAVE_OVERLAY
-#include "../input/input_overlay.h"
-#endif
-
-#include "video_defines.h"
-#include "video_coord_array.h"
-#include "video_filter.h"
-#include "video_shader_parse.h"
-#include "video_state_tracker.h"
-
-#include "../input/input_driver.h"
-
-#define RARCH_SCALE_BASE 256
-
-#include "video_shader_parse.h"
-
-#define VIDEO_SHADER_STOCK_BLEND (GFX_MAX_SHADERS - 1)
-#define VIDEO_SHADER_MENU (GFX_MAX_SHADERS - 2)
-#define VIDEO_SHADER_MENU_2 (GFX_MAX_SHADERS - 3)
-#define VIDEO_SHADER_MENU_3 (GFX_MAX_SHADERS - 4)
-#define VIDEO_SHADER_MENU_4 (GFX_MAX_SHADERS - 5)
-#define VIDEO_SHADER_MENU_5 (GFX_MAX_SHADERS - 6)
-#define VIDEO_SHADER_MENU_6 (GFX_MAX_SHADERS - 7)
-
-#if defined(_XBOX360)
-#define DEFAULT_SHADER_TYPE RARCH_SHADER_HLSL
-#elif defined(__PSL1GHT__) || defined(HAVE_OPENGLES2) || defined(HAVE_GLSL)
-#define DEFAULT_SHADER_TYPE RARCH_SHADER_GLSL
-#elif defined(__CELLOS_LV2__) || defined(HAVE_CG)
-#define DEFAULT_SHADER_TYPE RARCH_SHADER_CG
-#else
-#define DEFAULT_SHADER_TYPE RARCH_SHADER_NONE
-#endif
-
-RETRO_BEGIN_DECLS
-
-#ifndef MAX_EGLIMAGE_TEXTURES
-#define MAX_EGLIMAGE_TEXTURES 32
-#endif
-
-#define MAX_VARIABLES 64
-
-enum
-{
- TEXTURES = 8,
- TEXTURESMASK = TEXTURES - 1
-};
-
-struct LinkInfo
-{
- unsigned tex_w, tex_h;
- struct video_shader_pass *pass;
-};
-
-enum gfx_ctx_api
-{
- GFX_CTX_NONE = 0,
- GFX_CTX_OPENGL_API,
- GFX_CTX_OPENGL_ES_API,
- GFX_CTX_DIRECT3D8_API,
- GFX_CTX_DIRECT3D9_API,
- GFX_CTX_DIRECT3D10_API,
- GFX_CTX_DIRECT3D11_API,
- GFX_CTX_DIRECT3D12_API,
- GFX_CTX_OPENVG_API,
- GFX_CTX_VULKAN_API,
- GFX_CTX_SIXEL_API,
- GFX_CTX_METAL_API,
- GFX_CTX_GDI_API,
- GFX_CTX_GX_API,
- GFX_CTX_GX2_API
-};
-
-enum display_metric_types
-{
- DISPLAY_METRIC_NONE = 0,
- DISPLAY_METRIC_MM_WIDTH,
- DISPLAY_METRIC_MM_HEIGHT,
- DISPLAY_METRIC_DPI
-};
-
-enum display_flags
-{
- GFX_CTX_FLAGS_NONE = 0,
- GFX_CTX_FLAGS_GL_CORE_CONTEXT,
- GFX_CTX_FLAGS_MULTISAMPLING,
- 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_ADAPTIVE_VSYNC
-};
-
-enum shader_uniform_type
-{
- UNIFORM_1F = 0,
- UNIFORM_2F,
- UNIFORM_3F,
- UNIFORM_4F,
- UNIFORM_1FV,
- UNIFORM_2FV,
- UNIFORM_3FV,
- UNIFORM_4FV,
- UNIFORM_1I
-};
-
-enum shader_program_type
-{
- SHADER_PROGRAM_VERTEX = 0,
- SHADER_PROGRAM_FRAGMENT,
- SHADER_PROGRAM_COMBINED
-};
-
-struct shader_program_info
-{
- bool is_file;
- const char *vertex;
- const char *fragment;
- const char *combined;
- unsigned idx;
- void *data;
-};
-
-struct uniform_info
-{
- bool enabled;
-
- int32_t location;
- int32_t count;
- unsigned type; /* shader uniform type */
-
- struct
- {
- enum shader_program_type type;
- const char *ident;
- uint32_t idx;
- bool add_prefix;
- bool enable;
- } lookup;
-
- struct
- {
- struct
- {
- intptr_t v0;
- intptr_t v1;
- intptr_t v2;
- intptr_t v3;
- } integer;
-
- intptr_t *integerv;
-
- struct
- {
- uintptr_t v0;
- uintptr_t v1;
- uintptr_t v2;
- uintptr_t v3;
- } unsigned_integer;
-
- uintptr_t *unsigned_integerv;
-
- struct
- {
- float v0;
- float v1;
- float v2;
- float v3;
- } f;
-
- float *floatv;
- } result;
-};
-
-typedef struct shader_backend
-{
- void *(*init)(void *data, const char *path);
- void (*init_menu_shaders)(void *data);
- void (*deinit)(void *data);
-
- /* Set shader parameters. */
- void (*set_params)(void *data, void *shader_data);
-
- void (*set_uniform_parameter)(void *data, struct uniform_info *param,
- void *uniform_data);
-
- /* Compile a shader program. */
- bool (*compile_program)(void *data, unsigned idx,
- void *program_data, struct shader_program_info *program_info);
-
- /* Use a shader program specified by variable 'index'. */
- void (*use)(void *data, void *shader_data, unsigned index, bool set_active);
-
- /* Returns the number of currently loaded shaders. */
- unsigned (*num_shaders)(void *data);
-
- bool (*filter_type)(void *data, unsigned index, bool *smooth);
- enum gfx_wrap_type (*wrap_type)(void *data, unsigned index);
- void (*shader_scale)(void *data,
- unsigned index, struct gfx_fbo_scale *scale);
- bool (*set_coords)(void *handle_data,
- void *shader_data, const struct video_coords *coords);
- bool (*set_mvp)(void *data, void *shader_data,
- const void *mat_data);
- unsigned (*get_prev_textures)(void *data);
- bool (*get_feedback_pass)(void *data, unsigned *pass);
- bool (*mipmap_input)(void *data, unsigned index);
-
- struct video_shader *(*get_current_shader)(void *data);
-
- enum rarch_shader_type type;
-
- /* Human readable string. */
- const char *ident;
-} shader_backend_t;
-
-typedef struct video_shader_ctx_init
-{
- enum rarch_shader_type shader_type;
- const char *path;
- const shader_backend_t *shader;
- void *data;
- struct
- {
- bool core_context_enabled;
- } gl;
-} video_shader_ctx_init_t;
-
-typedef struct video_shader_ctx_params
-{
- unsigned width;
- unsigned height;
- unsigned tex_width;
- unsigned tex_height;
- unsigned out_width;
- unsigned out_height;
- unsigned frame_counter;
- unsigned fbo_info_cnt;
- void *data;
- const void *info;
- const void *prev_info;
- const void *feedback_info;
- const void *fbo_info;
-} video_shader_ctx_params_t;
-
-typedef struct video_shader_ctx_coords
-{
- void *handle_data;
- const void *data;
-} video_shader_ctx_coords_t;
-
-typedef struct video_shader_ctx_scale
-{
- unsigned idx;
- struct gfx_fbo_scale *scale;
-} video_shader_ctx_scale_t;
-
-typedef struct video_shader_ctx_info
-{
- bool set_active;
- unsigned num;
- unsigned idx;
- void *data;
-} video_shader_ctx_info_t;
-
-typedef struct video_shader_ctx_mvp
-{
- void *data;
- const void *matrix;
-} video_shader_ctx_mvp_t;
-
-typedef struct video_shader_ctx_filter
-{
- unsigned index;
- bool *smooth;
-} video_shader_ctx_filter_t;
-
-typedef struct video_shader_ctx_wrap
-{
- unsigned idx;
- enum gfx_wrap_type type;
-} video_shader_ctx_wrap_t;
-
-typedef struct video_shader_ctx
-{
- struct video_shader *data;
-} video_shader_ctx_t;
-
-typedef struct video_shader_ctx_ident
-{
- const char *ident;
-} video_shader_ctx_ident_t;
-
-typedef struct video_shader_ctx_texture
-{
- unsigned id;
-} video_shader_ctx_texture_t;
-
-typedef void (*gfx_ctx_proc_t)(void);
-
-typedef struct video_info
-{
- /* Launch in fullscreen mode instead of windowed mode. */
- bool fullscreen;
-
- /* Start with V-Sync enabled. */
- bool vsync;
-
- /* If true, the output image should have the aspect ratio
- * as set in aspect_ratio. */
- bool force_aspect;
-
- bool font_enable;
-
- /* Width of window.
- * If fullscreen mode is requested,
- * a width of 0 means the resolution of the
- * desktop should be used. */
- unsigned width;
-
- /* Height of window.
- * If fullscreen mode is requested,
- * a height of 0 means the resolutiof the desktop should be used.
- */
- unsigned height;
-
- int swap_interval;
-
-#ifdef GEKKO
- bool vfilter;
-#endif
-
- /* If true, applies bilinear filtering to the image,
- * otherwise nearest filtering. */
- bool smooth;
-
- bool is_threaded;
-
- /* Use 32bit RGBA rather than native RGB565/XBGR1555.
- *
- * XRGB1555 format is 16-bit and has byte ordering: 0RRRRRGGGGGBBBBB,
- * in native endian.
- *
- * ARGB8888 is AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB, native endian.
- * Alpha channel should be disregarded.
- * */
- bool rgb32;
-
-#ifdef GEKKO
- /* TODO - we can't really have driver system-specific
- * variables in here. There should be some
- * kind of publicly accessible driver implementation
- * video struct for specific things like this.
- */
-
- /* Wii-specific settings. Ignored for everything else. */
- unsigned viwidth;
-#endif
-
- /*
- * input_scale defines the maximum size of the picture that will
- * ever be used with the frame callback.
- *
- * The maximum resolution is a multiple of 256x256 size (RARCH_SCALE_BASE),
- * so an input scale of 2 means you should allocate a texture or of 512x512.
- *
- * Maximum input size: RARCH_SCALE_BASE * input_scale
- */
- unsigned input_scale;
-
- uintptr_t parent;
-} video_info_t;
-
-typedef struct video_frame_info
-{
- bool input_menu_swap_ok_cancel_buttons;
- bool input_driver_nonblock_state;
- bool shared_context;
- bool black_frame_insertion;
- bool hard_sync;
- bool fps_show;
- bool statistics_show;
- bool framecount_show;
- bool scale_integer;
- bool post_filter_record;
- bool windowed_fullscreen;
- bool fullscreen;
- bool font_enable;
- bool use_rgba;
- bool libretro_running;
- bool xmb_shadows_enable;
- bool battery_level_enable;
- bool timedate_enable;
- bool runloop_is_slowmotion;
- bool runloop_is_idle;
- bool runloop_is_paused;
- bool is_perfcnt_enable;
- bool menu_is_alive;
- bool msg_bgcolor_enable;
-
- int custom_vp_x;
- int custom_vp_y;
- int crt_switch_center_adjust;
-
- unsigned hard_sync_frames;
- unsigned aspect_ratio_idx;
- unsigned max_swapchain_images;
- unsigned monitor_index;
- unsigned crt_switch_resolution;
- unsigned crt_switch_resolution_super;
- unsigned width;
- unsigned height;
- unsigned xmb_theme;
- unsigned xmb_color_theme;
- unsigned menu_shader_pipeline;
- unsigned materialui_color_theme;
- unsigned ozone_color_theme;
- unsigned custom_vp_width;
- unsigned custom_vp_height;
- unsigned custom_vp_full_width;
- unsigned custom_vp_full_height;
-
- float menu_wallpaper_opacity;
- float menu_framebuffer_opacity;
- float menu_header_opacity;
- float menu_footer_opacity;
- float refresh_rate;
- float font_msg_pos_x;
- float font_msg_pos_y;
- float font_msg_color_r;
- float font_msg_color_g;
- float font_msg_color_b;
- float xmb_alpha_factor;
-
- char fps_text[128];
- char stat_text[512];
- char chat_text[256];
-
- uint64_t frame_count;
- float frame_time;
- float frame_rate;
-
- struct
- {
- float x;
- float y;
- float scale;
- /* Drop shadow color multiplier. */
- float drop_mod;
- /* Drop shadow offset.
- * If both are 0, no drop shadow will be rendered. */
- int drop_x, drop_y;
- /* Drop shadow alpha */
- float drop_alpha;
- /* ABGR. Use the macros. */
- uint32_t color;
- bool full_screen;
- enum text_alignment text_align;
- } osd_stat_params;
-
- void (*cb_update_window_title)(void*, void *);
- void (*cb_swap_buffers)(void*, void *);
- bool (*cb_get_metrics)(void *data, enum display_metric_types type,
- float *value);
- bool (*cb_set_resize)(void*, unsigned, unsigned);
-
- bool (*cb_set_mvp)(void *data, void *shader_data,
- const void *mat_data);
-
- void *context_data;
- void *shader_data;
- void *userdata;
- const shader_backend_t *shader_driver;
-} video_frame_info_t;
-
-typedef void (*update_window_title_cb)(void*, void*);
-typedef bool (*get_metrics_cb)(void *data, enum display_metric_types type,
- float *value);
-typedef bool (*set_resize_cb)(void*, unsigned, unsigned);
-
-typedef struct gfx_ctx_driver
-{
- /* The opaque pointer is the underlying video driver data (e.g. gl_t for
- * OpenGL contexts). Although not advised, the context driver is allowed
- * to hold a pointer to it as the context never outlives the video driver.
- *
- * The context driver is responsible for it's own data.*/
- void* (*init)(video_frame_info_t *video_info, void *video_driver);
- void (*destroy)(void *data);
-
- enum gfx_ctx_api (*get_api)(void *data);
-
- /* Which API to bind to. */
- bool (*bind_api)(void *video_driver, enum gfx_ctx_api,
- unsigned major, unsigned minor);
-
- /* Sets the swap interval. */
- 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);
-
- /* Gets current window size.
- * If not initialized yet, it returns current screen size. */
- void (*get_video_size)(void*, unsigned*, unsigned*);
-
- float (*get_refresh_rate)(void*);
-
- void (*get_video_output_size)(void*, unsigned*, unsigned*);
-
- void (*get_video_output_prev)(void*);
-
- void (*get_video_output_next)(void*);
-
- get_metrics_cb get_metrics;
-
- /* Translates a window size to an aspect ratio.
- * In most cases this will be just width / height, but
- * some contexts will better know which actual aspect ratio is used.
- * This can be NULL to assume the default behavior.
- */
- float (*translate_aspect)(void*, unsigned, unsigned);
-
- /* Asks driver to update window title (FPS, etc). */
- update_window_title_cb update_window_title;
-
- /* Queries for resize and quit events.
- * Also processes events. */
- void (*check_window)(void*, bool*, bool*,
- unsigned*, unsigned*, bool);
-
- /* Acknowledge a resize event. This is needed for some APIs.
- * Most backends will ignore this. */
- set_resize_cb set_resize;
-
- /* Checks if window has input focus. */
- bool (*has_focus)(void*);
-
- /* Should the screensaver be suppressed? */
- bool (*suppress_screensaver)(void *data, bool enable);
-
- /* Checks if context driver has windowed support. */
- bool (*has_windowed)(void*);
-
- /* Swaps buffers. VBlank sync depends on
- * earlier calls to swap_interval. */
- void (*swap_buffers)(void*, void *);
-
- /* Most video backends will want to use a certain input driver.
- * Checks for it here. */
- void (*input_driver)(void*, const char *, const input_driver_t**, void**);
-
- /* Wraps whatever gl_proc_address() there is.
- * Does not take opaque, to avoid lots of ugly wrapper code. */
- gfx_ctx_proc_t (*get_proc_address)(const char*);
-
- /* Returns true if this context supports EGLImage buffers for
- * screen drawing and was initalized correctly. */
- bool (*image_buffer_init)(void*, const video_info_t*);
-
- /* Writes the frame to the EGLImage and sets image_handle to it.
- * Returns true if a new image handle is created.
- * Always returns true the first time it's called for a new index.
- * The graphics core must handle a change in the handle correctly. */
- bool (*image_buffer_write)(void*, const void *frame, unsigned width,
- unsigned height, unsigned pitch, bool rgb32,
- unsigned index, void **image_handle);
-
- /* Shows or hides mouse. Can be NULL if context doesn't
- * have a concept of mouse pointer. */
- void (*show_mouse)(void *data, bool state);
-
- /* Human readable string. */
- const char *ident;
-
- uint32_t (*get_flags)(void *data);
-
- void (*set_flags)(void *data, uint32_t flags);
-
- /* Optional. Binds HW-render offscreen context. */
- void (*bind_hw_render)(void *data, bool enable);
-
- /* Optional. Gets base data for the context which is used by the driver.
- * This is mostly relevant for graphics APIs such as Vulkan
- * which do not have global context state. */
- void *(*get_context_data)(void *data);
-
- /* Optional. Makes driver context (only GLX right now)
- * active for this thread. */
- void (*make_current)(bool release);
-} gfx_ctx_driver_t;
-
-typedef struct gfx_ctx_flags
-{
- uint32_t flags;
-} gfx_ctx_flags_t;
-
-typedef struct gfx_ctx_size
-{
- bool *quit;
- bool *resize;
- unsigned *width;
- unsigned *height;
-} gfx_ctx_size_t;
-
-typedef struct gfx_ctx_mode
-{
- unsigned width;
- unsigned height;
- bool fullscreen;
-} gfx_ctx_mode_t;
-
-typedef struct gfx_ctx_metrics
-{
- enum display_metric_types type;
- float *value;
-} gfx_ctx_metrics_t;
-
-typedef struct gfx_ctx_aspect
-{
- float *aspect;
- unsigned width;
- unsigned height;
-} gfx_ctx_aspect_t;
-
-typedef struct gfx_ctx_image
-{
- const void *frame;
- unsigned width;
- unsigned height;
- unsigned pitch;
- unsigned index;
- bool rgb32;
- void **handle;
-} gfx_ctx_image_t;
-
-typedef struct gfx_ctx_input
-{
- const input_driver_t **input;
- void **input_data;
-} gfx_ctx_input_t;
-
-typedef struct gfx_ctx_proc_address
-{
- const char *sym;
- retro_proc_address_t addr;
-} gfx_ctx_proc_address_t;
-
-typedef struct gfx_ctx_ident
-{
- const char *ident;
-} gfx_ctx_ident_t;
-
-typedef struct video_viewport
-{
- int x;
- int y;
- unsigned width;
- unsigned height;
- unsigned full_width;
- unsigned full_height;
-} video_viewport_t;
-
-struct aspect_ratio_elem
-{
- char name[64];
- float value;
-};
-
-/* Optionally implemented interface to poke more
- * deeply into video driver. */
-
-typedef struct video_poke_interface
-{
- uint32_t (*get_flags)(void *data);
- void (*set_coords)(void *handle_data, void *shader_data,
- const struct video_coords *coords);
- void (*set_mvp)(void *data, void *shader_data,
- const void *mat_data);
- uintptr_t (*load_texture)(void *video_data, void *data,
- bool threaded, enum texture_filter_type filter_type);
- void (*unload_texture)(void *data, uintptr_t id);
- void (*set_video_mode)(void *data, unsigned width,
- unsigned height, bool fullscreen);
- float (*get_refresh_rate)(void *data);
- void (*set_filtering)(void *data, unsigned index, bool smooth);
- void (*get_video_output_size)(void *data,
- unsigned *width, unsigned *height);
-
- /* Move index to previous resolution */
- void (*get_video_output_prev)(void *data);
-
- /* Move index to next resolution */
- void (*get_video_output_next)(void *data);
-
- uintptr_t (*get_current_framebuffer)(void *data);
- retro_proc_address_t (*get_proc_address)(void *data, const char *sym);
- void (*set_aspect_ratio)(void *data, unsigned aspectratio_index);
- void (*apply_state_changes)(void *data);
-
- /* Update texture. */
- void (*set_texture_frame)(void *data, const void *frame, bool rgb32,
- unsigned width, unsigned height, float alpha);
- /* Enable or disable rendering. */
- void (*set_texture_enable)(void *data, bool enable, bool full_screen);
- void (*set_osd_msg)(void *data, video_frame_info_t *video_info,
- const char *msg,
- const void *params, void *font);
-
- void (*show_mouse)(void *data, bool state);
- void (*grab_mouse_toggle)(void *data);
-
- struct video_shader *(*get_current_shader)(void *data);
- bool (*get_current_software_framebuffer)(void *data,
- struct retro_framebuffer *framebuffer);
- bool (*get_hw_render_interface)(void *data,
- const struct retro_hw_render_interface **iface);
-} video_poke_interface_t;
-
-/* msg is for showing a message on the screen
- * along with the video frame. */
-typedef bool (*video_driver_frame_t)(void *data,
- const void *frame, unsigned width,
- unsigned height, uint64_t frame_count,
- unsigned pitch, const char *msg, video_frame_info_t *video_info);
-
-typedef struct video_driver
-{
- /* Should the video driver act as an input driver as well?
- * The video initialization might preinitialize an input driver
- * to override the settings in case the video driver relies on
- * input driver for event handling. */
- void *(*init)(const video_info_t *video,
- const input_driver_t **input,
- void **input_data);
-
- /* Updates frame on the screen.
- * Frame can be either XRGB1555, RGB565 or ARGB32 format
- * depending on rgb32 setting in video_info_t.
- * Pitch is the distance in bytes between two scanlines in memory.
- *
- * When msg is non-NULL,
- * it's a message that should be displayed to the user. */
- video_driver_frame_t frame;
-
- /* Should we care about syncing to vblank? Fast forwarding.
- *
- * Requests nonblocking operation.
- *
- * True = VSync is turned off.
- * False = VSync is turned on.
- * */
- void (*set_nonblock_state)(void *data, bool toggle);
-
- /* Is the window still active? */
- bool (*alive)(void *data);
-
- /* Does the window have focus? */
- bool (*focus)(void *data);
-
- /* Should the screensaver be suppressed? */
- bool (*suppress_screensaver)(void *data, bool enable);
-
- /* Does the graphics context support windowed mode? */
- bool (*has_windowed)(void *data);
-
- /* Sets shader. Might not be implemented. Will be moved to
- * poke_interface later. */
- bool (*set_shader)(void *data, enum rarch_shader_type type,
- const char *path);
-
- /* Frees driver. */
- void (*free)(void *data);
-
- /* Human-readable identifier. */
- const char *ident;
-
- void (*set_viewport)(void *data, unsigned width, unsigned height,
- bool force_full, bool allow_rotate);
-
- void (*set_rotation)(void *data, unsigned rotation);
- void (*viewport_info)(void *data, struct video_viewport *vp);
-
- /* Reads out in BGR byte order (24bpp). */
- bool (*read_viewport)(void *data, uint8_t *buffer, bool is_idle);
-
- /* Returns a pointer to a newly allocated buffer that can
- * (and must) be passed to free() by the caller, containing a
- * copy of the current raw frame in the active pixel format
- * and sets width, height and pitch to the correct values. */
- void* (*read_frame_raw)(void *data, unsigned *width,
- unsigned *height, size_t *pitch);
-
-#ifdef HAVE_OVERLAY
- void (*overlay_interface)(void *data,
- const video_overlay_interface_t **iface);
-#endif
- void (*poke_interface)(void *data, const video_poke_interface_t **iface);
- unsigned (*wrap_type_to_enum)(enum gfx_wrap_type type);
-} video_driver_t;
-
-extern struct aspect_ratio_elem aspectratio_lut[ASPECT_RATIO_END];
-
-bool video_driver_has_windowed(void);
-
-bool video_driver_cached_frame_has_valid_framebuffer(void);
-
-void video_driver_destroy(void);
-void video_driver_set_cached_frame_ptr(const void *data);
-void video_driver_set_stub_frame(void);
-void video_driver_unset_stub_frame(void);
-bool video_driver_is_stub_frame(void);
-bool video_driver_supports_recording(void);
-bool video_driver_supports_viewport_read(void);
-bool video_driver_supports_read_frame_raw(void);
-void video_driver_set_viewport_config(void);
-void video_driver_set_viewport_square_pixel(void);
-void video_driver_set_viewport_core(void);
-void video_driver_reset_custom_viewport(void);
-void video_driver_set_rgba(void);
-void video_driver_unset_rgba(void);
-bool video_driver_supports_rgba(void);
-bool video_driver_get_next_video_out(void);
-bool video_driver_get_prev_video_out(void);
-bool video_driver_init(bool *video_is_threaded);
-void video_driver_destroy_data(void);
-void video_driver_free(void);
-void video_driver_free_hw_context(void);
-void video_driver_monitor_reset(void);
-void video_driver_set_aspect_ratio(void);
-void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bool keep_aspect);
-void video_driver_show_mouse(void);
-void video_driver_hide_mouse(void);
-void video_driver_set_nonblock_state(bool toggle);
-bool video_driver_find_driver(void);
-void video_driver_apply_state_changes(void);
-bool video_driver_read_viewport(uint8_t *buffer, bool is_idle);
-bool video_driver_cached_frame(void);
-bool video_driver_frame_filter_alive(void);
-bool video_driver_frame_filter_is_32bit(void);
-void video_driver_default_settings(void);
-void video_driver_load_settings(config_file_t *conf);
-void video_driver_save_settings(config_file_t *conf);
-void video_driver_set_own_driver(void);
-void video_driver_unset_own_driver(void);
-bool video_driver_owns_driver(void);
-bool video_driver_is_hw_context(void);
-struct retro_hw_render_callback *video_driver_get_hw_context(void);
-const struct retro_hw_render_context_negotiation_interface
-*video_driver_get_context_negotiation_interface(void);
-void video_driver_set_context_negotiation_interface(const struct
- retro_hw_render_context_negotiation_interface *iface);
-bool video_driver_is_video_cache_context(void);
-void video_driver_set_video_cache_context_ack(void);
-bool video_driver_is_video_cache_context_ack(void);
-void video_driver_set_active(void);
-void video_driver_unset_active(void);
-bool video_driver_is_active(void);
-bool video_driver_gpu_record_init(unsigned size);
-void video_driver_gpu_record_deinit(void);
-bool video_driver_get_current_software_framebuffer(struct
- retro_framebuffer *fb);
-bool video_driver_get_hw_render_interface(const struct
- retro_hw_render_interface **iface);
-bool video_driver_get_viewport_info(struct video_viewport *viewport);
-void video_driver_set_title_buf(void);
-void video_driver_monitor_adjust_system_rates(void);
-
-/**
- * video_driver_find_handle:
- * @index : index of driver to get handle to.
- *
- * Returns: handle to video driver at index. Can be NULL
- * if nothing found.
- **/
-const void *video_driver_find_handle(int index);
-
-/**
- * video_driver_find_ident:
- * @index : index of driver to get handle to.
- *
- * Returns: Human-readable identifier of video driver at index.
- * Can be NULL if nothing found.
- **/
-const char *video_driver_find_ident(int index);
-
-/**
- * config_get_video_driver_options:
- *
- * Get an enumerated list of all video driver names, separated by '|'.
- *
- * Returns: string listing of all video driver names, separated by '|'.
- **/
-const char* config_get_video_driver_options(void);
-
-/**
- * video_driver_get_ptr:
- *
- * Use this if you need the real video driver
- * and driver data pointers.
- *
- * Returns: video driver's userdata.
- **/
-void *video_driver_get_ptr(bool force_nonthreaded_data);
-
-/**
- * video_driver_get_current_framebuffer:
- *
- * Gets pointer to current hardware renderer framebuffer object.
- * Used by RETRO_ENVIRONMENT_SET_HW_RENDER.
- *
- * Returns: pointer to hardware framebuffer object, otherwise 0.
- **/
-uintptr_t video_driver_get_current_framebuffer(void);
-
-retro_proc_address_t video_driver_get_proc_address(const char *sym);
-
-bool video_driver_set_shader(enum rarch_shader_type type,
- const char *shader);
-
-bool video_driver_set_rotation(unsigned rotation);
-
-bool video_driver_set_video_mode(unsigned width,
- unsigned height, bool fullscreen);
-
-bool video_driver_get_video_output_size(
- unsigned *width, unsigned *height);
-
-void video_driver_set_osd_msg(const char *msg,
- const void *params, void *font);
-
-void video_driver_set_texture_enable(bool enable, bool full_screen);
-
-void video_driver_set_texture_frame(const void *frame, bool rgb32,
- unsigned width, unsigned height, float alpha);
-
-#ifdef HAVE_OVERLAY
-bool video_driver_overlay_interface(
- const video_overlay_interface_t **iface);
-#endif
-
-void * video_driver_read_frame_raw(unsigned *width,
- unsigned *height, size_t *pitch);
-
-void video_driver_set_filtering(unsigned index, bool smooth);
-
-const char *video_driver_get_ident(void);
-
-bool video_driver_set_viewport(unsigned width, unsigned height,
- bool force_fullscreen, bool allow_rotate);
-
-void video_driver_get_size(unsigned *width, unsigned *height);
-
-void video_driver_set_size(unsigned *width, unsigned *height);
-
-void video_driver_unset_video_cache_context_ack(void);
-
-float video_driver_get_aspect_ratio(void);
-
-void video_driver_set_aspect_ratio_value(float value);
-
-rarch_softfilter_t *video_driver_frame_filter_get_ptr(void);
-
-enum retro_pixel_format video_driver_get_pixel_format(void);
-
-void video_driver_set_pixel_format(enum retro_pixel_format fmt);
-
-void video_driver_cached_frame_set(const void *data, unsigned width,
- unsigned height, size_t pitch);
-
-void video_driver_cached_frame_get(const void **data, unsigned *width,
- unsigned *height, size_t *pitch);
-
-void video_driver_menu_settings(void **list_data, void *list_info_data,
- void *group_data, void *subgroup_data, const char *parent_group);
-
-/**
- * video_viewport_get_scaled_integer:
- * @vp : Viewport handle
- * @width : Width.
- * @height : Height.
- * @aspect_ratio : Aspect ratio (in float).
- * @keep_aspect : Preserve aspect ratio?
- *
- * Gets viewport scaling dimensions based on
- * scaled integer aspect ratio.
- **/
-void video_viewport_get_scaled_integer(struct video_viewport *vp,
- unsigned width, unsigned height,
- float aspect_ratio, bool keep_aspect);
-
-struct retro_system_av_info *video_viewport_get_system_av_info(void);
-
-struct video_viewport *video_viewport_get_custom(void);
-
-/**
- * video_monitor_set_refresh_rate:
- * @hz : New refresh rate for monitor.
- *
- * Sets monitor refresh rate to new value.
- **/
-void video_monitor_set_refresh_rate(float hz);
-
-/**
- * video_monitor_fps_statistics
- * @refresh_rate : Monitor refresh rate.
- * @deviation : Deviation from measured refresh rate.
- * @sample_points : Amount of sampled points.
- *
- * Gets the monitor FPS statistics based on the current
- * runtime.
- *
- * Returns: true (1) on success.
- * false (0) if:
- * a) threaded video mode is enabled
- * b) less than 2 frame time samples.
- * c) FPS monitor enable is off.
- **/
-bool video_monitor_fps_statistics(double *refresh_rate,
- double *deviation, unsigned *sample_points);
-
-unsigned video_pixel_get_alignment(unsigned pitch);
-
-const video_poke_interface_t *video_driver_get_poke(void);
-
-/**
- * video_driver_frame:
- * @data : pointer to data of the video frame.
- * @width : width of the video frame.
- * @height : height of the video frame.
- * @pitch : pitch of the video frame.
- *
- * Video frame render callback function.
- **/
-void video_driver_frame(const void *data, unsigned width,
- unsigned height, size_t pitch);
-
-#define video_driver_translate_coord_viewport_wrap(vp, mouse_x, mouse_y, res_x, res_y, res_screen_x, res_screen_y) \
- (video_driver_get_viewport_info(vp) ? video_driver_translate_coord_viewport(vp, mouse_x, mouse_y, res_x, res_y, res_screen_x, res_screen_y) : false)
-
-/**
- * video_driver_translate_coord_viewport:
- * @mouse_x : Pointer X coordinate.
- * @mouse_y : Pointer Y coordinate.
- * @res_x : Scaled X coordinate.
- * @res_y : Scaled Y coordinate.
- * @res_screen_x : Scaled screen X coordinate.
- * @res_screen_y : Scaled screen Y coordinate.
- *
- * Translates pointer [X,Y] coordinates into scaled screen
- * coordinates based on viewport info.
- *
- * Returns: true (1) if successful, false if video driver doesn't support
- * viewport info.
- **/
-bool video_driver_translate_coord_viewport(
- struct video_viewport *vp,
- int mouse_x, int mouse_y,
- int16_t *res_x, int16_t *res_y, int16_t *res_screen_x,
- int16_t *res_screen_y);
-
-uintptr_t video_driver_display_get(void);
-
-enum rarch_display_type video_driver_display_type_get(void);
-
-uintptr_t video_driver_window_get(void);
-
-void video_driver_display_type_set(enum rarch_display_type type);
-
-void video_driver_display_set(uintptr_t idx);
-
-void video_driver_window_set(uintptr_t idx);
-
-bool video_driver_texture_load(void *data,
- enum texture_filter_type filter_type,
- uintptr_t *id);
-
-bool video_driver_texture_unload(uintptr_t *id);
-
-void video_driver_build_info(video_frame_info_t *video_info);
-
-void video_driver_reinit(void);
-
-void video_driver_get_window_title(char *buf, unsigned len);
-
-void video_driver_get_record_status(
- bool *has_gpu_record,
- uint8_t **gpu_buf);
-
-bool *video_driver_get_threaded(void);
-
-void video_driver_set_threaded(bool val);
-
-void video_driver_get_status(uint64_t *frame_count, bool * is_alive,
- bool *is_focused);
-
-/**
- * video_context_driver_init_first:
- * @data : Input data.
- * @ident : Identifier of graphics context driver to find.
- * @api : API of higher-level graphics API.
- * @major : Major version number of higher-level graphics API.
- * @minor : Minor version number of higher-level graphics API.
- * @hw_render_ctx : Request a graphics context driver capable of
- * hardware rendering?
- *
- * Finds first suitable graphics context driver and initializes.
- *
- * Returns: graphics context driver if found, otherwise NULL.
- **/
-const gfx_ctx_driver_t *video_context_driver_init_first(
- void *data, const char *ident,
- enum gfx_ctx_api api, unsigned major, unsigned minor,
- bool hw_render_ctx, void **ctx_data);
-
-bool video_context_driver_find_prev_driver(void);
-
-bool video_context_driver_find_next_driver(void);
-
-bool video_context_driver_init_image_buffer(const video_info_t *data);
-
-bool video_context_driver_write_to_image_buffer(gfx_ctx_image_t *img);
-
-bool video_context_driver_get_video_output_prev(void);
-
-bool video_context_driver_get_video_output_next(void);
-
-bool video_context_driver_bind_hw_render(bool *enable);
-
-void video_context_driver_make_current(bool restore);
-
-bool video_context_driver_set(const gfx_ctx_driver_t *data);
-
-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(int *interval);
-
-bool video_context_driver_get_proc_address(gfx_ctx_proc_address_t *proc);
-
-bool video_context_driver_suppress_screensaver(bool *bool_data);
-
-bool video_context_driver_get_ident(gfx_ctx_ident_t *ident);
-
-bool video_context_driver_set_video_mode(gfx_ctx_mode_t *mode_info);
-
-bool video_context_driver_get_video_size(gfx_ctx_mode_t *mode_info);
-
-bool video_context_driver_get_refresh_rate(float *refresh_rate);
-
-bool video_context_driver_show_mouse(bool *bool_data);
-
-bool video_context_driver_set_flags(gfx_ctx_flags_t *flags);
-
-bool video_context_driver_get_metrics(gfx_ctx_metrics_t *metrics);
-
-bool video_context_driver_translate_aspect(gfx_ctx_aspect_t *aspect);
-
-bool video_context_driver_input_driver(gfx_ctx_input_t *inp);
-
-enum gfx_ctx_api video_context_driver_get_api(void);
-
-void video_context_driver_free(void);
-
-bool video_shader_driver_get_prev_textures(video_shader_ctx_texture_t *texture);
-
-bool video_shader_driver_get_ident(video_shader_ctx_ident_t *ident);
-
-bool video_shader_driver_get_current_shader(video_shader_ctx_t *shader);
-
-bool video_shader_driver_direct_get_current_shader(video_shader_ctx_t *shader);
-
-bool video_shader_driver_deinit(void);
-
-void video_shader_driver_set_parameter(struct uniform_info *param);
-
-void video_shader_driver_set_parameters(video_shader_ctx_params_t *params);
-
-bool video_shader_driver_init_first(void);
-
-bool video_shader_driver_init(video_shader_ctx_init_t *init);
-
-bool video_shader_driver_get_feedback_pass(unsigned *data);
-
-bool video_shader_driver_mipmap_input(unsigned *index);
-
-void video_driver_set_coords(video_shader_ctx_coords_t *coords);
-
-bool video_shader_driver_scale(video_shader_ctx_scale_t *scaler);
-
-bool video_shader_driver_info(video_shader_ctx_info_t *shader_info);
-
-void video_driver_set_mvp(video_shader_ctx_mvp_t *mvp);
-
-bool video_shader_driver_filter_type(video_shader_ctx_filter_t *filter);
-
-bool video_shader_driver_compile_program(struct shader_program_info *program_info);
-
-void video_shader_driver_use(video_shader_ctx_info_t *shader_info);
-
-bool video_shader_driver_wrap_type(video_shader_ctx_wrap_t *wrap);
-
-float video_driver_get_refresh_rate(void);
-
-extern bool (*video_driver_cb_has_focus)(void);
-
-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;
-extern video_driver_t video_psp1;
-extern video_driver_t video_vita2d;
-extern video_driver_t video_ps2;
-extern video_driver_t video_ctr;
-extern video_driver_t video_switch;
-extern video_driver_t video_d3d8;
-extern video_driver_t video_d3d9;
-extern video_driver_t video_d3d10;
-extern video_driver_t video_d3d11;
-extern video_driver_t video_d3d12;
-extern video_driver_t video_gx;
-extern video_driver_t video_wiiu;
-extern video_driver_t video_xenon360;
-extern video_driver_t video_xvideo;
-extern video_driver_t video_sdl;
-extern video_driver_t video_sdl2;
-extern video_driver_t video_vg;
-extern video_driver_t video_omap;
-extern video_driver_t video_exynos;
-extern video_driver_t video_dispmanx;
-extern video_driver_t video_sunxi;
-extern video_driver_t video_drm;
-extern video_driver_t video_xshm;
-extern video_driver_t video_caca;
-extern video_driver_t video_gdi;
-extern video_driver_t video_vga;
-extern video_driver_t video_sixel;
-extern video_driver_t video_null;
-
-extern const gfx_ctx_driver_t gfx_ctx_osmesa;
-extern const gfx_ctx_driver_t gfx_ctx_sdl_gl;
-extern const gfx_ctx_driver_t gfx_ctx_x_egl;
-extern const gfx_ctx_driver_t gfx_ctx_wayland;
-extern const gfx_ctx_driver_t gfx_ctx_x;
-extern const gfx_ctx_driver_t gfx_ctx_drm;
-extern const gfx_ctx_driver_t gfx_ctx_mali_fbdev;
-extern const gfx_ctx_driver_t gfx_ctx_vivante_fbdev;
-extern const gfx_ctx_driver_t gfx_ctx_android;
-extern const gfx_ctx_driver_t gfx_ctx_ps3;
-extern const gfx_ctx_driver_t gfx_ctx_wgl;
-extern const gfx_ctx_driver_t gfx_ctx_videocore;
-extern const gfx_ctx_driver_t gfx_ctx_qnx;
-extern const gfx_ctx_driver_t gfx_ctx_cgl;
-extern const gfx_ctx_driver_t gfx_ctx_cocoagl;
-extern const gfx_ctx_driver_t gfx_ctx_emscripten;
-extern const gfx_ctx_driver_t gfx_ctx_opendingux_fbdev;
-extern const gfx_ctx_driver_t gfx_ctx_khr_display;
-extern const gfx_ctx_driver_t gfx_ctx_gdi;
-extern const gfx_ctx_driver_t gfx_ctx_sixel;
-extern const gfx_ctx_driver_t switch_ctx;
-extern const gfx_ctx_driver_t orbis_ctx;
-extern const gfx_ctx_driver_t gfx_ctx_null;
-
-extern const shader_backend_t gl_glsl_backend;
-extern const shader_backend_t gl_cg_backend;
-extern const shader_backend_t shader_null_backend;
-
-RETRO_END_DECLS
-
-#endif
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
+ * Copyright (C) 2011-2017 - Daniel De Matteis
+ *
+ * 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 .
+ */
+
+#ifndef __VIDEO_DRIVER__H
+#define __VIDEO_DRIVER__H
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#ifdef HAVE_OVERLAY
+#include "../input/input_overlay.h"
+#endif
+
+#include "video_defines.h"
+#include "video_coord_array.h"
+#include "video_filter.h"
+#include "video_shader_parse.h"
+#include "video_state_tracker.h"
+
+#include "../input/input_driver.h"
+
+#define RARCH_SCALE_BASE 256
+
+#include "video_shader_parse.h"
+
+#define VIDEO_SHADER_STOCK_BLEND (GFX_MAX_SHADERS - 1)
+#define VIDEO_SHADER_MENU (GFX_MAX_SHADERS - 2)
+#define VIDEO_SHADER_MENU_2 (GFX_MAX_SHADERS - 3)
+#define VIDEO_SHADER_MENU_3 (GFX_MAX_SHADERS - 4)
+#define VIDEO_SHADER_MENU_4 (GFX_MAX_SHADERS - 5)
+#define VIDEO_SHADER_MENU_5 (GFX_MAX_SHADERS - 6)
+#define VIDEO_SHADER_MENU_6 (GFX_MAX_SHADERS - 7)
+
+#if defined(_XBOX360)
+#define DEFAULT_SHADER_TYPE RARCH_SHADER_HLSL
+#elif defined(__PSL1GHT__) || defined(HAVE_OPENGLES2) || defined(HAVE_GLSL)
+#define DEFAULT_SHADER_TYPE RARCH_SHADER_GLSL
+#elif defined(__CELLOS_LV2__) || defined(HAVE_CG)
+#define DEFAULT_SHADER_TYPE RARCH_SHADER_CG
+#else
+#define DEFAULT_SHADER_TYPE RARCH_SHADER_NONE
+#endif
+
+RETRO_BEGIN_DECLS
+
+#ifndef MAX_EGLIMAGE_TEXTURES
+#define MAX_EGLIMAGE_TEXTURES 32
+#endif
+
+#define MAX_VARIABLES 64
+
+enum
+{
+ TEXTURES = 8,
+ TEXTURESMASK = TEXTURES - 1
+};
+
+struct LinkInfo
+{
+ unsigned tex_w, tex_h;
+ struct video_shader_pass *pass;
+};
+
+enum gfx_ctx_api
+{
+ GFX_CTX_NONE = 0,
+ GFX_CTX_OPENGL_API,
+ GFX_CTX_OPENGL_ES_API,
+ GFX_CTX_DIRECT3D8_API,
+ GFX_CTX_DIRECT3D9_API,
+ GFX_CTX_DIRECT3D10_API,
+ GFX_CTX_DIRECT3D11_API,
+ GFX_CTX_DIRECT3D12_API,
+ GFX_CTX_OPENVG_API,
+ GFX_CTX_VULKAN_API,
+ GFX_CTX_SIXEL_API,
+ GFX_CTX_METAL_API,
+ GFX_CTX_GDI_API,
+ GFX_CTX_GX_API,
+ GFX_CTX_GX2_API
+};
+
+enum display_metric_types
+{
+ DISPLAY_METRIC_NONE = 0,
+ DISPLAY_METRIC_MM_WIDTH,
+ DISPLAY_METRIC_MM_HEIGHT,
+ DISPLAY_METRIC_DPI
+};
+
+enum display_flags
+{
+ GFX_CTX_FLAGS_NONE = 0,
+ GFX_CTX_FLAGS_GL_CORE_CONTEXT,
+ GFX_CTX_FLAGS_MULTISAMPLING,
+ 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_ADAPTIVE_VSYNC
+};
+
+enum shader_uniform_type
+{
+ UNIFORM_1F = 0,
+ UNIFORM_2F,
+ UNIFORM_3F,
+ UNIFORM_4F,
+ UNIFORM_1FV,
+ UNIFORM_2FV,
+ UNIFORM_3FV,
+ UNIFORM_4FV,
+ UNIFORM_1I
+};
+
+enum shader_program_type
+{
+ SHADER_PROGRAM_VERTEX = 0,
+ SHADER_PROGRAM_FRAGMENT,
+ SHADER_PROGRAM_COMBINED
+};
+
+struct shader_program_info
+{
+ bool is_file;
+ const char *vertex;
+ const char *fragment;
+ const char *combined;
+ unsigned idx;
+ void *data;
+};
+
+struct uniform_info
+{
+ bool enabled;
+
+ int32_t location;
+ int32_t count;
+ unsigned type; /* shader uniform type */
+
+ struct
+ {
+ enum shader_program_type type;
+ const char *ident;
+ uint32_t idx;
+ bool add_prefix;
+ bool enable;
+ } lookup;
+
+ struct
+ {
+ struct
+ {
+ intptr_t v0;
+ intptr_t v1;
+ intptr_t v2;
+ intptr_t v3;
+ } integer;
+
+ intptr_t *integerv;
+
+ struct
+ {
+ uintptr_t v0;
+ uintptr_t v1;
+ uintptr_t v2;
+ uintptr_t v3;
+ } unsigned_integer;
+
+ uintptr_t *unsigned_integerv;
+
+ struct
+ {
+ float v0;
+ float v1;
+ float v2;
+ float v3;
+ } f;
+
+ float *floatv;
+ } result;
+};
+
+typedef struct shader_backend
+{
+ void *(*init)(void *data, const char *path);
+ void (*init_menu_shaders)(void *data);
+ void (*deinit)(void *data);
+
+ /* Set shader parameters. */
+ void (*set_params)(void *data, void *shader_data);
+
+ void (*set_uniform_parameter)(void *data, struct uniform_info *param,
+ void *uniform_data);
+
+ /* Compile a shader program. */
+ bool (*compile_program)(void *data, unsigned idx,
+ void *program_data, struct shader_program_info *program_info);
+
+ /* Use a shader program specified by variable 'index'. */
+ void (*use)(void *data, void *shader_data, unsigned index, bool set_active);
+
+ /* Returns the number of currently loaded shaders. */
+ unsigned (*num_shaders)(void *data);
+
+ bool (*filter_type)(void *data, unsigned index, bool *smooth);
+ enum gfx_wrap_type (*wrap_type)(void *data, unsigned index);
+ void (*shader_scale)(void *data,
+ unsigned index, struct gfx_fbo_scale *scale);
+ bool (*set_coords)(void *handle_data,
+ void *shader_data, const struct video_coords *coords);
+ bool (*set_mvp)(void *data, void *shader_data,
+ const void *mat_data);
+ unsigned (*get_prev_textures)(void *data);
+ bool (*get_feedback_pass)(void *data, unsigned *pass);
+ bool (*mipmap_input)(void *data, unsigned index);
+
+ struct video_shader *(*get_current_shader)(void *data);
+
+ enum rarch_shader_type type;
+
+ /* Human readable string. */
+ const char *ident;
+} shader_backend_t;
+
+typedef struct video_shader_ctx_init
+{
+ enum rarch_shader_type shader_type;
+ const char *path;
+ const shader_backend_t *shader;
+ void *data;
+ struct
+ {
+ bool core_context_enabled;
+ } gl;
+} video_shader_ctx_init_t;
+
+typedef struct video_shader_ctx_params
+{
+ unsigned width;
+ unsigned height;
+ unsigned tex_width;
+ unsigned tex_height;
+ unsigned out_width;
+ unsigned out_height;
+ unsigned frame_counter;
+ unsigned fbo_info_cnt;
+ void *data;
+ const void *info;
+ const void *prev_info;
+ const void *feedback_info;
+ const void *fbo_info;
+} video_shader_ctx_params_t;
+
+typedef struct video_shader_ctx_coords
+{
+ void *handle_data;
+ const void *data;
+} video_shader_ctx_coords_t;
+
+typedef struct video_shader_ctx_scale
+{
+ unsigned idx;
+ struct gfx_fbo_scale *scale;
+} video_shader_ctx_scale_t;
+
+typedef struct video_shader_ctx_info
+{
+ bool set_active;
+ unsigned num;
+ unsigned idx;
+ void *data;
+} video_shader_ctx_info_t;
+
+typedef struct video_shader_ctx_mvp
+{
+ void *data;
+ const void *matrix;
+} video_shader_ctx_mvp_t;
+
+typedef struct video_shader_ctx_filter
+{
+ unsigned index;
+ bool *smooth;
+} video_shader_ctx_filter_t;
+
+typedef struct video_shader_ctx_wrap
+{
+ unsigned idx;
+ enum gfx_wrap_type type;
+} video_shader_ctx_wrap_t;
+
+typedef struct video_shader_ctx
+{
+ struct video_shader *data;
+} video_shader_ctx_t;
+
+typedef struct video_shader_ctx_ident
+{
+ const char *ident;
+} video_shader_ctx_ident_t;
+
+typedef struct video_shader_ctx_texture
+{
+ unsigned id;
+} video_shader_ctx_texture_t;
+
+typedef void (*gfx_ctx_proc_t)(void);
+
+typedef struct video_info
+{
+ /* Launch in fullscreen mode instead of windowed mode. */
+ bool fullscreen;
+
+ /* Start with V-Sync enabled. */
+ bool vsync;
+
+ /* If true, the output image should have the aspect ratio
+ * as set in aspect_ratio. */
+ bool force_aspect;
+
+ bool font_enable;
+
+ /* Width of window.
+ * If fullscreen mode is requested,
+ * a width of 0 means the resolution of the
+ * desktop should be used. */
+ unsigned width;
+
+ /* Height of window.
+ * If fullscreen mode is requested,
+ * a height of 0 means the resolutiof the desktop should be used.
+ */
+ unsigned height;
+
+ int swap_interval;
+
+#ifdef GEKKO
+ bool vfilter;
+#endif
+
+ /* If true, applies bilinear filtering to the image,
+ * otherwise nearest filtering. */
+ bool smooth;
+
+ bool is_threaded;
+
+ /* Use 32bit RGBA rather than native RGB565/XBGR1555.
+ *
+ * XRGB1555 format is 16-bit and has byte ordering: 0RRRRRGGGGGBBBBB,
+ * in native endian.
+ *
+ * ARGB8888 is AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB, native endian.
+ * Alpha channel should be disregarded.
+ * */
+ bool rgb32;
+
+#ifdef GEKKO
+ /* TODO - we can't really have driver system-specific
+ * variables in here. There should be some
+ * kind of publicly accessible driver implementation
+ * video struct for specific things like this.
+ */
+
+ /* Wii-specific settings. Ignored for everything else. */
+ unsigned viwidth;
+#endif
+
+ /*
+ * input_scale defines the maximum size of the picture that will
+ * ever be used with the frame callback.
+ *
+ * The maximum resolution is a multiple of 256x256 size (RARCH_SCALE_BASE),
+ * so an input scale of 2 means you should allocate a texture or of 512x512.
+ *
+ * Maximum input size: RARCH_SCALE_BASE * input_scale
+ */
+ unsigned input_scale;
+
+ uintptr_t parent;
+} video_info_t;
+
+typedef struct video_frame_info
+{
+ bool input_menu_swap_ok_cancel_buttons;
+ bool input_driver_nonblock_state;
+ bool shared_context;
+ bool black_frame_insertion;
+ bool hard_sync;
+ bool fps_show;
+ bool statistics_show;
+ bool framecount_show;
+ bool scale_integer;
+ bool post_filter_record;
+ bool windowed_fullscreen;
+ bool fullscreen;
+ bool font_enable;
+ bool use_rgba;
+ bool libretro_running;
+ bool xmb_shadows_enable;
+ bool battery_level_enable;
+ bool timedate_enable;
+ bool runloop_is_slowmotion;
+ bool runloop_is_idle;
+ bool runloop_is_paused;
+ bool is_perfcnt_enable;
+ bool menu_is_alive;
+ bool msg_bgcolor_enable;
+
+ int custom_vp_x;
+ int custom_vp_y;
+ int crt_switch_center_adjust;
+
+ unsigned hard_sync_frames;
+ unsigned aspect_ratio_idx;
+ unsigned max_swapchain_images;
+ unsigned monitor_index;
+ unsigned crt_switch_resolution;
+ unsigned crt_switch_resolution_super;
+ unsigned width;
+ unsigned height;
+ unsigned xmb_theme;
+ unsigned xmb_color_theme;
+ unsigned menu_shader_pipeline;
+ unsigned materialui_color_theme;
+ unsigned ozone_color_theme;
+ unsigned custom_vp_width;
+ unsigned custom_vp_height;
+ unsigned custom_vp_full_width;
+ unsigned custom_vp_full_height;
+
+ float menu_wallpaper_opacity;
+ float menu_framebuffer_opacity;
+ float menu_header_opacity;
+ float menu_footer_opacity;
+ float refresh_rate;
+ float font_msg_pos_x;
+ float font_msg_pos_y;
+ float font_msg_color_r;
+ float font_msg_color_g;
+ float font_msg_color_b;
+ float xmb_alpha_factor;
+
+ char fps_text[128];
+ char stat_text[512];
+ char chat_text[256];
+
+ uint64_t frame_count;
+ float frame_time;
+ float frame_rate;
+
+ struct
+ {
+ float x;
+ float y;
+ float scale;
+ /* Drop shadow color multiplier. */
+ float drop_mod;
+ /* Drop shadow offset.
+ * If both are 0, no drop shadow will be rendered. */
+ int drop_x, drop_y;
+ /* Drop shadow alpha */
+ float drop_alpha;
+ /* ABGR. Use the macros. */
+ uint32_t color;
+ bool full_screen;
+ enum text_alignment text_align;
+ } osd_stat_params;
+
+ void (*cb_update_window_title)(void*, void *);
+ void (*cb_swap_buffers)(void*, void *);
+ bool (*cb_get_metrics)(void *data, enum display_metric_types type,
+ float *value);
+ bool (*cb_set_resize)(void*, unsigned, unsigned);
+
+ bool (*cb_set_mvp)(void *data, void *shader_data,
+ const void *mat_data);
+
+ void *context_data;
+ void *shader_data;
+ void *userdata;
+ const shader_backend_t *shader_driver;
+} video_frame_info_t;
+
+typedef void (*update_window_title_cb)(void*, void*);
+typedef bool (*get_metrics_cb)(void *data, enum display_metric_types type,
+ float *value);
+typedef bool (*set_resize_cb)(void*, unsigned, unsigned);
+
+typedef struct gfx_ctx_driver
+{
+ /* The opaque pointer is the underlying video driver data (e.g. gl_t for
+ * OpenGL contexts). Although not advised, the context driver is allowed
+ * to hold a pointer to it as the context never outlives the video driver.
+ *
+ * The context driver is responsible for it's own data.*/
+ void* (*init)(video_frame_info_t *video_info, void *video_driver);
+ void (*destroy)(void *data);
+
+ enum gfx_ctx_api (*get_api)(void *data);
+
+ /* Which API to bind to. */
+ bool (*bind_api)(void *video_driver, enum gfx_ctx_api,
+ unsigned major, unsigned minor);
+
+ /* Sets the swap interval. */
+ 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);
+
+ /* Gets current window size.
+ * If not initialized yet, it returns current screen size. */
+ void (*get_video_size)(void*, unsigned*, unsigned*);
+
+ float (*get_refresh_rate)(void*);
+
+ void (*get_video_output_size)(void*, unsigned*, unsigned*);
+
+ void (*get_video_output_prev)(void*);
+
+ void (*get_video_output_next)(void*);
+
+ get_metrics_cb get_metrics;
+
+ /* Translates a window size to an aspect ratio.
+ * In most cases this will be just width / height, but
+ * some contexts will better know which actual aspect ratio is used.
+ * This can be NULL to assume the default behavior.
+ */
+ float (*translate_aspect)(void*, unsigned, unsigned);
+
+ /* Asks driver to update window title (FPS, etc). */
+ update_window_title_cb update_window_title;
+
+ /* Queries for resize and quit events.
+ * Also processes events. */
+ void (*check_window)(void*, bool*, bool*,
+ unsigned*, unsigned*, bool);
+
+ /* Acknowledge a resize event. This is needed for some APIs.
+ * Most backends will ignore this. */
+ set_resize_cb set_resize;
+
+ /* Checks if window has input focus. */
+ bool (*has_focus)(void*);
+
+ /* Should the screensaver be suppressed? */
+ bool (*suppress_screensaver)(void *data, bool enable);
+
+ /* Checks if context driver has windowed support. */
+ bool (*has_windowed)(void*);
+
+ /* Swaps buffers. VBlank sync depends on
+ * earlier calls to swap_interval. */
+ void (*swap_buffers)(void*, void *);
+
+ /* Most video backends will want to use a certain input driver.
+ * Checks for it here. */
+ void (*input_driver)(void*, const char *, const input_driver_t**, void**);
+
+ /* Wraps whatever gl_proc_address() there is.
+ * Does not take opaque, to avoid lots of ugly wrapper code. */
+ gfx_ctx_proc_t (*get_proc_address)(const char*);
+
+ /* Returns true if this context supports EGLImage buffers for
+ * screen drawing and was initalized correctly. */
+ bool (*image_buffer_init)(void*, const video_info_t*);
+
+ /* Writes the frame to the EGLImage and sets image_handle to it.
+ * Returns true if a new image handle is created.
+ * Always returns true the first time it's called for a new index.
+ * The graphics core must handle a change in the handle correctly. */
+ bool (*image_buffer_write)(void*, const void *frame, unsigned width,
+ unsigned height, unsigned pitch, bool rgb32,
+ unsigned index, void **image_handle);
+
+ /* Shows or hides mouse. Can be NULL if context doesn't
+ * have a concept of mouse pointer. */
+ void (*show_mouse)(void *data, bool state);
+
+ /* Human readable string. */
+ const char *ident;
+
+ uint32_t (*get_flags)(void *data);
+
+ void (*set_flags)(void *data, uint32_t flags);
+
+ /* Optional. Binds HW-render offscreen context. */
+ void (*bind_hw_render)(void *data, bool enable);
+
+ /* Optional. Gets base data for the context which is used by the driver.
+ * This is mostly relevant for graphics APIs such as Vulkan
+ * which do not have global context state. */
+ void *(*get_context_data)(void *data);
+
+ /* Optional. Makes driver context (only GLX right now)
+ * active for this thread. */
+ void (*make_current)(bool release);
+} gfx_ctx_driver_t;
+
+typedef struct gfx_ctx_flags
+{
+ uint32_t flags;
+} gfx_ctx_flags_t;
+
+typedef struct gfx_ctx_size
+{
+ bool *quit;
+ bool *resize;
+ unsigned *width;
+ unsigned *height;
+} gfx_ctx_size_t;
+
+typedef struct gfx_ctx_mode
+{
+ unsigned width;
+ unsigned height;
+ bool fullscreen;
+} gfx_ctx_mode_t;
+
+typedef struct gfx_ctx_metrics
+{
+ enum display_metric_types type;
+ float *value;
+} gfx_ctx_metrics_t;
+
+typedef struct gfx_ctx_aspect
+{
+ float *aspect;
+ unsigned width;
+ unsigned height;
+} gfx_ctx_aspect_t;
+
+typedef struct gfx_ctx_image
+{
+ const void *frame;
+ unsigned width;
+ unsigned height;
+ unsigned pitch;
+ unsigned index;
+ bool rgb32;
+ void **handle;
+} gfx_ctx_image_t;
+
+typedef struct gfx_ctx_input
+{
+ const input_driver_t **input;
+ void **input_data;
+} gfx_ctx_input_t;
+
+typedef struct gfx_ctx_proc_address
+{
+ const char *sym;
+ retro_proc_address_t addr;
+} gfx_ctx_proc_address_t;
+
+typedef struct gfx_ctx_ident
+{
+ const char *ident;
+} gfx_ctx_ident_t;
+
+typedef struct video_viewport
+{
+ int x;
+ int y;
+ unsigned width;
+ unsigned height;
+ unsigned full_width;
+ unsigned full_height;
+} video_viewport_t;
+
+struct aspect_ratio_elem
+{
+ char name[64];
+ float value;
+};
+
+/* Optionally implemented interface to poke more
+ * deeply into video driver. */
+
+typedef struct video_poke_interface
+{
+ uint32_t (*get_flags)(void *data);
+ void (*set_coords)(void *handle_data, void *shader_data,
+ const struct video_coords *coords);
+ void (*set_mvp)(void *data, void *shader_data,
+ const void *mat_data);
+ uintptr_t (*load_texture)(void *video_data, void *data,
+ bool threaded, enum texture_filter_type filter_type);
+ void (*unload_texture)(void *data, uintptr_t id);
+ void (*set_video_mode)(void *data, unsigned width,
+ unsigned height, bool fullscreen);
+ float (*get_refresh_rate)(void *data);
+ void (*set_filtering)(void *data, unsigned index, bool smooth);
+ void (*get_video_output_size)(void *data,
+ unsigned *width, unsigned *height);
+
+ /* Move index to previous resolution */
+ void (*get_video_output_prev)(void *data);
+
+ /* Move index to next resolution */
+ void (*get_video_output_next)(void *data);
+
+ uintptr_t (*get_current_framebuffer)(void *data);
+ retro_proc_address_t (*get_proc_address)(void *data, const char *sym);
+ void (*set_aspect_ratio)(void *data, unsigned aspectratio_index);
+ void (*apply_state_changes)(void *data);
+
+ /* Update texture. */
+ void (*set_texture_frame)(void *data, const void *frame, bool rgb32,
+ unsigned width, unsigned height, float alpha);
+ /* Enable or disable rendering. */
+ void (*set_texture_enable)(void *data, bool enable, bool full_screen);
+ void (*set_osd_msg)(void *data, video_frame_info_t *video_info,
+ const char *msg,
+ const void *params, void *font);
+
+ void (*show_mouse)(void *data, bool state);
+ void (*grab_mouse_toggle)(void *data);
+
+ struct video_shader *(*get_current_shader)(void *data);
+ bool (*get_current_software_framebuffer)(void *data,
+ struct retro_framebuffer *framebuffer);
+ bool (*get_hw_render_interface)(void *data,
+ const struct retro_hw_render_interface **iface);
+} video_poke_interface_t;
+
+/* msg is for showing a message on the screen
+ * along with the video frame. */
+typedef bool (*video_driver_frame_t)(void *data,
+ const void *frame, unsigned width,
+ unsigned height, uint64_t frame_count,
+ unsigned pitch, const char *msg, video_frame_info_t *video_info);
+
+typedef struct video_driver
+{
+ /* Should the video driver act as an input driver as well?
+ * The video initialization might preinitialize an input driver
+ * to override the settings in case the video driver relies on
+ * input driver for event handling. */
+ void *(*init)(const video_info_t *video,
+ const input_driver_t **input,
+ void **input_data);
+
+ /* Updates frame on the screen.
+ * Frame can be either XRGB1555, RGB565 or ARGB32 format
+ * depending on rgb32 setting in video_info_t.
+ * Pitch is the distance in bytes between two scanlines in memory.
+ *
+ * When msg is non-NULL,
+ * it's a message that should be displayed to the user. */
+ video_driver_frame_t frame;
+
+ /* Should we care about syncing to vblank? Fast forwarding.
+ *
+ * Requests nonblocking operation.
+ *
+ * True = VSync is turned off.
+ * False = VSync is turned on.
+ * */
+ void (*set_nonblock_state)(void *data, bool toggle);
+
+ /* Is the window still active? */
+ bool (*alive)(void *data);
+
+ /* Does the window have focus? */
+ bool (*focus)(void *data);
+
+ /* Should the screensaver be suppressed? */
+ bool (*suppress_screensaver)(void *data, bool enable);
+
+ /* Does the graphics context support windowed mode? */
+ bool (*has_windowed)(void *data);
+
+ /* Sets shader. Might not be implemented. Will be moved to
+ * poke_interface later. */
+ bool (*set_shader)(void *data, enum rarch_shader_type type,
+ const char *path);
+
+ /* Frees driver. */
+ void (*free)(void *data);
+
+ /* Human-readable identifier. */
+ const char *ident;
+
+ void (*set_viewport)(void *data, unsigned width, unsigned height,
+ bool force_full, bool allow_rotate);
+
+ void (*set_rotation)(void *data, unsigned rotation);
+ void (*viewport_info)(void *data, struct video_viewport *vp);
+
+ /* Reads out in BGR byte order (24bpp). */
+ bool (*read_viewport)(void *data, uint8_t *buffer, bool is_idle);
+
+ /* Returns a pointer to a newly allocated buffer that can
+ * (and must) be passed to free() by the caller, containing a
+ * copy of the current raw frame in the active pixel format
+ * and sets width, height and pitch to the correct values. */
+ void* (*read_frame_raw)(void *data, unsigned *width,
+ unsigned *height, size_t *pitch);
+
+#ifdef HAVE_OVERLAY
+ void (*overlay_interface)(void *data,
+ const video_overlay_interface_t **iface);
+#endif
+ void (*poke_interface)(void *data, const video_poke_interface_t **iface);
+ unsigned (*wrap_type_to_enum)(enum gfx_wrap_type type);
+} video_driver_t;
+
+extern struct aspect_ratio_elem aspectratio_lut[ASPECT_RATIO_END];
+
+bool video_driver_has_windowed(void);
+
+bool video_driver_cached_frame_has_valid_framebuffer(void);
+
+void video_driver_destroy(void);
+void video_driver_set_cached_frame_ptr(const void *data);
+void video_driver_set_stub_frame(void);
+void video_driver_unset_stub_frame(void);
+bool video_driver_is_stub_frame(void);
+bool video_driver_supports_recording(void);
+bool video_driver_supports_viewport_read(void);
+bool video_driver_supports_read_frame_raw(void);
+void video_driver_set_viewport_config(void);
+void video_driver_set_viewport_square_pixel(void);
+void video_driver_set_viewport_core(void);
+void video_driver_reset_custom_viewport(void);
+void video_driver_set_rgba(void);
+void video_driver_unset_rgba(void);
+bool video_driver_supports_rgba(void);
+bool video_driver_get_next_video_out(void);
+bool video_driver_get_prev_video_out(void);
+bool video_driver_init(bool *video_is_threaded);
+void video_driver_destroy_data(void);
+void video_driver_free(void);
+void video_driver_free_hw_context(void);
+void video_driver_monitor_reset(void);
+void video_driver_set_aspect_ratio(void);
+void video_driver_update_viewport(struct video_viewport* vp, bool force_full, bool keep_aspect);
+void video_driver_show_mouse(void);
+void video_driver_hide_mouse(void);
+void video_driver_set_nonblock_state(bool toggle);
+bool video_driver_find_driver(void);
+void video_driver_apply_state_changes(void);
+bool video_driver_read_viewport(uint8_t *buffer, bool is_idle);
+bool video_driver_cached_frame(void);
+bool video_driver_frame_filter_alive(void);
+bool video_driver_frame_filter_is_32bit(void);
+void video_driver_default_settings(void);
+void video_driver_load_settings(config_file_t *conf);
+void video_driver_save_settings(config_file_t *conf);
+void video_driver_set_own_driver(void);
+void video_driver_unset_own_driver(void);
+bool video_driver_owns_driver(void);
+bool video_driver_is_hw_context(void);
+struct retro_hw_render_callback *video_driver_get_hw_context(void);
+const struct retro_hw_render_context_negotiation_interface
+*video_driver_get_context_negotiation_interface(void);
+void video_driver_set_context_negotiation_interface(const struct
+ retro_hw_render_context_negotiation_interface *iface);
+bool video_driver_is_video_cache_context(void);
+void video_driver_set_video_cache_context_ack(void);
+bool video_driver_is_video_cache_context_ack(void);
+void video_driver_set_active(void);
+void video_driver_unset_active(void);
+bool video_driver_is_active(void);
+bool video_driver_gpu_record_init(unsigned size);
+void video_driver_gpu_record_deinit(void);
+bool video_driver_get_current_software_framebuffer(struct
+ retro_framebuffer *fb);
+bool video_driver_get_hw_render_interface(const struct
+ retro_hw_render_interface **iface);
+bool video_driver_get_viewport_info(struct video_viewport *viewport);
+void video_driver_set_title_buf(void);
+void video_driver_monitor_adjust_system_rates(void);
+
+/**
+ * video_driver_find_handle:
+ * @index : index of driver to get handle to.
+ *
+ * Returns: handle to video driver at index. Can be NULL
+ * if nothing found.
+ **/
+const void *video_driver_find_handle(int index);
+
+/**
+ * video_driver_find_ident:
+ * @index : index of driver to get handle to.
+ *
+ * Returns: Human-readable identifier of video driver at index.
+ * Can be NULL if nothing found.
+ **/
+const char *video_driver_find_ident(int index);
+
+/**
+ * config_get_video_driver_options:
+ *
+ * Get an enumerated list of all video driver names, separated by '|'.
+ *
+ * Returns: string listing of all video driver names, separated by '|'.
+ **/
+const char* config_get_video_driver_options(void);
+
+/**
+ * video_driver_get_ptr:
+ *
+ * Use this if you need the real video driver
+ * and driver data pointers.
+ *
+ * Returns: video driver's userdata.
+ **/
+void *video_driver_get_ptr(bool force_nonthreaded_data);
+
+/**
+ * video_driver_get_current_framebuffer:
+ *
+ * Gets pointer to current hardware renderer framebuffer object.
+ * Used by RETRO_ENVIRONMENT_SET_HW_RENDER.
+ *
+ * Returns: pointer to hardware framebuffer object, otherwise 0.
+ **/
+uintptr_t video_driver_get_current_framebuffer(void);
+
+retro_proc_address_t video_driver_get_proc_address(const char *sym);
+
+bool video_driver_set_shader(enum rarch_shader_type type,
+ const char *shader);
+
+bool video_driver_set_rotation(unsigned rotation);
+
+bool video_driver_set_video_mode(unsigned width,
+ unsigned height, bool fullscreen);
+
+bool video_driver_get_video_output_size(
+ unsigned *width, unsigned *height);
+
+void video_driver_set_osd_msg(const char *msg,
+ const void *params, void *font);
+
+void video_driver_set_texture_enable(bool enable, bool full_screen);
+
+void video_driver_set_texture_frame(const void *frame, bool rgb32,
+ unsigned width, unsigned height, float alpha);
+
+#ifdef HAVE_OVERLAY
+bool video_driver_overlay_interface(
+ const video_overlay_interface_t **iface);
+#endif
+
+void * video_driver_read_frame_raw(unsigned *width,
+ unsigned *height, size_t *pitch);
+
+void video_driver_set_filtering(unsigned index, bool smooth);
+
+const char *video_driver_get_ident(void);
+
+bool video_driver_set_viewport(unsigned width, unsigned height,
+ bool force_fullscreen, bool allow_rotate);
+
+void video_driver_get_size(unsigned *width, unsigned *height);
+
+void video_driver_set_size(unsigned *width, unsigned *height);
+
+void video_driver_unset_video_cache_context_ack(void);
+
+float video_driver_get_aspect_ratio(void);
+
+void video_driver_set_aspect_ratio_value(float value);
+
+rarch_softfilter_t *video_driver_frame_filter_get_ptr(void);
+
+enum retro_pixel_format video_driver_get_pixel_format(void);
+
+void video_driver_set_pixel_format(enum retro_pixel_format fmt);
+
+void video_driver_cached_frame_set(const void *data, unsigned width,
+ unsigned height, size_t pitch);
+
+void video_driver_cached_frame_get(const void **data, unsigned *width,
+ unsigned *height, size_t *pitch);
+
+void video_driver_menu_settings(void **list_data, void *list_info_data,
+ void *group_data, void *subgroup_data, const char *parent_group);
+
+/**
+ * video_viewport_get_scaled_integer:
+ * @vp : Viewport handle
+ * @width : Width.
+ * @height : Height.
+ * @aspect_ratio : Aspect ratio (in float).
+ * @keep_aspect : Preserve aspect ratio?
+ *
+ * Gets viewport scaling dimensions based on
+ * scaled integer aspect ratio.
+ **/
+void video_viewport_get_scaled_integer(struct video_viewport *vp,
+ unsigned width, unsigned height,
+ float aspect_ratio, bool keep_aspect);
+
+struct retro_system_av_info *video_viewport_get_system_av_info(void);
+
+struct video_viewport *video_viewport_get_custom(void);
+
+/**
+ * video_monitor_set_refresh_rate:
+ * @hz : New refresh rate for monitor.
+ *
+ * Sets monitor refresh rate to new value.
+ **/
+void video_monitor_set_refresh_rate(float hz);
+
+/**
+ * video_monitor_fps_statistics
+ * @refresh_rate : Monitor refresh rate.
+ * @deviation : Deviation from measured refresh rate.
+ * @sample_points : Amount of sampled points.
+ *
+ * Gets the monitor FPS statistics based on the current
+ * runtime.
+ *
+ * Returns: true (1) on success.
+ * false (0) if:
+ * a) threaded video mode is enabled
+ * b) less than 2 frame time samples.
+ * c) FPS monitor enable is off.
+ **/
+bool video_monitor_fps_statistics(double *refresh_rate,
+ double *deviation, unsigned *sample_points);
+
+unsigned video_pixel_get_alignment(unsigned pitch);
+
+const video_poke_interface_t *video_driver_get_poke(void);
+
+/**
+ * video_driver_frame:
+ * @data : pointer to data of the video frame.
+ * @width : width of the video frame.
+ * @height : height of the video frame.
+ * @pitch : pitch of the video frame.
+ *
+ * Video frame render callback function.
+ **/
+void video_driver_frame(const void *data, unsigned width,
+ unsigned height, size_t pitch);
+
+void crt_switch_driver_reinit(void);
+
+#define video_driver_translate_coord_viewport_wrap(vp, mouse_x, mouse_y, res_x, res_y, res_screen_x, res_screen_y) \
+ (video_driver_get_viewport_info(vp) ? video_driver_translate_coord_viewport(vp, mouse_x, mouse_y, res_x, res_y, res_screen_x, res_screen_y) : false)
+
+/**
+ * video_driver_translate_coord_viewport:
+ * @mouse_x : Pointer X coordinate.
+ * @mouse_y : Pointer Y coordinate.
+ * @res_x : Scaled X coordinate.
+ * @res_y : Scaled Y coordinate.
+ * @res_screen_x : Scaled screen X coordinate.
+ * @res_screen_y : Scaled screen Y coordinate.
+ *
+ * Translates pointer [X,Y] coordinates into scaled screen
+ * coordinates based on viewport info.
+ *
+ * Returns: true (1) if successful, false if video driver doesn't support
+ * viewport info.
+ **/
+bool video_driver_translate_coord_viewport(
+ struct video_viewport *vp,
+ int mouse_x, int mouse_y,
+ int16_t *res_x, int16_t *res_y, int16_t *res_screen_x,
+ int16_t *res_screen_y);
+
+uintptr_t video_driver_display_get(void);
+
+enum rarch_display_type video_driver_display_type_get(void);
+
+uintptr_t video_driver_window_get(void);
+
+void video_driver_display_type_set(enum rarch_display_type type);
+
+void video_driver_display_set(uintptr_t idx);
+
+void video_driver_window_set(uintptr_t idx);
+
+bool video_driver_texture_load(void *data,
+ enum texture_filter_type filter_type,
+ uintptr_t *id);
+
+bool video_driver_texture_unload(uintptr_t *id);
+
+void video_driver_build_info(video_frame_info_t *video_info);
+
+void video_driver_reinit(void);
+
+void video_driver_get_window_title(char *buf, unsigned len);
+
+void video_driver_get_record_status(
+ bool *has_gpu_record,
+ uint8_t **gpu_buf);
+
+bool *video_driver_get_threaded(void);
+
+void video_driver_set_threaded(bool val);
+
+void video_driver_get_status(uint64_t *frame_count, bool * is_alive,
+ bool *is_focused);
+
+/**
+ * video_context_driver_init_first:
+ * @data : Input data.
+ * @ident : Identifier of graphics context driver to find.
+ * @api : API of higher-level graphics API.
+ * @major : Major version number of higher-level graphics API.
+ * @minor : Minor version number of higher-level graphics API.
+ * @hw_render_ctx : Request a graphics context driver capable of
+ * hardware rendering?
+ *
+ * Finds first suitable graphics context driver and initializes.
+ *
+ * Returns: graphics context driver if found, otherwise NULL.
+ **/
+const gfx_ctx_driver_t *video_context_driver_init_first(
+ void *data, const char *ident,
+ enum gfx_ctx_api api, unsigned major, unsigned minor,
+ bool hw_render_ctx, void **ctx_data);
+
+bool video_context_driver_find_prev_driver(void);
+
+bool video_context_driver_find_next_driver(void);
+
+bool video_context_driver_init_image_buffer(const video_info_t *data);
+
+bool video_context_driver_write_to_image_buffer(gfx_ctx_image_t *img);
+
+bool video_context_driver_get_video_output_prev(void);
+
+bool video_context_driver_get_video_output_next(void);
+
+bool video_context_driver_bind_hw_render(bool *enable);
+
+void video_context_driver_make_current(bool restore);
+
+bool video_context_driver_set(const gfx_ctx_driver_t *data);
+
+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(int *interval);
+
+bool video_context_driver_get_proc_address(gfx_ctx_proc_address_t *proc);
+
+bool video_context_driver_suppress_screensaver(bool *bool_data);
+
+bool video_context_driver_get_ident(gfx_ctx_ident_t *ident);
+
+bool video_context_driver_set_video_mode(gfx_ctx_mode_t *mode_info);
+
+bool video_context_driver_get_video_size(gfx_ctx_mode_t *mode_info);
+
+bool video_context_driver_get_refresh_rate(float *refresh_rate);
+
+bool video_context_driver_show_mouse(bool *bool_data);
+
+bool video_context_driver_set_flags(gfx_ctx_flags_t *flags);
+
+bool video_context_driver_get_metrics(gfx_ctx_metrics_t *metrics);
+
+bool video_context_driver_translate_aspect(gfx_ctx_aspect_t *aspect);
+
+bool video_context_driver_input_driver(gfx_ctx_input_t *inp);
+
+enum gfx_ctx_api video_context_driver_get_api(void);
+
+void video_context_driver_free(void);
+
+bool video_shader_driver_get_prev_textures(video_shader_ctx_texture_t *texture);
+
+bool video_shader_driver_get_ident(video_shader_ctx_ident_t *ident);
+
+bool video_shader_driver_get_current_shader(video_shader_ctx_t *shader);
+
+bool video_shader_driver_direct_get_current_shader(video_shader_ctx_t *shader);
+
+bool video_shader_driver_deinit(void);
+
+void video_shader_driver_set_parameter(struct uniform_info *param);
+
+void video_shader_driver_set_parameters(video_shader_ctx_params_t *params);
+
+bool video_shader_driver_init_first(void);
+
+bool video_shader_driver_init(video_shader_ctx_init_t *init);
+
+bool video_shader_driver_get_feedback_pass(unsigned *data);
+
+bool video_shader_driver_mipmap_input(unsigned *index);
+
+void video_driver_set_coords(video_shader_ctx_coords_t *coords);
+
+bool video_shader_driver_scale(video_shader_ctx_scale_t *scaler);
+
+bool video_shader_driver_info(video_shader_ctx_info_t *shader_info);
+
+void video_driver_set_mvp(video_shader_ctx_mvp_t *mvp);
+
+bool video_shader_driver_filter_type(video_shader_ctx_filter_t *filter);
+
+bool video_shader_driver_compile_program(struct shader_program_info *program_info);
+
+void video_shader_driver_use(video_shader_ctx_info_t *shader_info);
+
+bool video_shader_driver_wrap_type(video_shader_ctx_wrap_t *wrap);
+
+float video_driver_get_refresh_rate(void);
+
+extern bool (*video_driver_cb_has_focus)(void);
+
+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;
+extern video_driver_t video_psp1;
+extern video_driver_t video_vita2d;
+extern video_driver_t video_ps2;
+extern video_driver_t video_ctr;
+extern video_driver_t video_switch;
+extern video_driver_t video_d3d8;
+extern video_driver_t video_d3d9;
+extern video_driver_t video_d3d10;
+extern video_driver_t video_d3d11;
+extern video_driver_t video_d3d12;
+extern video_driver_t video_gx;
+extern video_driver_t video_wiiu;
+extern video_driver_t video_xenon360;
+extern video_driver_t video_xvideo;
+extern video_driver_t video_sdl;
+extern video_driver_t video_sdl2;
+extern video_driver_t video_vg;
+extern video_driver_t video_omap;
+extern video_driver_t video_exynos;
+extern video_driver_t video_dispmanx;
+extern video_driver_t video_sunxi;
+extern video_driver_t video_drm;
+extern video_driver_t video_xshm;
+extern video_driver_t video_caca;
+extern video_driver_t video_gdi;
+extern video_driver_t video_vga;
+extern video_driver_t video_sixel;
+extern video_driver_t video_null;
+
+extern const gfx_ctx_driver_t gfx_ctx_osmesa;
+extern const gfx_ctx_driver_t gfx_ctx_sdl_gl;
+extern const gfx_ctx_driver_t gfx_ctx_x_egl;
+extern const gfx_ctx_driver_t gfx_ctx_wayland;
+extern const gfx_ctx_driver_t gfx_ctx_x;
+extern const gfx_ctx_driver_t gfx_ctx_drm;
+extern const gfx_ctx_driver_t gfx_ctx_mali_fbdev;
+extern const gfx_ctx_driver_t gfx_ctx_vivante_fbdev;
+extern const gfx_ctx_driver_t gfx_ctx_android;
+extern const gfx_ctx_driver_t gfx_ctx_ps3;
+extern const gfx_ctx_driver_t gfx_ctx_wgl;
+extern const gfx_ctx_driver_t gfx_ctx_videocore;
+extern const gfx_ctx_driver_t gfx_ctx_qnx;
+extern const gfx_ctx_driver_t gfx_ctx_cgl;
+extern const gfx_ctx_driver_t gfx_ctx_cocoagl;
+extern const gfx_ctx_driver_t gfx_ctx_emscripten;
+extern const gfx_ctx_driver_t gfx_ctx_opendingux_fbdev;
+extern const gfx_ctx_driver_t gfx_ctx_khr_display;
+extern const gfx_ctx_driver_t gfx_ctx_gdi;
+extern const gfx_ctx_driver_t gfx_ctx_sixel;
+extern const gfx_ctx_driver_t switch_ctx;
+extern const gfx_ctx_driver_t orbis_ctx;
+extern const gfx_ctx_driver_t gfx_ctx_null;
+
+extern const shader_backend_t gl_glsl_backend;
+extern const shader_backend_t gl_cg_backend;
+extern const shader_backend_t shader_null_backend;
+
+RETRO_END_DECLS
+
+#endif