Merge pull request #5320 from Cacodemon345/qt-openglrenderer-pcem
Port OpenGL 3.x renderer from PCem
This commit is contained in:
@@ -172,7 +172,6 @@ int force_43 = 0; /* (C) video *
|
|||||||
int video_filter_method = 1; /* (C) video */
|
int video_filter_method = 1; /* (C) video */
|
||||||
int video_vsync = 0; /* (C) video */
|
int video_vsync = 0; /* (C) video */
|
||||||
int video_framerate = -1; /* (C) video */
|
int video_framerate = -1; /* (C) video */
|
||||||
char video_shader[512] = { '\0' }; /* (C) video */
|
|
||||||
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of
|
bool serial_passthrough_enabled[SERIAL_MAX] = { 0, 0, 0, 0, 0, 0, 0 }; /* (C) activation and kind of
|
||||||
pass-through for serial ports */
|
pass-through for serial ports */
|
||||||
int bugger_enabled = 0; /* (C) enable ISAbugger */
|
int bugger_enabled = 0; /* (C) enable ISAbugger */
|
||||||
@@ -252,6 +251,8 @@ int unscaled_size_y = SCREEN_RES_Y; /* current unscaled size Y */
|
|||||||
int efscrnsz_y = SCREEN_RES_Y;
|
int efscrnsz_y = SCREEN_RES_Y;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
__thread int is_cpu_thread = 0;
|
||||||
|
|
||||||
static wchar_t mouse_msg[3][200];
|
static wchar_t mouse_msg[3][200];
|
||||||
|
|
||||||
static volatile atomic_int do_pause_ack = 0;
|
static volatile atomic_int do_pause_ack = 0;
|
||||||
|
|||||||
83
src/config.c
83
src/config.c
@@ -77,6 +77,10 @@
|
|||||||
#include <86box/snd_opl.h>
|
#include <86box/snd_opl.h>
|
||||||
#include <86box/version.h>
|
#include <86box/version.h>
|
||||||
|
|
||||||
|
/* Deliberate to not make the 86box.h header kitchen-sink. */
|
||||||
|
#include <86box/qt-glsl.h>
|
||||||
|
extern char gl3_shader_file[MAX_USER_SHADERS][512];
|
||||||
|
|
||||||
static int cx;
|
static int cx;
|
||||||
static int cy;
|
static int cy;
|
||||||
static int cw;
|
static int cw;
|
||||||
@@ -196,7 +200,6 @@ load_general(void)
|
|||||||
|
|
||||||
video_framerate = ini_section_get_int(cat, "video_gl_framerate", -1);
|
video_framerate = ini_section_get_int(cat, "video_gl_framerate", -1);
|
||||||
video_vsync = ini_section_get_int(cat, "video_gl_vsync", 0);
|
video_vsync = ini_section_get_int(cat, "video_gl_vsync", 0);
|
||||||
strncpy(video_shader, ini_section_get_string(cat, "video_gl_shader", ""), sizeof(video_shader) - 1);
|
|
||||||
|
|
||||||
window_remember = ini_section_get_int(cat, "window_remember", 0);
|
window_remember = ini_section_get_int(cat, "window_remember", 0);
|
||||||
if (window_remember) {
|
if (window_remember) {
|
||||||
@@ -1714,6 +1717,46 @@ load_other_peripherals(void)
|
|||||||
ini_section_delete_var(cat, temp);
|
ini_section_delete_var(cat, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load OpenGL 3.0 renderer options. */
|
||||||
|
static void
|
||||||
|
load_gl3_shaders(void)
|
||||||
|
{
|
||||||
|
ini_section_t cat = ini_find_section(config, "GL3 Shaders");
|
||||||
|
char *p;
|
||||||
|
char temp[512];
|
||||||
|
int i = 0, shaders = 0;
|
||||||
|
memset(temp, 0, sizeof(temp));
|
||||||
|
memset(gl3_shader_file, 0, sizeof(gl3_shader_file));
|
||||||
|
|
||||||
|
shaders = ini_section_get_int(cat, "shaders", 0);
|
||||||
|
if (shaders > MAX_USER_SHADERS)
|
||||||
|
shaders = MAX_USER_SHADERS;
|
||||||
|
|
||||||
|
if (shaders == 0) {
|
||||||
|
ini_section_t general = ini_find_section(config, "General");
|
||||||
|
if (general) {
|
||||||
|
p = ini_section_get_string(general, "video_gl_shader", NULL);
|
||||||
|
if (p) {
|
||||||
|
strncpy(gl3_shader_file[0], p, 512);
|
||||||
|
ini_delete_var(config, general, "video_gl_shader");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < shaders; i++) {
|
||||||
|
temp[0] = 0;
|
||||||
|
snprintf(temp, 512, "shader%d", i);
|
||||||
|
p = ini_section_get_string(cat, temp, "");
|
||||||
|
if (p[0]) {
|
||||||
|
strncpy(gl3_shader_file[i], p, 512);
|
||||||
|
} else {
|
||||||
|
gl3_shader_file[i][0] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Load the specified or a default configuration file. */
|
/* Load the specified or a default configuration file. */
|
||||||
void
|
void
|
||||||
config_load(void)
|
config_load(void)
|
||||||
@@ -1810,6 +1853,7 @@ config_load(void)
|
|||||||
load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */
|
load_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */
|
||||||
load_other_removable_devices(); /* Other removable devices */
|
load_other_removable_devices(); /* Other removable devices */
|
||||||
load_other_peripherals(); /* Other peripherals */
|
load_other_peripherals(); /* Other peripherals */
|
||||||
|
load_gl3_shaders(); /* GL3 Shaders */
|
||||||
|
|
||||||
/* Migrate renamed device configurations. */
|
/* Migrate renamed device configurations. */
|
||||||
c = ini_find_section(config, "MDA");
|
c = ini_find_section(config, "MDA");
|
||||||
@@ -2002,10 +2046,6 @@ save_general(void)
|
|||||||
ini_section_set_int(cat, "video_gl_vsync", video_vsync);
|
ini_section_set_int(cat, "video_gl_vsync", video_vsync);
|
||||||
else
|
else
|
||||||
ini_section_delete_var(cat, "video_gl_vsync");
|
ini_section_delete_var(cat, "video_gl_vsync");
|
||||||
if (strlen(video_shader) > 0)
|
|
||||||
ini_section_set_string(cat, "video_gl_shader", video_shader);
|
|
||||||
else
|
|
||||||
ini_section_delete_var(cat, "video_gl_shader");
|
|
||||||
|
|
||||||
if (do_auto_pause)
|
if (do_auto_pause)
|
||||||
ini_section_set_int(cat, "do_auto_pause", do_auto_pause);
|
ini_section_set_int(cat, "do_auto_pause", do_auto_pause);
|
||||||
@@ -2632,6 +2672,38 @@ save_other_peripherals(void)
|
|||||||
ini_delete_section_if_empty(config, cat);
|
ini_delete_section_if_empty(config, cat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save "GL3 Shaders" section. */
|
||||||
|
static void
|
||||||
|
save_gl3_shaders(void)
|
||||||
|
{
|
||||||
|
ini_section_t cat = ini_find_or_create_section(config, "GL3 Shaders");
|
||||||
|
char temp[512];
|
||||||
|
int shaders = 0, i = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_USER_SHADERS; i++) {
|
||||||
|
if (gl3_shader_file[i][0] == 0) {
|
||||||
|
temp[0] = 0;
|
||||||
|
snprintf(temp, 512, "shader%d", i);
|
||||||
|
ini_section_delete_var(cat, temp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
shaders++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_section_set_int(cat, "shaders", shaders);
|
||||||
|
if (shaders == 0) {
|
||||||
|
ini_section_delete_var(cat, "shaders");
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < shaders; i++) {
|
||||||
|
temp[0] = 0;
|
||||||
|
snprintf(temp, 512, "shader%d", i);
|
||||||
|
ini_section_set_string(cat, temp, gl3_shader_file[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_delete_section_if_empty(config, cat);
|
||||||
|
}
|
||||||
|
|
||||||
/* Save "Hard Disks" section. */
|
/* Save "Hard Disks" section. */
|
||||||
static void
|
static void
|
||||||
save_hard_disks(void)
|
save_hard_disks(void)
|
||||||
@@ -2987,6 +3059,7 @@ config_save(void)
|
|||||||
save_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */
|
save_floppy_and_cdrom_drives(); /* Floppy and CD-ROM drives */
|
||||||
save_other_removable_devices(); /* Other removable devices */
|
save_other_removable_devices(); /* Other removable devices */
|
||||||
save_other_peripherals(); /* Other peripherals */
|
save_other_peripherals(); /* Other peripherals */
|
||||||
|
save_gl3_shaders(); /* GL3 Shaders */
|
||||||
|
|
||||||
ini_write(config, cfg_path);
|
ini_write(config, cfg_path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,6 @@ extern int video_filter_method; /* (C) video */
|
|||||||
extern int video_vsync; /* (C) video */
|
extern int video_vsync; /* (C) video */
|
||||||
extern int video_framerate; /* (C) video */
|
extern int video_framerate; /* (C) video */
|
||||||
extern int gfxcard[GFXCARD_MAX]; /* (C) graphics/video card */
|
extern int gfxcard[GFXCARD_MAX]; /* (C) graphics/video card */
|
||||||
extern char video_shader[512]; /* (C) video */
|
|
||||||
extern int bugger_enabled; /* (C) enable ISAbugger */
|
extern int bugger_enabled; /* (C) enable ISAbugger */
|
||||||
extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */
|
extern int novell_keycard_enabled; /* (C) enable Novell NetWare 2.x key card emulation. */
|
||||||
extern int postcard_enabled; /* (C) enable POST card */
|
extern int postcard_enabled; /* (C) enable POST card */
|
||||||
@@ -188,6 +187,8 @@ extern FILE *stdlog; /* file to log output to */
|
|||||||
#endif
|
#endif
|
||||||
extern int config_changed; /* config has changed */
|
extern int config_changed; /* config has changed */
|
||||||
|
|
||||||
|
extern __thread int is_cpu_thread; /* Is this the CPU thread? */
|
||||||
|
|
||||||
/* Function prototypes. */
|
/* Function prototypes. */
|
||||||
#ifdef HAVE_STDARG_H
|
#ifdef HAVE_STDARG_H
|
||||||
extern void pclog_ex(const char *fmt, va_list ap);
|
extern void pclog_ex(const char *fmt, va_list ap);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ typedef void *ini_section_t;
|
|||||||
|
|
||||||
extern ini_t ini_new(void);
|
extern ini_t ini_new(void);
|
||||||
extern ini_t ini_read(const char *fn);
|
extern ini_t ini_read(const char *fn);
|
||||||
|
extern void ini_strip_quotes(ini_t ini);
|
||||||
extern void ini_write(ini_t ini, const char *fn);
|
extern void ini_write(ini_t ini, const char *fn);
|
||||||
extern void ini_dump(ini_t ini);
|
extern void ini_dump(ini_t ini);
|
||||||
extern void ini_close(ini_t ini);
|
extern void ini_close(ini_t ini);
|
||||||
@@ -58,6 +59,7 @@ extern void ini_section_set_hex20(ini_section_t section, const char *name, i
|
|||||||
extern void ini_section_set_mac(ini_section_t section, const char *name, int val);
|
extern void ini_section_set_mac(ini_section_t section, const char *name, int val);
|
||||||
extern void ini_section_set_string(ini_section_t section, const char *name, const char *val);
|
extern void ini_section_set_string(ini_section_t section, const char *name, const char *val);
|
||||||
extern void ini_section_set_wstring(ini_section_t section, const char *name, wchar_t *val);
|
extern void ini_section_set_wstring(ini_section_t section, const char *name, wchar_t *val);
|
||||||
|
extern int ini_has_entry(ini_section_t self, const char *name);
|
||||||
|
|
||||||
#define ini_delete_var(ini, head, name) ini_section_delete_var(ini_find_section(ini, head), name)
|
#define ini_delete_var(ini, head, name) ini_section_delete_var(ini_find_section(ini, head), name)
|
||||||
|
|
||||||
|
|||||||
@@ -54,16 +54,16 @@ typedef struct kbc_at_port_t {
|
|||||||
typedef struct atkbc_dev_t {
|
typedef struct atkbc_dev_t {
|
||||||
const char *name; /* name of this device */
|
const char *name; /* name of this device */
|
||||||
|
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t command;
|
uint8_t command;
|
||||||
uint8_t last_scan_code;
|
uint8_t last_scan_code;
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint8_t resolution;
|
uint8_t resolution;
|
||||||
uint8_t rate;
|
uint8_t rate;
|
||||||
uint8_t cmd_queue_start;
|
uint8_t cmd_queue_start;
|
||||||
uint8_t cmd_queue_end;
|
uint8_t cmd_queue_end;
|
||||||
uint8_t queue_start;
|
uint8_t queue_start;
|
||||||
uint8_t queue_end;
|
uint8_t queue_end;
|
||||||
|
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
|
|
||||||
|
|||||||
158
src/include/86box/qt-glsl.h
Normal file
158
src/include/86box/qt-glsl.h
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#ifndef SRC_WX_GLSL_H_
|
||||||
|
#define SRC_WX_GLSL_H_
|
||||||
|
|
||||||
|
#define MAX_PREV 7
|
||||||
|
|
||||||
|
#define MAX_SHADERS 20
|
||||||
|
#define MAX_TEXTURES 20
|
||||||
|
#define MAX_PARAMETERS 100
|
||||||
|
|
||||||
|
#define MAX_USER_SHADERS 20
|
||||||
|
//#define SDL2_SHADER_DEBUG
|
||||||
|
|
||||||
|
struct shader_scale {
|
||||||
|
int mode[2];
|
||||||
|
float value[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_state {
|
||||||
|
float input_size[2];
|
||||||
|
float input_texture_size[2];
|
||||||
|
float output_texture_size[2];
|
||||||
|
float output_size[2];
|
||||||
|
float tex_coords[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_vbo {
|
||||||
|
int vertex_coord;
|
||||||
|
int tex_coord;
|
||||||
|
int color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_texture {
|
||||||
|
int id;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int type;
|
||||||
|
int internal_format;
|
||||||
|
int format;
|
||||||
|
int min_filter;
|
||||||
|
int mag_filter;
|
||||||
|
int wrap_mode;
|
||||||
|
void *data;
|
||||||
|
int mipmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_lut_texture {
|
||||||
|
char name[50];
|
||||||
|
struct shader_texture texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_fbo {
|
||||||
|
int id;
|
||||||
|
struct shader_texture texture;
|
||||||
|
int srgb;
|
||||||
|
int mipmap_input;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_prev {
|
||||||
|
struct shader_fbo fbo;
|
||||||
|
struct shader_vbo vbo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_input {
|
||||||
|
int texture;
|
||||||
|
int input_size;
|
||||||
|
int texture_size;
|
||||||
|
int tex_coord;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_uniforms {
|
||||||
|
int mvp_matrix;
|
||||||
|
int vertex_coord;
|
||||||
|
int tex_coord;
|
||||||
|
int color;
|
||||||
|
|
||||||
|
int texture;
|
||||||
|
int input_size;
|
||||||
|
int texture_size;
|
||||||
|
int output_size;
|
||||||
|
|
||||||
|
int frame_count;
|
||||||
|
int frame_direction;
|
||||||
|
|
||||||
|
struct shader_input orig;
|
||||||
|
struct shader_input pass[MAX_SHADERS];
|
||||||
|
struct shader_input prev_pass[MAX_SHADERS];
|
||||||
|
struct shader_input prev[MAX_PREV];
|
||||||
|
|
||||||
|
int parameters[MAX_PARAMETERS];
|
||||||
|
int lut_textures[MAX_TEXTURES];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_program {
|
||||||
|
int vertex_shader;
|
||||||
|
int fragment_shader;
|
||||||
|
int id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_parameter {
|
||||||
|
char id[64];
|
||||||
|
char description[64];
|
||||||
|
float default_value;
|
||||||
|
float value;
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
|
float step;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader_pass {
|
||||||
|
int active;
|
||||||
|
char alias[64];
|
||||||
|
int vertex_array;
|
||||||
|
int frame_count_mod;
|
||||||
|
struct shader_program program;
|
||||||
|
struct shader_uniforms uniforms;
|
||||||
|
struct shader_fbo fbo;
|
||||||
|
struct shader_vbo vbo;
|
||||||
|
struct shader_state state;
|
||||||
|
struct shader_scale scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct glsl_shader {
|
||||||
|
int active;
|
||||||
|
char name[64];
|
||||||
|
|
||||||
|
int num_passes;
|
||||||
|
struct shader_pass passes[MAX_SHADERS];
|
||||||
|
|
||||||
|
int num_lut_textures;
|
||||||
|
struct shader_lut_texture lut_textures[MAX_TEXTURES];
|
||||||
|
|
||||||
|
int num_parameters;
|
||||||
|
struct shader_parameter parameters[MAX_PARAMETERS];
|
||||||
|
|
||||||
|
struct shader_pass prev_scene;
|
||||||
|
struct shader_prev prev[MAX_PREV + 1];
|
||||||
|
|
||||||
|
int last_prev_update;
|
||||||
|
int has_prev;
|
||||||
|
|
||||||
|
float shader_refresh_rate;
|
||||||
|
|
||||||
|
int input_filter_linear;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct glsl_t {
|
||||||
|
int num_shaders;
|
||||||
|
struct glsl_shader shaders[MAX_USER_SHADERS];
|
||||||
|
struct shader_pass scene;
|
||||||
|
struct shader_pass final_pass;
|
||||||
|
struct shader_pass fs_color;
|
||||||
|
#ifdef SDL2_SHADER_DEBUG
|
||||||
|
struct shader_pass debug;
|
||||||
|
#endif
|
||||||
|
int srgb;
|
||||||
|
} glsl_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
59
src/include/86box/qt-glslp-parser.h
Normal file
59
src/include/86box/qt-glslp-parser.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#ifndef SRC_WX_GLSLP_PARSER_H_
|
||||||
|
#define SRC_WX_GLSLP_PARSER_H_
|
||||||
|
|
||||||
|
#include "qt-glsl.h"
|
||||||
|
|
||||||
|
struct parameter {
|
||||||
|
char id[64];
|
||||||
|
char description[64];
|
||||||
|
float default_value;
|
||||||
|
float value;
|
||||||
|
float min;
|
||||||
|
float max;
|
||||||
|
float step;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct texture {
|
||||||
|
char path[256];
|
||||||
|
char name[50];
|
||||||
|
int linear;
|
||||||
|
int mipmap;
|
||||||
|
char wrap_mode[50];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct shader {
|
||||||
|
char shader_fn[1024];
|
||||||
|
char *shader_program;
|
||||||
|
char alias[64];
|
||||||
|
int filter_linear;
|
||||||
|
int float_framebuffer;
|
||||||
|
int srgb_framebuffer;
|
||||||
|
int mipmap_input;
|
||||||
|
int frame_count_mod;
|
||||||
|
char wrap_mode[50];
|
||||||
|
char scale_type_x[9], scale_type_y[9];
|
||||||
|
float scale_x, scale_y;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct glslp_t {
|
||||||
|
char name[64];
|
||||||
|
int num_shaders;
|
||||||
|
struct shader shaders[MAX_SHADERS];
|
||||||
|
|
||||||
|
int num_textures;
|
||||||
|
struct texture textures[MAX_TEXTURES];
|
||||||
|
|
||||||
|
int num_parameters;
|
||||||
|
struct parameter parameters[MAX_PARAMETERS];
|
||||||
|
|
||||||
|
int input_filter_linear;
|
||||||
|
} glslp_t;
|
||||||
|
|
||||||
|
void get_glslp_name(const char *f, char *s, int size);
|
||||||
|
glslp_t *glslp_parse(const char *f);
|
||||||
|
void glslp_free(glslp_t *p);
|
||||||
|
|
||||||
|
void glslp_read_shader_config(glslp_t *shader);
|
||||||
|
void glslp_write_shader_config(glslp_t *shader);
|
||||||
|
|
||||||
|
#endif /* SRC_WX_GLSLP_PARSER_H_ */
|
||||||
133
src/ini.c
133
src/ini.c
@@ -157,6 +157,22 @@ find_entry(section_t *section, const char *name)
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ini_has_entry(ini_section_t self, const char *name)
|
||||||
|
{
|
||||||
|
section_t *section = (section_t *) self;
|
||||||
|
const entry_t *entry;
|
||||||
|
|
||||||
|
if (section == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
entry = find_entry(section, name);
|
||||||
|
if (entry == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
entries_num(section_t *section)
|
entries_num(section_t *section)
|
||||||
{
|
{
|
||||||
@@ -237,9 +253,8 @@ ini_delete_section_if_empty(ini_t ini, ini_section_t section)
|
|||||||
static section_t *
|
static section_t *
|
||||||
create_section(list_t *head, const char *name)
|
create_section(list_t *head, const char *name)
|
||||||
{
|
{
|
||||||
section_t *ns = malloc(sizeof(section_t));
|
section_t *ns = calloc(1, sizeof(section_t));
|
||||||
|
|
||||||
memset(ns, 0x00, sizeof(section_t));
|
|
||||||
memcpy(ns->name, name, strlen(name) + 1);
|
memcpy(ns->name, name, strlen(name) + 1);
|
||||||
list_add(&ns->list, head);
|
list_add(&ns->list, head);
|
||||||
|
|
||||||
@@ -262,9 +277,8 @@ ini_find_or_create_section(ini_t ini, const char *name)
|
|||||||
static entry_t *
|
static entry_t *
|
||||||
create_entry(section_t *section, const char *name)
|
create_entry(section_t *section, const char *name)
|
||||||
{
|
{
|
||||||
entry_t *ne = malloc(sizeof(entry_t));
|
entry_t *ne = calloc(1, sizeof(entry_t));
|
||||||
|
|
||||||
memset(ne, 0x00, sizeof(entry_t));
|
|
||||||
memcpy(ne->name, name, strlen(name) + 1);
|
memcpy(ne->name, name, strlen(name) + 1);
|
||||||
list_add(&ne->list, §ion->entry_head);
|
list_add(&ne->list, §ion->entry_head);
|
||||||
|
|
||||||
@@ -373,11 +387,8 @@ ini_read(const char *fn)
|
|||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
head = malloc(sizeof(list_t));
|
head = calloc(1, sizeof(list_t));
|
||||||
memset(head, 0x00, sizeof(list_t));
|
sec = calloc(1, sizeof(section_t));
|
||||||
|
|
||||||
sec = malloc(sizeof(section_t));
|
|
||||||
memset(sec, 0x00, sizeof(section_t));
|
|
||||||
|
|
||||||
list_add(&sec->list, head);
|
list_add(&sec->list, head);
|
||||||
if (bom)
|
if (bom)
|
||||||
@@ -458,7 +469,7 @@ ini_read(const char *fn)
|
|||||||
d = c;
|
d = c;
|
||||||
|
|
||||||
/* Allocate a new variable entry.. */
|
/* Allocate a new variable entry.. */
|
||||||
ne = malloc(sizeof(entry_t));
|
ne = calloc(1, sizeof(entry_t));
|
||||||
memset(ne, 0x00, sizeof(entry_t));
|
memset(ne, 0x00, sizeof(entry_t));
|
||||||
memcpy(ne->name, ename, 128);
|
memcpy(ne->name, ename, 128);
|
||||||
wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata) - 1);
|
wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata) - 1);
|
||||||
@@ -534,6 +545,103 @@ ini_write(ini_t ini, const char *fn)
|
|||||||
(void) fclose(fp);
|
(void) fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Wide-character version of "trim" */
|
||||||
|
wchar_t *
|
||||||
|
trim_w(wchar_t *str)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
wchar_t *frontp = str;
|
||||||
|
wchar_t *endp = NULL;
|
||||||
|
|
||||||
|
if (str == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (str[0] == L'\0') {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = wcslen(str);
|
||||||
|
endp = str + len;
|
||||||
|
|
||||||
|
/* Move the front and back pointers to address the first non-whitespace
|
||||||
|
* characters from each end.
|
||||||
|
*/
|
||||||
|
while (iswspace((wint_t) *frontp)) {
|
||||||
|
++frontp;
|
||||||
|
}
|
||||||
|
if (endp != frontp) {
|
||||||
|
while (iswspace((wint_t) *(--endp)) && endp != frontp) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontp != str && endp == frontp)
|
||||||
|
*str = L'\0';
|
||||||
|
else if ((str + len - 1) != endp)
|
||||||
|
*(endp + 1) = L'\0';
|
||||||
|
|
||||||
|
/* Shift the string so that it starts at str so that if it's dynamically
|
||||||
|
* allocated, we can still free it on the returned pointer. Note the reuse
|
||||||
|
* of endp to mean the front of the string buffer now.
|
||||||
|
*/
|
||||||
|
endp = str;
|
||||||
|
if (frontp != str) {
|
||||||
|
while (*frontp) {
|
||||||
|
*endp++ = *frontp++;
|
||||||
|
}
|
||||||
|
*endp = L'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char* trim(char* str);
|
||||||
|
|
||||||
|
void
|
||||||
|
ini_strip_quotes(ini_t ini)
|
||||||
|
{
|
||||||
|
list_t *list = (list_t *) ini;
|
||||||
|
section_t *sec;
|
||||||
|
|
||||||
|
sec = (section_t *) list->next;
|
||||||
|
|
||||||
|
while (sec != NULL) {
|
||||||
|
entry_t *ent;
|
||||||
|
|
||||||
|
ent = (entry_t *) sec->entry_head.next;
|
||||||
|
while (ent != NULL) {
|
||||||
|
if (ent->name[0] != '\0') {
|
||||||
|
int trailing_hash = strcspn(ent->data, "#");
|
||||||
|
int trailing_quote;
|
||||||
|
ent->wdata[trailing_hash] = 0;
|
||||||
|
ent->data[trailing_hash] = 0;
|
||||||
|
if (ent->wdata[0] == L'\"') {
|
||||||
|
memmove(ent->wdata, &ent->wdata[1], sizeof(ent->wdata) - sizeof(wchar_t));
|
||||||
|
}
|
||||||
|
if (ent->wdata[wcslen(ent->wdata) - 1] == L'\"') {
|
||||||
|
ent->wdata[wcslen(ent->wdata) - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ent->data[0] == '\"') {
|
||||||
|
memmove(ent->data, &ent->data[1], sizeof(ent->data) - sizeof(char));
|
||||||
|
}
|
||||||
|
if (ent->data[strlen(ent->data) - 1] == '\"') {
|
||||||
|
ent->data[strlen(ent->data) - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
trailing_quote = strcspn(ent->data, "\"");
|
||||||
|
ent->wdata[trailing_quote] = 0;
|
||||||
|
ent->data[trailing_quote] = 0;
|
||||||
|
|
||||||
|
trim_w(ent->wdata);
|
||||||
|
trim(ent->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ent = (entry_t *) ent->list.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
sec = (section_t *) sec->list.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ini_t
|
ini_t
|
||||||
ini_new(void)
|
ini_new(void)
|
||||||
{
|
{
|
||||||
@@ -593,6 +701,11 @@ ini_section_get_int(ini_section_t self, const char *name, int def)
|
|||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
return def;
|
return def;
|
||||||
|
|
||||||
|
if (stricmp(entry->data, "true") == 0)
|
||||||
|
return 1;
|
||||||
|
if (stricmp(entry->data, "false") == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
sscanf(entry->data, "%i", &value);
|
sscanf(entry->data, "%i", &value);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@@ -89,11 +89,7 @@ add_library(ui STATIC
|
|||||||
qt_hardwarerenderer.hpp
|
qt_hardwarerenderer.hpp
|
||||||
qt_openglrenderer.cpp
|
qt_openglrenderer.cpp
|
||||||
qt_openglrenderer.hpp
|
qt_openglrenderer.hpp
|
||||||
qt_opengloptions.cpp
|
qt_glsl_parser.cpp
|
||||||
qt_opengloptions.hpp
|
|
||||||
qt_opengloptionsdialog.cpp
|
|
||||||
qt_opengloptionsdialog.hpp
|
|
||||||
qt_opengloptionsdialog.ui
|
|
||||||
|
|
||||||
qt_settings.cpp
|
qt_settings.cpp
|
||||||
qt_settings.hpp
|
qt_settings.hpp
|
||||||
@@ -190,6 +186,14 @@ add_library(ui STATIC
|
|||||||
|
|
||||||
../qt_resources.qrc
|
../qt_resources.qrc
|
||||||
./qdarkstyle/dark/darkstyle.qrc
|
./qdarkstyle/dark/darkstyle.qrc
|
||||||
|
|
||||||
|
qt_openglshadermanagerdialog.hpp
|
||||||
|
qt_openglshadermanagerdialog.cpp
|
||||||
|
qt_openglshadermanagerdialog.ui
|
||||||
|
|
||||||
|
qt_openglshaderconfig.hpp
|
||||||
|
qt_openglshaderconfig.cpp
|
||||||
|
qt_openglshaderconfig.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
if(RTMIDI)
|
if(RTMIDI)
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ plat_vidapi(const char *api)
|
|||||||
return 4;
|
return 4;
|
||||||
} else if (!strcasecmp(api, "vnc")) {
|
} else if (!strcasecmp(api, "vnc")) {
|
||||||
return 5;
|
return 5;
|
||||||
|
} else if (!strcasecmp(api, "qt_opengl3_pcem")) {
|
||||||
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -83,6 +85,9 @@ plat_vidapi_name(int api)
|
|||||||
case 5:
|
case 5:
|
||||||
name = "vnc";
|
name = "vnc";
|
||||||
break;
|
break;
|
||||||
|
case 6:
|
||||||
|
name = "qt_opengl3_pcem";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fatal("Unknown renderer: %i\n", api);
|
fatal("Unknown renderer: %i\n", api);
|
||||||
break;
|
break;
|
||||||
|
|||||||
384
src/qt/qt_glsl_parser.cpp
Normal file
384
src/qt/qt_glsl_parser.cpp
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
#include "qt_mainwindow.hpp"
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QWindow>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
|
extern MainWindow* main_window;
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/ini.h>
|
||||||
|
#include <86box/config.h>
|
||||||
|
#include <86box/qt-glslp-parser.h>
|
||||||
|
#include <86box/path.h>
|
||||||
|
|
||||||
|
extern void startblit();
|
||||||
|
extern void endblit();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define safe_strncpy(a, b, n) \
|
||||||
|
do { \
|
||||||
|
strncpy((a), (b), (n)-1); \
|
||||||
|
(a)[(n)-1] = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static inline void *wx_config_load(const char *path) { ini_t ini = ini_read(path); if (ini) ini_strip_quotes(ini); return (void*)ini; }
|
||||||
|
|
||||||
|
static inline int wx_config_get_string(void *config, const char *name, char *dst, int size, const char *defVal) {
|
||||||
|
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||||
|
char* str = ini_get_string((ini_t)config, "", name, (char*)defVal);
|
||||||
|
if (size == 0)
|
||||||
|
return res;
|
||||||
|
if (str != NULL)
|
||||||
|
strncpy(dst, str, size - 1);
|
||||||
|
else
|
||||||
|
dst[0] = 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wx_config_get_int(void *config, const char *name, int *dst, int defVal) {
|
||||||
|
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||||
|
*dst = ini_get_int((ini_t)config, "", name, defVal);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wx_config_get_float(void *config, const char *name, float *dst, float defVal) {
|
||||||
|
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||||
|
*dst = (float)ini_get_double((ini_t)config, "", name, defVal);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wx_config_get_bool(void *config, const char *name, int *dst, int defVal) {
|
||||||
|
int res = ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name);
|
||||||
|
*dst = !!ini_get_int((ini_t)config, "", name, defVal);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wx_config_has_entry(void *config, const char *name) { return ini_has_entry(ini_find_or_create_section((ini_t)config, ""), name); }
|
||||||
|
static inline void wx_config_free(void *config) { ini_close(config); };
|
||||||
|
|
||||||
|
static int endswith(const char *str, const char *ext) {
|
||||||
|
int i;
|
||||||
|
const char *p;
|
||||||
|
int elen = strlen(ext);
|
||||||
|
int slen = strlen(str);
|
||||||
|
if (slen >= elen) {
|
||||||
|
p = &str[slen - elen];
|
||||||
|
for (i = 0; i < elen; ++i) {
|
||||||
|
if (tolower(p[i]) != tolower(ext[i]))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *load_file(const char *fn) {
|
||||||
|
FILE *f = fopen(fn, "rb");
|
||||||
|
if (!f)
|
||||||
|
return 0;
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long fsize = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
char *data = (char*)malloc(fsize + 1);
|
||||||
|
|
||||||
|
fread(data, fsize, 1, f);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
data[fsize] = 0;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void strip_lines(const char *program, const char *starts_with) {
|
||||||
|
/* strip parameters */
|
||||||
|
char *ptr = strstr(program, starts_with);
|
||||||
|
while (ptr) {
|
||||||
|
while (*ptr != '\n' && *ptr != '\0')
|
||||||
|
*ptr++ = ' ';
|
||||||
|
ptr = strstr(program, starts_with);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void strip_parameters(const char *program) {
|
||||||
|
/* strip parameters */
|
||||||
|
strip_lines(program, "#pragma parameter");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void strip_defines(const char *program) {
|
||||||
|
/* strip texture define */
|
||||||
|
strip_lines(program, "#define texture");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int has_parameter(glslp_t *glsl, char *id) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < glsl->num_parameters; ++i)
|
||||||
|
if (!strcmp(glsl->parameters[i].id, id))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_parameters(glslp_t *glsl) {
|
||||||
|
int i;
|
||||||
|
struct parameter p;
|
||||||
|
for (i = 0; i < glsl->num_shaders; ++i) {
|
||||||
|
struct shader *shader = &glsl->shaders[i];
|
||||||
|
FILE *f = fopen(shader->shader_fn, "rb");
|
||||||
|
if (!f)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char line[1024];
|
||||||
|
while (fgets(line, sizeof(line) - 1, f) && glsl->num_parameters < MAX_PARAMETERS) {
|
||||||
|
int num = sscanf(line, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", p.id, p.description,
|
||||||
|
&p.default_value, &p.min, &p.max, &p.step);
|
||||||
|
if (num < 5)
|
||||||
|
continue;
|
||||||
|
p.id[63] = 0;
|
||||||
|
p.description[63] = 0;
|
||||||
|
|
||||||
|
if (num == 5)
|
||||||
|
p.step = 0.1f * (p.max - p.min);
|
||||||
|
|
||||||
|
p.value = p.default_value;
|
||||||
|
|
||||||
|
if (!has_parameter(glsl, p.id)) {
|
||||||
|
memcpy(&glsl->parameters[glsl->num_parameters++], &p, sizeof(struct parameter));
|
||||||
|
pclog("Read parameter: %s (%s) %f, %f -> %f (%f)\n", p.id, p.description, p.default_value, p.min,
|
||||||
|
p.max, p.step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct parameter *get_parameter(glslp_t *glslp, const char *id) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < glslp->num_parameters; ++i) {
|
||||||
|
if (!strcmp(glslp->parameters[i].id, id)) {
|
||||||
|
return &glslp->parameters[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static glslp_t *glsl_parse(const char *f) {
|
||||||
|
glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t));
|
||||||
|
memset(glslp, 0, sizeof(glslp_t));
|
||||||
|
glslp->num_shaders = 1;
|
||||||
|
struct shader *shader = &glslp->shaders[0];
|
||||||
|
strcpy(shader->shader_fn, f);
|
||||||
|
shader->shader_program = load_file(f);
|
||||||
|
if (!shader->shader_program) {
|
||||||
|
QMessageBox::critical((QWidget *) qApp->findChild<QWindow *>(), QObject::tr("GLSL error"), QObject::tr("Could not load shader %1").arg(shader->shader_fn));
|
||||||
|
//wx_simple_messagebox("GLSL error", "Could not load shader %s\n", shader->shader_fn);
|
||||||
|
glslp_free(glslp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strip_parameters(shader->shader_program);
|
||||||
|
strip_defines(shader->shader_program);
|
||||||
|
shader->scale_x = shader->scale_y = 1.0f;
|
||||||
|
strcpy(shader->scale_type_x, "source");
|
||||||
|
strcpy(shader->scale_type_y, "source");
|
||||||
|
get_parameters(glslp);
|
||||||
|
return glslp;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
void get_glslp_name(const char *f, char *s, int size) { safe_strncpy(s, path_get_filename((char *)f), size); }
|
||||||
|
|
||||||
|
glslp_t *glslp_parse(const char *f) {
|
||||||
|
int i, j, len, sublen;
|
||||||
|
char s[513], t[513], z[540];
|
||||||
|
|
||||||
|
memset(s, 0, sizeof(s));
|
||||||
|
if (endswith(f, ".glsl"))
|
||||||
|
return glsl_parse(f);
|
||||||
|
|
||||||
|
void *cfg = wx_config_load(f);
|
||||||
|
|
||||||
|
if (!cfg) {
|
||||||
|
fprintf(stderr, "GLSLP Error: Could not load GLSLP-file %s\n", f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glslp_t *glslp = (glslp_t*)malloc(sizeof(glslp_t));
|
||||||
|
memset(glslp, 0, sizeof(glslp_t));
|
||||||
|
|
||||||
|
get_glslp_name(f, glslp->name, sizeof(glslp->name));
|
||||||
|
|
||||||
|
wx_config_get_int(cfg, "shaders", &glslp->num_shaders, 0);
|
||||||
|
|
||||||
|
wx_config_get_bool(cfg, "filter_linear0", &glslp->input_filter_linear, -1);
|
||||||
|
|
||||||
|
for (i = 0; i < glslp->num_shaders; ++i) {
|
||||||
|
struct shader *shader = &glslp->shaders[i];
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "shader%d", i);
|
||||||
|
if (!wx_config_get_string(cfg, s, t, sizeof(t), 0)) {
|
||||||
|
/* shader doesn't exist, lets break here */
|
||||||
|
glslp->num_shaders = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strcpy(s, f);
|
||||||
|
*path_get_filename(s) = 0;
|
||||||
|
snprintf(shader->shader_fn, sizeof(shader->shader_fn) - 1, "%s%s", s, t);
|
||||||
|
shader->shader_program = load_file(shader->shader_fn);
|
||||||
|
if (!shader->shader_program) {
|
||||||
|
fprintf(stderr, "GLSLP Error: Could not load shader %s\n", shader->shader_fn);
|
||||||
|
glslp_free(glslp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strip_parameters(shader->shader_program);
|
||||||
|
strip_defines(shader->shader_program);
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "alias%d", i);
|
||||||
|
wx_config_get_string(cfg, s, shader->alias, sizeof(shader->alias), 0);
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "filter_linear%d", i + 1);
|
||||||
|
wx_config_get_bool(cfg, s, &shader->filter_linear, 0);
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "wrap_mode%d", i);
|
||||||
|
wx_config_get_string(cfg, s, shader->wrap_mode, sizeof(shader->wrap_mode), 0);
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "float_framebuffer%d", i);
|
||||||
|
wx_config_get_bool(cfg, s, &shader->float_framebuffer, 0);
|
||||||
|
snprintf(s, sizeof(s) - 1, "srgb_framebuffer%d", i);
|
||||||
|
wx_config_get_bool(cfg, s, &shader->srgb_framebuffer, 0);
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "mipmap_input%d", i);
|
||||||
|
wx_config_get_bool(cfg, s, &shader->mipmap_input, 0);
|
||||||
|
|
||||||
|
strcpy(shader->scale_type_x, "source");
|
||||||
|
snprintf(s, sizeof(s) - 1, "scale_type_x%d", i);
|
||||||
|
wx_config_get_string(cfg, s, shader->scale_type_x, sizeof(shader->scale_type_x), 0);
|
||||||
|
strcpy(shader->scale_type_y, "source");
|
||||||
|
snprintf(s, sizeof(s) - 1, "scale_type_y%d", i);
|
||||||
|
wx_config_get_string(cfg, s, shader->scale_type_y, sizeof(shader->scale_type_y), 0);
|
||||||
|
snprintf(s, sizeof(s) - 1, "scale_type%d", i);
|
||||||
|
if (wx_config_has_entry(cfg, s)) {
|
||||||
|
wx_config_get_string(cfg, s, shader->scale_type_x, sizeof(shader->scale_type_x), 0);
|
||||||
|
wx_config_get_string(cfg, s, shader->scale_type_y, sizeof(shader->scale_type_y), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "scale_x%d", i);
|
||||||
|
wx_config_get_float(cfg, s, &shader->scale_x, 1.0f);
|
||||||
|
snprintf(s, sizeof(s) - 1, "scale_y%d", i);
|
||||||
|
wx_config_get_float(cfg, s, &shader->scale_y, 1.0f);
|
||||||
|
snprintf(s, sizeof(s) - 1, "scale%d", i);
|
||||||
|
if (wx_config_has_entry(cfg, s)) {
|
||||||
|
wx_config_get_float(cfg, s, &shader->scale_x, 1.0f);
|
||||||
|
wx_config_get_float(cfg, s, &shader->scale_y, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(s, sizeof(s) - 1, "frame_count_mod%d", i);
|
||||||
|
wx_config_get_int(cfg, s, &shader->frame_count_mod, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* textures */
|
||||||
|
glslp->num_textures = 0;
|
||||||
|
wx_config_get_string(cfg, "textures", t, sizeof(t), 0);
|
||||||
|
|
||||||
|
len = strlen(t);
|
||||||
|
j = 0;
|
||||||
|
sublen = 0;
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
if (t[i] == ';' || i == len - 1) {
|
||||||
|
sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1;
|
||||||
|
safe_strncpy(s, t + j, sublen);
|
||||||
|
s[511 < sublen ? 511 : sublen] = 0;
|
||||||
|
|
||||||
|
if (s[strlen(s) - 1] == ';') s[strlen(s) - 1] = 0;
|
||||||
|
|
||||||
|
struct texture *tex = &glslp->textures[glslp->num_textures++];
|
||||||
|
|
||||||
|
strcpy(tex->name, s);
|
||||||
|
wx_config_get_string(cfg, s, tex->path, sizeof(tex->path), 0);
|
||||||
|
|
||||||
|
snprintf(z, sizeof(z) - 1, "%s_linear", s);
|
||||||
|
wx_config_get_bool(cfg, z, &tex->linear, 0);
|
||||||
|
|
||||||
|
snprintf(z, sizeof(z) - 1, "%s_mipmap", s);
|
||||||
|
wx_config_get_bool(cfg, z, &tex->mipmap, 0);
|
||||||
|
|
||||||
|
snprintf(z, sizeof(z) - 1, "%s_wrap_mode", s);
|
||||||
|
wx_config_get_string(cfg, z, tex->wrap_mode, sizeof(tex->wrap_mode), 0);
|
||||||
|
|
||||||
|
j = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parameters */
|
||||||
|
get_parameters(glslp);
|
||||||
|
|
||||||
|
wx_config_get_string(cfg, "parameters", t, sizeof(t), 0);
|
||||||
|
|
||||||
|
len = strlen(t);
|
||||||
|
j = 0;
|
||||||
|
sublen = 0;
|
||||||
|
for (i = 0; i < len; ++i) {
|
||||||
|
if (t[i] == ';' || i == len - 1) {
|
||||||
|
sublen = (i - j) + ((i == len - 1) ? 1 : 0) + 1;
|
||||||
|
safe_strncpy(s, t + j, sublen);
|
||||||
|
s[511 < sublen ? 511 : sublen] = 0;
|
||||||
|
|
||||||
|
struct parameter *p = get_parameter(glslp, s);
|
||||||
|
|
||||||
|
if (p)
|
||||||
|
wx_config_get_float(cfg, s, &p->default_value, 0);
|
||||||
|
|
||||||
|
j = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
wx_config_free(cfg);
|
||||||
|
|
||||||
|
return glslp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void glslp_free(glslp_t *p) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < p->num_shaders; ++i)
|
||||||
|
if (p->shaders[i].shader_program)
|
||||||
|
free(p->shaders[i].shader_program);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void glslp_read_shader_config(glslp_t *shader) {
|
||||||
|
char s[512];
|
||||||
|
int i;
|
||||||
|
char *name = shader->name;
|
||||||
|
sprintf(s, "GL3 Shaders - %s", name);
|
||||||
|
for (i = 0; i < shader->num_parameters; ++i) {
|
||||||
|
struct parameter *param = &shader->parameters[i];
|
||||||
|
param->value = config_get_double(s, param->id, param->default_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void glslp_write_shader_config(glslp_t *shader) {
|
||||||
|
char s[512];
|
||||||
|
int i;
|
||||||
|
char *name = shader->name;
|
||||||
|
|
||||||
|
startblit();
|
||||||
|
sprintf(s, "GL3 Shaders - %s", name);
|
||||||
|
for (i = 0; i < shader->num_parameters; ++i) {
|
||||||
|
struct parameter *param = &shader->parameters[i];
|
||||||
|
config_set_double(s, param->id, param->value);
|
||||||
|
}
|
||||||
|
endblit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -90,6 +90,8 @@ extern "C" {
|
|||||||
#include <86box/timer.h>
|
#include <86box/timer.h>
|
||||||
#include <86box/nvr.h>
|
#include <86box/nvr.h>
|
||||||
extern int qt_nvr_save(void);
|
extern int qt_nvr_save(void);
|
||||||
|
|
||||||
|
bool cpu_thread_running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qt_set_sequence_auto_mnemonic(bool b);
|
void qt_set_sequence_auto_mnemonic(bool b);
|
||||||
@@ -389,6 +391,7 @@ main_thread_fn()
|
|||||||
// title_update = 1;
|
// title_update = 1;
|
||||||
uint64_t old_time = elapsed_timer.elapsed();
|
uint64_t old_time = elapsed_timer.elapsed();
|
||||||
int drawits = frames = 0;
|
int drawits = frames = 0;
|
||||||
|
is_cpu_thread = 1;
|
||||||
while (!is_quit && cpu_thread_run) {
|
while (!is_quit && cpu_thread_run) {
|
||||||
/* See if it is time to run a frame of code. */
|
/* See if it is time to run a frame of code. */
|
||||||
const uint64_t new_time = elapsed_timer.elapsed();
|
const uint64_t new_time = elapsed_timer.elapsed();
|
||||||
@@ -443,6 +446,7 @@ main_thread_fn()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_thread_running = false;
|
||||||
is_quit = 1;
|
is_quit = 1;
|
||||||
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
|
for (uint8_t i = 1; i < GFXCARD_MAX; i ++) {
|
||||||
if (gfxcard[i]) {
|
if (gfxcard[i]) {
|
||||||
@@ -735,6 +739,7 @@ main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
plat_pause(0);
|
plat_pause(0);
|
||||||
|
|
||||||
|
cpu_thread_running = true;
|
||||||
main_thread = new std::thread(main_thread_fn);
|
main_thread = new std::thread(main_thread_fn);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ extern int qt_nvr_save(void);
|
|||||||
#ifdef MTR_ENABLED
|
#ifdef MTR_ENABLED
|
||||||
# include <minitrace/minitrace.h>
|
# include <minitrace/minitrace.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern bool cpu_thread_running;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
@@ -452,6 +454,9 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
endblit();
|
endblit();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
case 6:
|
||||||
|
newVidApi = RendererStack::Renderer::OpenGL3PCem;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
ui->stackedWidget->switchRenderer(newVidApi);
|
ui->stackedWidget->switchRenderer(newVidApi);
|
||||||
if (!show_second_monitors)
|
if (!show_second_monitors)
|
||||||
@@ -779,6 +784,14 @@ MainWindow::closeEvent(QCloseEvent *event)
|
|||||||
ui->stackedWidget->mouse_exit_func();
|
ui->stackedWidget->mouse_exit_func();
|
||||||
|
|
||||||
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
|
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
|
||||||
|
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||||
|
if (renderers[i] && renderers[i]->isHidden()) {
|
||||||
|
renderers[i]->show();
|
||||||
|
QApplication::processEvents();
|
||||||
|
renderers[i]->switchRenderer(RendererStack::Renderer::Software);
|
||||||
|
QApplication::processEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qt_nvr_save();
|
qt_nvr_save();
|
||||||
config_save();
|
config_save();
|
||||||
@@ -1253,7 +1266,7 @@ MainWindow::eventFilter(QObject *receiver, QEvent *event)
|
|||||||
static auto curdopause = dopause;
|
static auto curdopause = dopause;
|
||||||
if (event->type() == QEvent::WindowBlocked) {
|
if (event->type() == QEvent::WindowBlocked) {
|
||||||
curdopause = dopause;
|
curdopause = dopause;
|
||||||
plat_pause(1);
|
plat_pause(isShowMessage ? 2 : 1);
|
||||||
emit setMouseCapture(false);
|
emit setMouseCapture(false);
|
||||||
} else if (event->type() == QEvent::WindowUnblocked) {
|
} else if (event->type() == QEvent::WindowUnblocked) {
|
||||||
plat_pause(curdopause);
|
plat_pause(curdopause);
|
||||||
@@ -1277,7 +1290,11 @@ void
|
|||||||
MainWindow::showMessage(int flags, const QString &header, const QString &message)
|
MainWindow::showMessage(int flags, const QString &header, const QString &message)
|
||||||
{
|
{
|
||||||
if (QThread::currentThread() == this->thread()) {
|
if (QThread::currentThread() == this->thread()) {
|
||||||
showMessage_(flags, header, message);
|
if (!cpu_thread_running) {
|
||||||
|
showMessageForNonQtThread(flags, header, message, nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
showMessage_(flags, header, message);
|
||||||
} else {
|
} else {
|
||||||
std::atomic_bool done = false;
|
std::atomic_bool done = false;
|
||||||
emit showMessageForNonQtThread(flags, header, message, &done);
|
emit showMessageForNonQtThread(flags, header, message, &done);
|
||||||
@@ -1293,6 +1310,7 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag
|
|||||||
if (done) {
|
if (done) {
|
||||||
*done = false;
|
*done = false;
|
||||||
}
|
}
|
||||||
|
isShowMessage = true;
|
||||||
QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this);
|
QMessageBox box(QMessageBox::Warning, header, message, QMessageBox::NoButton, this);
|
||||||
if (flags & (MBX_FATAL)) {
|
if (flags & (MBX_FATAL)) {
|
||||||
box.setIcon(QMessageBox::Critical);
|
box.setIcon(QMessageBox::Critical);
|
||||||
@@ -1304,6 +1322,7 @@ MainWindow::showMessage_(int flags, const QString &header, const QString &messag
|
|||||||
if (done) {
|
if (done) {
|
||||||
*done = true;
|
*done = true;
|
||||||
}
|
}
|
||||||
|
isShowMessage = false;
|
||||||
if (cpu_thread_run == 0)
|
if (cpu_thread_run == 0)
|
||||||
QApplication::exit(-1);
|
QApplication::exit(-1);
|
||||||
}
|
}
|
||||||
@@ -1980,15 +1999,40 @@ MainWindow::changeEvent(QEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MainWindow::reloadAllRenderers()
|
||||||
|
{
|
||||||
|
reload_renderers = true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MainWindow::on_actionRenderer_options_triggered()
|
MainWindow::on_actionRenderer_options_triggered()
|
||||||
{
|
{
|
||||||
if (const auto dlg = ui->stackedWidget->getOptions(this)) {
|
if (const auto dlg = ui->stackedWidget->getOptions(this)) {
|
||||||
if (dlg->exec() == QDialog::Accepted) {
|
if (dlg->exec() == QDialog::Accepted) {
|
||||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
if (ui->stackedWidget->reloadRendererOption()) {
|
||||||
|
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||||
|
if (show_second_monitors) {
|
||||||
|
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||||
|
if (renderers[i] && renderers[i]->reloadRendererOption() && renderers[i]->hasOptions()) {
|
||||||
|
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else for (int i = 1; i < MONITORS_NUM; i++) {
|
||||||
if (renderers[i] && renderers[i]->hasOptions())
|
if (renderers[i] && renderers[i]->hasOptions())
|
||||||
renderers[i]->reloadOptions();
|
renderers[i]->reloadOptions();
|
||||||
}
|
}
|
||||||
|
} else if (reload_renderers && ui->stackedWidget->reloadRendererOption()) {
|
||||||
|
reload_renderers = false;
|
||||||
|
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||||
|
if (show_second_monitors) {
|
||||||
|
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||||
|
if (renderers[i] && renderers[i]->reloadRendererOption() && renderers[i]->hasOptions()) {
|
||||||
|
ui->stackedWidget->switchRenderer(static_cast<RendererStack::Renderer>(vid_api));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public:
|
|||||||
QSize getRenderWidgetSize();
|
QSize getRenderWidgetSize();
|
||||||
void setSendKeyboardInput(bool enabled);
|
void setSendKeyboardInput(bool enabled);
|
||||||
void checkFullscreenHotkey();
|
void checkFullscreenHotkey();
|
||||||
|
void reloadAllRenderers();
|
||||||
|
|
||||||
std::array<std::unique_ptr<RendererStack>, 8> renderers;
|
std::array<std::unique_ptr<RendererStack>, 8> renderers;
|
||||||
signals:
|
signals:
|
||||||
@@ -173,11 +174,17 @@ private:
|
|||||||
bool fs_on_signal = false;
|
bool fs_on_signal = false;
|
||||||
bool fs_off_signal = false;
|
bool fs_off_signal = false;
|
||||||
|
|
||||||
|
/* Reload the renderers after closing renderer options dialog. */
|
||||||
|
bool reload_renderers = false;
|
||||||
|
|
||||||
friend class SpecifyDimensions;
|
friend class SpecifyDimensions;
|
||||||
friend class ProgSettings;
|
friend class ProgSettings;
|
||||||
friend class RendererCommon;
|
friend class RendererCommon;
|
||||||
friend class RendererStack; // For UI variable access by non-primary renderer windows.
|
friend class RendererStack; // For UI variable access by non-primary renderer windows.
|
||||||
friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes.
|
friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes.
|
||||||
|
|
||||||
|
|
||||||
|
bool isShowMessage = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QT_MAINWINDOW_HPP
|
#endif // QT_MAINWINDOW_HPP
|
||||||
|
|||||||
@@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
||||||
* running old operating systems and software designed for IBM
|
|
||||||
* PC systems and compatibles from 1981 through fairly recent
|
|
||||||
* system designs based on the PCI bus.
|
|
||||||
*
|
|
||||||
* This file is part of the 86Box distribution.
|
|
||||||
*
|
|
||||||
* OpenGL renderer options for Qt
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Authors: Teemu Korhonen
|
|
||||||
*
|
|
||||||
* Copyright 2022 Teemu Korhonen
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QStringBuilder>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "qt_opengloptions.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <86box/86box.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Default vertex shader. */
|
|
||||||
static const GLchar *vertex_shader = "\
|
|
||||||
in vec2 VertexCoord;\n\
|
|
||||||
in vec2 TexCoord;\n\
|
|
||||||
out vec2 tex;\n\
|
|
||||||
void main(){\n\
|
|
||||||
gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\
|
|
||||||
tex = TexCoord;\n\
|
|
||||||
}\n";
|
|
||||||
|
|
||||||
/* Default fragment shader. */
|
|
||||||
static const GLchar *fragment_shader = "\
|
|
||||||
in vec2 tex;\n\
|
|
||||||
uniform sampler2D texsampler;\n\
|
|
||||||
out vec4 color;\n\
|
|
||||||
void main() {\n\
|
|
||||||
color = texture(texsampler, tex);\n\
|
|
||||||
}\n";
|
|
||||||
|
|
||||||
OpenGLOptions::OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion)
|
|
||||||
: QObject(parent)
|
|
||||||
, m_glslVersion(glslVersion)
|
|
||||||
{
|
|
||||||
m_filter = video_filter_method == 0
|
|
||||||
? FilterType::Nearest
|
|
||||||
: FilterType::Linear;
|
|
||||||
|
|
||||||
if (!loadConfig)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Initialize with config. */
|
|
||||||
m_vsync = video_vsync != 0;
|
|
||||||
m_framerate = video_framerate;
|
|
||||||
|
|
||||||
m_renderBehavior = video_framerate == -1
|
|
||||||
? RenderBehaviorType::SyncWithVideo
|
|
||||||
: RenderBehaviorType::TargetFramerate;
|
|
||||||
|
|
||||||
QString shaderPath(video_shader);
|
|
||||||
|
|
||||||
if (shaderPath.isEmpty()) {
|
|
||||||
addDefaultShader();
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
addShader(shaderPath);
|
|
||||||
} catch (const std::runtime_error &) {
|
|
||||||
/* Fallback to default shader */
|
|
||||||
addDefaultShader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptions::save() const
|
|
||||||
{
|
|
||||||
video_vsync = m_vsync ? 1 : 0;
|
|
||||||
video_framerate = m_renderBehavior == RenderBehaviorType::SyncWithVideo ? -1 : m_framerate;
|
|
||||||
video_filter_method = m_filter == FilterType::Nearest ? 0 : 1;
|
|
||||||
|
|
||||||
/* TODO: multiple shaders */
|
|
||||||
auto path = m_shaders.first().path().toLocal8Bit();
|
|
||||||
|
|
||||||
if (!path.isEmpty())
|
|
||||||
qstrncpy(video_shader, path.constData(), sizeof(video_shader));
|
|
||||||
else
|
|
||||||
video_shader[0] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenGLOptions::FilterType
|
|
||||||
OpenGLOptions::filter() const
|
|
||||||
{
|
|
||||||
/* Filter method is controlled externally */
|
|
||||||
return video_filter_method == 0
|
|
||||||
? FilterType::Nearest
|
|
||||||
: FilterType::Linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptions::setRenderBehavior(RenderBehaviorType value)
|
|
||||||
{
|
|
||||||
m_renderBehavior = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptions::setFrameRate(int value)
|
|
||||||
{
|
|
||||||
m_framerate = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptions::setVSync(bool value)
|
|
||||||
{
|
|
||||||
m_vsync = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptions::setFilter(FilterType value)
|
|
||||||
{
|
|
||||||
m_filter = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptions::addShader(const QString &path)
|
|
||||||
{
|
|
||||||
QFile shader_file(path);
|
|
||||||
|
|
||||||
if (!shader_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
QString(tr("Error opening \"%1\": %2"))
|
|
||||||
.arg(path)
|
|
||||||
.arg(shader_file.errorString())
|
|
||||||
.toStdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto shader_text = QString(shader_file.readAll());
|
|
||||||
|
|
||||||
shader_file.close();
|
|
||||||
|
|
||||||
/* Remove parameter lines */
|
|
||||||
shader_text.remove(QRegularExpression("^\\s*#pragma parameter.*?\\n", QRegularExpression::MultilineOption));
|
|
||||||
|
|
||||||
QRegularExpression version("^\\s*(#version\\s+\\w+)", QRegularExpression::MultilineOption);
|
|
||||||
|
|
||||||
auto match = version.match(shader_text);
|
|
||||||
|
|
||||||
QString version_line(m_glslVersion);
|
|
||||||
|
|
||||||
if (match.hasMatch()) {
|
|
||||||
/* Extract existing version and remove it. */
|
|
||||||
version_line = match.captured(1);
|
|
||||||
shader_text.remove(version);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto shader = new QOpenGLShaderProgram(this);
|
|
||||||
|
|
||||||
auto throw_shader_error = [path, shader](const QString &what) {
|
|
||||||
throw std::runtime_error(
|
|
||||||
QString(what % ":\n\n %2")
|
|
||||||
.arg(path)
|
|
||||||
.arg(shader->log())
|
|
||||||
.toStdString());
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char *extension = "\n#extension GL_ARB_shading_language_420pack : enable\n";
|
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version_line % extension % "\n#define VERTEX\n#line 1\n" % shader_text))
|
|
||||||
throw_shader_error(tr("Error compiling vertex shader in file \"%1\""));
|
|
||||||
|
|
||||||
if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % extension % "\n#define FRAGMENT\n#line 1\n" % shader_text))
|
|
||||||
throw_shader_error(tr("Error compiling fragment shader in file \"%1\""));
|
|
||||||
|
|
||||||
if (!shader->link())
|
|
||||||
throw_shader_error(tr("Error linking shader program in file \"%1\""));
|
|
||||||
|
|
||||||
m_shaders << OpenGLShaderPass(shader, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptions::addDefaultShader()
|
|
||||||
{
|
|
||||||
auto shader = new QOpenGLShaderProgram(this);
|
|
||||||
shader->addShaderFromSourceCode(QOpenGLShader::Vertex, m_glslVersion % "\n" % vertex_shader);
|
|
||||||
shader->addShaderFromSourceCode(QOpenGLShader::Fragment, m_glslVersion % "\n" % fragment_shader);
|
|
||||||
shader->link();
|
|
||||||
m_shaders << OpenGLShaderPass(shader, QString());
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
||||||
* running old operating systems and software designed for IBM
|
|
||||||
* PC systems and compatibles from 1981 through fairly recent
|
|
||||||
* system designs based on the PCI bus.
|
|
||||||
*
|
|
||||||
* This file is part of the 86Box distribution.
|
|
||||||
*
|
|
||||||
* Header for OpenGL renderer options
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Authors: Teemu Korhonen
|
|
||||||
*
|
|
||||||
* Copyright 2022 Teemu Korhonen
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef QT_OPENGLOPTIONS_HPP
|
|
||||||
#define QT_OPENGLOPTIONS_HPP
|
|
||||||
|
|
||||||
#include <QList>
|
|
||||||
#include <QObject>
|
|
||||||
#include <QOpenGLContext>
|
|
||||||
#include <QOpenGLShaderProgram>
|
|
||||||
|
|
||||||
class OpenGLShaderPass {
|
|
||||||
public:
|
|
||||||
OpenGLShaderPass(QOpenGLShaderProgram *shader, const QString &path)
|
|
||||||
: m_shader(shader)
|
|
||||||
, m_path(path)
|
|
||||||
, m_vertex_coord(shader->attributeLocation("VertexCoord"))
|
|
||||||
, m_tex_coord(shader->attributeLocation("TexCoord"))
|
|
||||||
, m_color(shader->attributeLocation("Color"))
|
|
||||||
, m_mvp_matrix(shader->uniformLocation("MVPMatrix"))
|
|
||||||
, m_input_size(shader->uniformLocation("InputSize"))
|
|
||||||
, m_output_size(shader->uniformLocation("OutputSize"))
|
|
||||||
, m_texture_size(shader->uniformLocation("TextureSize"))
|
|
||||||
, m_frame_count(shader->uniformLocation("FrameCount"))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bind() const { return m_shader->bind(); }
|
|
||||||
const QString &path() const { return m_path; }
|
|
||||||
const GLint &vertex_coord() const { return m_vertex_coord; }
|
|
||||||
const GLint &tex_coord() const { return m_tex_coord; }
|
|
||||||
const GLint &color() const { return m_color; }
|
|
||||||
const GLint &mvp_matrix() const { return m_mvp_matrix; }
|
|
||||||
const GLint &input_size() const { return m_input_size; }
|
|
||||||
const GLint &output_size() const { return m_output_size; }
|
|
||||||
const GLint &texture_size() const { return m_texture_size; }
|
|
||||||
const GLint &frame_count() const { return m_frame_count; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QOpenGLShaderProgram *m_shader;
|
|
||||||
QString m_path;
|
|
||||||
GLint m_vertex_coord;
|
|
||||||
GLint m_tex_coord;
|
|
||||||
GLint m_color;
|
|
||||||
GLint m_mvp_matrix;
|
|
||||||
GLint m_input_size;
|
|
||||||
GLint m_output_size;
|
|
||||||
GLint m_texture_size;
|
|
||||||
GLint m_frame_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OpenGLOptions : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
enum RenderBehaviorType { SyncWithVideo,
|
|
||||||
TargetFramerate };
|
|
||||||
|
|
||||||
enum FilterType { Nearest,
|
|
||||||
Linear };
|
|
||||||
|
|
||||||
OpenGLOptions(QObject *parent, bool loadConfig, const QString &glslVersion);
|
|
||||||
|
|
||||||
RenderBehaviorType renderBehavior() const { return m_renderBehavior; }
|
|
||||||
int framerate() const { return m_framerate; }
|
|
||||||
bool vSync() const { return m_vsync; }
|
|
||||||
FilterType filter() const;
|
|
||||||
|
|
||||||
const QList<OpenGLShaderPass> &shaders() const { return m_shaders; }
|
|
||||||
|
|
||||||
void setRenderBehavior(RenderBehaviorType value);
|
|
||||||
void setFrameRate(int value);
|
|
||||||
void setVSync(bool value);
|
|
||||||
void setFilter(FilterType value);
|
|
||||||
void addShader(const QString &path);
|
|
||||||
void addDefaultShader();
|
|
||||||
void save() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
RenderBehaviorType m_renderBehavior = SyncWithVideo;
|
|
||||||
int m_framerate = -1;
|
|
||||||
bool m_vsync = false;
|
|
||||||
FilterType m_filter = Nearest;
|
|
||||||
QList<OpenGLShaderPass> m_shaders;
|
|
||||||
QString m_glslVersion;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
||||||
* running old operating systems and software designed for IBM
|
|
||||||
* PC systems and compatibles from 1981 through fairly recent
|
|
||||||
* system designs based on the PCI bus.
|
|
||||||
*
|
|
||||||
* This file is part of the 86Box distribution.
|
|
||||||
*
|
|
||||||
* OpenGL renderer options dialog for Qt
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Authors: Teemu Korhonen
|
|
||||||
*
|
|
||||||
* Copyright 2022 Teemu Korhonen
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QStringBuilder>
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include "qt_opengloptionsdialog.hpp"
|
|
||||||
#include "qt_util.hpp"
|
|
||||||
#include "ui_qt_opengloptionsdialog.h"
|
|
||||||
|
|
||||||
OpenGLOptionsDialog::OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function<OpenGLOptions *()> optionsFactory)
|
|
||||||
: QDialog(parent)
|
|
||||||
, ui(new Ui::OpenGLOptionsDialog)
|
|
||||||
, createOptions(optionsFactory)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
|
|
||||||
if (options.renderBehavior() == OpenGLOptions::SyncWithVideo)
|
|
||||||
ui->syncWithVideo->setChecked(true);
|
|
||||||
else {
|
|
||||||
ui->syncToFramerate->setChecked(true);
|
|
||||||
ui->targetFps->setValue(options.framerate());
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->vsync->setChecked(options.vSync());
|
|
||||||
|
|
||||||
if (!options.shaders().isEmpty()) {
|
|
||||||
auto path = options.shaders().first().path();
|
|
||||||
if (!path.isEmpty())
|
|
||||||
ui->shader->setPlainText(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenGLOptionsDialog::~OpenGLOptionsDialog()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptionsDialog::accept()
|
|
||||||
{
|
|
||||||
auto options = createOptions();
|
|
||||||
|
|
||||||
options->setRenderBehavior(
|
|
||||||
ui->syncWithVideo->isChecked()
|
|
||||||
? OpenGLOptions::SyncWithVideo
|
|
||||||
: OpenGLOptions::TargetFramerate);
|
|
||||||
|
|
||||||
options->setFrameRate(ui->targetFps->value());
|
|
||||||
|
|
||||||
options->setVSync(ui->vsync->isChecked());
|
|
||||||
|
|
||||||
auto shader = ui->shader->toPlainText();
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (!shader.isEmpty())
|
|
||||||
options->addShader(shader);
|
|
||||||
else
|
|
||||||
options->addDefaultShader();
|
|
||||||
|
|
||||||
} catch (const std::runtime_error &e) {
|
|
||||||
delete options;
|
|
||||||
|
|
||||||
QMessageBox msgBox(this);
|
|
||||||
msgBox.setWindowTitle(tr("Shader error"));
|
|
||||||
msgBox.setText(tr("Could not load shaders."));
|
|
||||||
msgBox.setInformativeText(tr("More information in details."));
|
|
||||||
msgBox.setDetailedText(e.what());
|
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Close);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::Close);
|
|
||||||
msgBox.setStyleSheet("QTextEdit { min-width: 45em; }");
|
|
||||||
msgBox.exec();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
options->save();
|
|
||||||
|
|
||||||
emit optionsChanged(options);
|
|
||||||
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
OpenGLOptionsDialog::on_addShader_clicked()
|
|
||||||
{
|
|
||||||
auto shader = QFileDialog::getOpenFileName(
|
|
||||||
this,
|
|
||||||
QString(),
|
|
||||||
QString(),
|
|
||||||
tr("OpenGL Shaders") % util::DlgFilter({ "glsl" }, true));
|
|
||||||
|
|
||||||
if (shader.isNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ui->shader->setPlainText(shader);
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
|
||||||
* running old operating systems and software designed for IBM
|
|
||||||
* PC systems and compatibles from 1981 through fairly recent
|
|
||||||
* system designs based on the PCI bus.
|
|
||||||
*
|
|
||||||
* This file is part of the 86Box distribution.
|
|
||||||
*
|
|
||||||
* Header for OpenGL renderer options dialog
|
|
||||||
*
|
|
||||||
* Authors: Teemu Korhonen
|
|
||||||
*
|
|
||||||
* Copyright 2022 Teemu Korhonen
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef QT_OPENGLOPTIONSDIALOG_H
|
|
||||||
#define QT_OPENGLOPTIONSDIALOG_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include "qt_opengloptions.hpp"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class OpenGLOptionsDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
class OpenGLOptionsDialog : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options, std::function<OpenGLOptions *()> optionsFactory);
|
|
||||||
~OpenGLOptionsDialog();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void optionsChanged(OpenGLOptions *options);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void accept() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::OpenGLOptionsDialog *ui;
|
|
||||||
|
|
||||||
std::function<OpenGLOptions *()> createOptions;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_addShader_clicked();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QT_OPENGLOPTIONSDIALOG_H
|
|
||||||
@@ -1,280 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>OpenGLOptionsDialog</class>
|
|
||||||
<widget class="QDialog" name="OpenGLOptionsDialog">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>400</width>
|
|
||||||
<height>320</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>OpenGL 3.0 renderer options</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Render behavior</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2" columnstretch="3,1">
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QRadioButton" name="syncToFramerate">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use target framerate:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QSpinBox" name="targetFps">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="suffix">
|
|
||||||
<string> fps</string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>15</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>240</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>60</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QCheckBox" name="vsync">
|
|
||||||
<property name="text">
|
|
||||||
<string>VSync</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QRadioButton" name="syncWithVideo">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Render each frame immediately, in sync with the emulated display.</p><p><span style=" font-style:italic;">This is the recommended option if the shaders in use don't utilize frametime for animated effects.</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Synchronize with video</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QSlider" name="fpsSlider">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="minimum">
|
|
||||||
<number>15</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>240</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>60</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="invertedAppearance">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="tickPosition">
|
|
||||||
<enum>QSlider::NoTicks</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
|
||||||
<property name="title">
|
|
||||||
<string>Shaders</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout" columnstretch="3,1">
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QPushButton" name="removeShader">
|
|
||||||
<property name="text">
|
|
||||||
<string>Remove</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" rowspan="3">
|
|
||||||
<widget class="QTextEdit" name="shader">
|
|
||||||
<property name="readOnly">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>No shader selected</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1" alignment="Qt::AlignTop">
|
|
||||||
<widget class="QPushButton" name="addShader">
|
|
||||||
<property name="text">
|
|
||||||
<string>Browse...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<tabstops>
|
|
||||||
<tabstop>syncWithVideo</tabstop>
|
|
||||||
<tabstop>syncToFramerate</tabstop>
|
|
||||||
<tabstop>fpsSlider</tabstop>
|
|
||||||
<tabstop>targetFps</tabstop>
|
|
||||||
<tabstop>vsync</tabstop>
|
|
||||||
<tabstop>shader</tabstop>
|
|
||||||
<tabstop>addShader</tabstop>
|
|
||||||
<tabstop>removeShader</tabstop>
|
|
||||||
</tabstops>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>OpenGLOptionsDialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>257</x>
|
|
||||||
<y>310</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>157</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>rejected()</signal>
|
|
||||||
<receiver>OpenGLOptionsDialog</receiver>
|
|
||||||
<slot>reject()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>325</x>
|
|
||||||
<y>310</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>syncToFramerate</sender>
|
|
||||||
<signal>toggled(bool)</signal>
|
|
||||||
<receiver>targetFps</receiver>
|
|
||||||
<slot>setEnabled(bool)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>140</x>
|
|
||||||
<y>71</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>380</x>
|
|
||||||
<y>98</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>syncToFramerate</sender>
|
|
||||||
<signal>toggled(bool)</signal>
|
|
||||||
<receiver>fpsSlider</receiver>
|
|
||||||
<slot>setEnabled(bool)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>158</x>
|
|
||||||
<y>66</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>168</x>
|
|
||||||
<y>87</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>fpsSlider</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>targetFps</receiver>
|
|
||||||
<slot>setValue(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>252</x>
|
|
||||||
<y>90</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>308</x>
|
|
||||||
<y>89</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>targetFps</sender>
|
|
||||||
<signal>valueChanged(int)</signal>
|
|
||||||
<receiver>fpsSlider</receiver>
|
|
||||||
<slot>setValue(int)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>364</x>
|
|
||||||
<y>93</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>134</x>
|
|
||||||
<y>93</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>removeShader</sender>
|
|
||||||
<signal>clicked()</signal>
|
|
||||||
<receiver>shader</receiver>
|
|
||||||
<slot>clear()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>333</x>
|
|
||||||
<y>201</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>235</x>
|
|
||||||
<y>208</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -11,12 +11,14 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Authors: Teemu Korhonen
|
* Authors: Teemu Korhonen
|
||||||
|
* Cacodemon345
|
||||||
*
|
*
|
||||||
* Copyright 2022 Teemu Korhonen
|
* Copyright 2022 Teemu Korhonen
|
||||||
|
* Copyright 2025 Cacodemon345
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef QT_OPENGLRENDERER_HPP
|
#ifndef QT_OpenGLRenderer_HPP
|
||||||
#define QT_OPENGLRENDERER_HPP
|
#define QT_OpenGLRenderer_HPP
|
||||||
|
|
||||||
#if defined Q_OS_MACOS || __arm__
|
#if defined Q_OS_MACOS || __arm__
|
||||||
# define NO_BUFFER_STORAGE
|
# define NO_BUFFER_STORAGE
|
||||||
@@ -37,12 +39,24 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "qt_opengloptions.hpp"
|
|
||||||
#include "qt_renderercommon.hpp"
|
#include "qt_renderercommon.hpp"
|
||||||
|
|
||||||
typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <86box/qt-glslp-parser.h>
|
||||||
|
}
|
||||||
|
|
||||||
class OpenGLRenderer : public QWindow, protected QOpenGLExtraFunctions, public RendererCommon {
|
struct render_data {
|
||||||
|
int pass;
|
||||||
|
struct glsl_shader *shader;
|
||||||
|
struct shader_pass *shader_pass;
|
||||||
|
GLfloat *output_size;
|
||||||
|
struct shader_pass *orig_pass;
|
||||||
|
GLint texture;
|
||||||
|
int frame_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenGLRenderer : public QWindow, public RendererCommon {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -56,7 +70,7 @@ public:
|
|||||||
void finalize() override final;
|
void finalize() override final;
|
||||||
bool hasOptions() const override { return true; }
|
bool hasOptions() const override { return true; }
|
||||||
QDialog *getOptions(QWidget *parent) override;
|
QDialog *getOptions(QWidget *parent) override;
|
||||||
void reloadOptions() override;
|
bool reloadRendererOption() { return true; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void initialized();
|
void initialized();
|
||||||
@@ -71,47 +85,64 @@ protected:
|
|||||||
bool event(QEvent *event) override;
|
bool event(QEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int INIT_WIDTH = 640;
|
|
||||||
static constexpr int INIT_HEIGHT = 400;
|
std::array<std::unique_ptr<uint8_t>, 2> imagebufs;
|
||||||
static constexpr int ROW_LENGTH = 2048;
|
|
||||||
static constexpr int BUFFERPIXELS = 4194304;
|
|
||||||
static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */
|
|
||||||
static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */
|
|
||||||
|
|
||||||
QTimer *renderTimer;
|
QTimer *renderTimer;
|
||||||
OpenGLOptions *options;
|
|
||||||
|
|
||||||
QString glslVersion;
|
QString glslVersion = "";
|
||||||
|
|
||||||
bool isInitialized = false;
|
bool isInitialized = false;
|
||||||
bool isFinalized = false;
|
bool isFinalized = false;
|
||||||
|
|
||||||
GLuint unpackBufferID = 0;
|
int max_texture_size = 65536;
|
||||||
GLuint vertexArrayID = 0;
|
int frameCounter = 0;
|
||||||
GLuint vertexBufferID = 0;
|
|
||||||
GLuint textureID = 0;
|
|
||||||
int frameCounter = 0;
|
|
||||||
|
|
||||||
OpenGLOptions::FilterType currentFilter;
|
QOpenGLExtraFunctions glw;
|
||||||
|
struct shader_texture scene_texture;
|
||||||
|
glsl_t *active_shader;
|
||||||
|
|
||||||
void *unpackBuffer = nullptr;
|
void *unpackBuffer = nullptr;
|
||||||
|
|
||||||
|
int glsl_version[2] = { 0, 0 };
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
void initializeExtensions();
|
void initializeExtensions();
|
||||||
void initializeBuffers();
|
void initializeBuffers();
|
||||||
void applyOptions();
|
void applyOptions();
|
||||||
void applyShader(const OpenGLShaderPass &shader);
|
|
||||||
bool notReady() const { return !isInitialized || isFinalized; }
|
void create_scene_shader();
|
||||||
|
void create_texture(struct shader_texture *tex);
|
||||||
|
void create_fbo(struct shader_fbo *fbo);
|
||||||
|
void recreate_fbo(struct shader_fbo *fbo, int width, int height);
|
||||||
|
void setup_fbo(struct shader *shader, struct shader_fbo *fbo);
|
||||||
|
|
||||||
/* GL_ARB_buffer_storage */
|
bool notReady() const { return !isInitialized || isFinalized; }
|
||||||
bool hasBufferStorage = false;
|
glsl_t* load_glslp(glsl_t *glsl, int num_shader, const char *f);
|
||||||
#ifndef NO_BUFFER_STORAGE
|
glsl_t* load_shaders(int num, char shaders[MAX_USER_SHADERS][512]);
|
||||||
PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr;
|
int compile_shader(GLenum shader_type, const char *prepend, const char *program, int *dst);
|
||||||
#endif
|
int create_default_shader_tex(struct shader_pass *pass);
|
||||||
|
int create_default_shader_color(struct shader_pass *pass);
|
||||||
|
int create_program(struct shader_program *program);
|
||||||
|
|
||||||
|
GLuint get_uniform(GLuint program, const char *name);
|
||||||
|
GLuint get_attrib(GLuint program, const char *name);
|
||||||
|
|
||||||
|
void find_uniforms(struct glsl_shader *glsl, int num_pass);
|
||||||
|
void delete_texture(struct shader_texture *tex);
|
||||||
|
void delete_fbo(struct shader_fbo *fbo);
|
||||||
|
void delete_program(struct shader_program *program);
|
||||||
|
void delete_vbo(struct shader_vbo *vbo);
|
||||||
|
void delete_pass(struct shader_pass *pass);
|
||||||
|
void delete_prev(struct shader_prev *prev);
|
||||||
|
void delete_shader(struct glsl_shader *glsl);
|
||||||
|
void delete_glsl(glsl_t *glsl);
|
||||||
|
void read_shader_config();
|
||||||
|
|
||||||
|
void render_pass(struct render_data *data);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void render();
|
void render();
|
||||||
void updateOptions(OpenGLOptions *newOptions);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class opengl_init_error : public std::runtime_error {
|
class opengl_init_error : public std::runtime_error {
|
||||||
|
|||||||
85
src/qt/qt_openglshaderconfig.cpp
Normal file
85
src/qt/qt_openglshaderconfig.cpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
#include "qt_openglshaderconfig.hpp"
|
||||||
|
#include "ui_qt_openglshaderconfig.h"
|
||||||
|
|
||||||
|
#include "qt_mainwindow.hpp"
|
||||||
|
|
||||||
|
extern MainWindow* main_window;
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/plat.h>
|
||||||
|
#include <86box/config.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLShaderConfig::OpenGLShaderConfig(QWidget *parent, glslp_t* shader)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::OpenGLShaderConfig)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
currentShader = shader;
|
||||||
|
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
|
||||||
|
|
||||||
|
glslp_read_shader_config(currentShader);
|
||||||
|
|
||||||
|
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||||
|
auto spinBox = new QDoubleSpinBox;
|
||||||
|
spinBox->setObjectName(currentShader->parameters[i].id);
|
||||||
|
spinBox->setRange(currentShader->parameters[i].min, currentShader->parameters[i].max);
|
||||||
|
spinBox->setValue(currentShader->parameters[i].value);
|
||||||
|
spinBox->setSingleStep(currentShader->parameters[i].step);
|
||||||
|
QFormLayout* layout = (QFormLayout*)ui->scrollAreaWidgetContents->layout();
|
||||||
|
layout->addRow(currentShader->parameters[i].description, spinBox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLShaderConfig::~OpenGLShaderConfig()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderConfig::on_buttonBox_clicked(QAbstractButton *button)
|
||||||
|
{
|
||||||
|
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole) {
|
||||||
|
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||||
|
QDoubleSpinBox* box = this->findChild<QDoubleSpinBox*>(QString(currentShader->parameters[i].id));
|
||||||
|
if (box) {
|
||||||
|
box->setValue(currentShader->parameters[i].default_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) {
|
||||||
|
startblit();
|
||||||
|
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||||
|
QDoubleSpinBox* box = this->findChild<QDoubleSpinBox*>(QString(currentShader->parameters[i].id));
|
||||||
|
if (box) {
|
||||||
|
float val = (float)box->value();
|
||||||
|
currentShader->parameters[i].value = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glslp_write_shader_config(currentShader);
|
||||||
|
config_save();
|
||||||
|
endblit();
|
||||||
|
main_window->reloadAllRenderers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderConfig::on_OpenGLShaderConfig_accepted()
|
||||||
|
{
|
||||||
|
startblit();
|
||||||
|
for (int i = 0; i < currentShader->num_parameters; i++) {
|
||||||
|
QDoubleSpinBox* box = (QDoubleSpinBox*)this->findChild<QDoubleSpinBox*>(QString(currentShader->parameters[i].id));
|
||||||
|
if (box) {
|
||||||
|
float val = (float)box->value();
|
||||||
|
currentShader->parameters[i].value = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glslp_write_shader_config(currentShader);
|
||||||
|
config_save();
|
||||||
|
endblit();
|
||||||
|
main_window->reloadAllRenderers();
|
||||||
|
}
|
||||||
|
|
||||||
40
src/qt/qt_openglshaderconfig.hpp
Normal file
40
src/qt/qt_openglshaderconfig.hpp
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef QT_OPENGLSHADERCONFIG_HPP
|
||||||
|
#define QT_OPENGLSHADERCONFIG_HPP
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QAbstractButton>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <86box/qt-glslp-parser.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class OpenGLShaderConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
class OpenGLShaderConfig : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit OpenGLShaderConfig(QWidget *parent = nullptr, glslp_t* shader = nullptr);
|
||||||
|
~OpenGLShaderConfig();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_clicked(QAbstractButton *button);
|
||||||
|
|
||||||
|
void on_OpenGLShaderConfig_accepted();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::OpenGLShaderConfig *ui;
|
||||||
|
glslp_t* currentShader;
|
||||||
|
|
||||||
|
std::map<std::string, double> defaultValues;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_OPENGLSHADERCONFIG_HPP
|
||||||
92
src/qt/qt_openglshaderconfig.ui
Normal file
92
src/qt/qt_openglshaderconfig.ui
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>OpenGLShaderConfig</class>
|
||||||
|
<widget class="QDialog" name="OpenGLShaderConfig">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Shader Configuration</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SizeConstraint::SetMinAndMaxSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>380</width>
|
||||||
|
<height>250</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout_2">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SizeConstraint::SetMaximumSize</enum>
|
||||||
|
</property>
|
||||||
|
<property name="fieldGrowthPolicy">
|
||||||
|
<enum>QFormLayout::FieldGrowthPolicy::AllNonFixedFieldsGrow</enum>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::Reset</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>OpenGLShaderConfig</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>OpenGLShaderConfig</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
||||||
260
src/qt/qt_openglshadermanagerdialog.cpp
Normal file
260
src/qt/qt_openglshadermanagerdialog.cpp
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
#include "qt_openglshadermanagerdialog.hpp"
|
||||||
|
#include "ui_qt_openglshadermanagerdialog.h"
|
||||||
|
|
||||||
|
#include "qt_mainwindow.hpp"
|
||||||
|
extern MainWindow* main_window;
|
||||||
|
|
||||||
|
#include "qt_openglshaderconfig.hpp"
|
||||||
|
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/plat.h>
|
||||||
|
#include <86box/video.h>
|
||||||
|
#include <86box/path.h>
|
||||||
|
#include <86box/ini.h>
|
||||||
|
#include <86box/config.h>
|
||||||
|
#include <86box/qt-glslp-parser.h>
|
||||||
|
|
||||||
|
extern char gl3_shader_file[MAX_USER_SHADERS][512];
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLShaderManagerDialog::OpenGLShaderManagerDialog(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, ui(new Ui::OpenGLShaderManagerDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
ui->checkBoxVSync->setChecked(!!video_vsync);
|
||||||
|
ui->radioButtonVideoSync->setChecked(video_framerate == -1);
|
||||||
|
ui->radioButtonTargetFramerate->setChecked(video_framerate != -1);
|
||||||
|
if (video_framerate != -1) {
|
||||||
|
ui->targetFrameRate->setValue(video_framerate);
|
||||||
|
} else {
|
||||||
|
ui->targetFrameRate->setDisabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_USER_SHADERS; i++) {
|
||||||
|
if (gl3_shader_file[i][0] != 0) {
|
||||||
|
char* filename = path_get_filename(gl3_shader_file[i]);
|
||||||
|
if (filename[0] != 0) {
|
||||||
|
glslp_t* shaderfile = glslp_parse(gl3_shader_file[i]);
|
||||||
|
if (shaderfile) {
|
||||||
|
QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget);
|
||||||
|
item->setText(filename);
|
||||||
|
item->setData(Qt::UserRole + 1, QString(gl3_shader_file[i]));
|
||||||
|
item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ui->shaderListWidget->count()) {
|
||||||
|
ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1);
|
||||||
|
auto current = ui->shaderListWidget->currentItem();
|
||||||
|
if (current) {
|
||||||
|
glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong();
|
||||||
|
if (shader->num_parameters > 0)
|
||||||
|
ui->buttonConfigure->setEnabled(true);
|
||||||
|
else
|
||||||
|
ui->buttonConfigure->setEnabled(false);
|
||||||
|
} else {
|
||||||
|
ui->buttonConfigure->setEnabled(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ui->buttonRemove->setDisabled(true);
|
||||||
|
ui->buttonMoveUp->setDisabled(true);
|
||||||
|
ui->buttonMoveDown->setDisabled(true);
|
||||||
|
ui->buttonConfigure->setDisabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGLShaderManagerDialog::~OpenGLShaderManagerDialog()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ui->shaderListWidget->count(); i++) {
|
||||||
|
if (ui->shaderListWidget->item(i) && ui->shaderListWidget->item(i)->data(Qt::UserRole + 2).toULongLong()) {
|
||||||
|
glslp_free((glslp_t*)ui->shaderListWidget->item(i)->data(Qt::UserRole + 2).toULongLong());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_buttonBox_clicked(QAbstractButton *button)
|
||||||
|
{
|
||||||
|
if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole) {
|
||||||
|
accept();
|
||||||
|
} else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) {
|
||||||
|
reject();
|
||||||
|
} else if (ui->buttonBox->buttonRole(button) == QDialogButtonBox::ApplyRole) {
|
||||||
|
on_OpenGLShaderManagerDialog_accepted();
|
||||||
|
main_window->reloadAllRenderers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_buttonMoveUp_clicked()
|
||||||
|
{
|
||||||
|
if (ui->shaderListWidget->currentRow() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int row = ui->shaderListWidget->currentRow();
|
||||||
|
auto item = ui->shaderListWidget->takeItem(row);
|
||||||
|
ui->shaderListWidget->insertItem(row - 1, item);
|
||||||
|
ui->shaderListWidget->setCurrentItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_shaderListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
|
||||||
|
{
|
||||||
|
if (current == nullptr) {
|
||||||
|
ui->buttonRemove->setDisabled(true);
|
||||||
|
ui->buttonMoveUp->setDisabled(true);
|
||||||
|
ui->buttonMoveDown->setDisabled(true);
|
||||||
|
ui->buttonConfigure->setDisabled(true);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ui->buttonRemove->setDisabled(false);
|
||||||
|
ui->buttonConfigure->setDisabled(true);
|
||||||
|
if (current) {
|
||||||
|
glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong();
|
||||||
|
if (shader->num_parameters > 0)
|
||||||
|
ui->buttonConfigure->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0);
|
||||||
|
ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_shaderListWidget_currentRowChanged(int currentRow)
|
||||||
|
{
|
||||||
|
auto current = ui->shaderListWidget->currentItem();
|
||||||
|
if (current == nullptr) {
|
||||||
|
ui->buttonRemove->setDisabled(true);
|
||||||
|
ui->buttonMoveUp->setDisabled(true);
|
||||||
|
ui->buttonMoveDown->setDisabled(true);
|
||||||
|
ui->buttonConfigure->setDisabled(true);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
ui->buttonRemove->setDisabled(false);
|
||||||
|
ui->buttonConfigure->setDisabled(true);
|
||||||
|
if (current) {
|
||||||
|
glslp_t* shader = (glslp_t*)current->data(Qt::UserRole + 2).toULongLong();
|
||||||
|
if (shader->num_parameters > 0)
|
||||||
|
ui->buttonConfigure->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->buttonMoveUp->setDisabled(ui->shaderListWidget->currentRow() == 0);
|
||||||
|
ui->buttonMoveDown->setDisabled(ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_buttonMoveDown_clicked()
|
||||||
|
{
|
||||||
|
if (ui->shaderListWidget->currentRow() == (ui->shaderListWidget->count() - 1))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int row = ui->shaderListWidget->currentRow();
|
||||||
|
auto item = ui->shaderListWidget->takeItem(row);
|
||||||
|
ui->shaderListWidget->insertItem(row + 1, item);
|
||||||
|
ui->shaderListWidget->setCurrentItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_buttonAdd_clicked()
|
||||||
|
{
|
||||||
|
auto res = QFileDialog::getOpenFileName(this, QString(), QString(), "GLSL Shaders (*.glslp *.glsl);;All files (*.*)");
|
||||||
|
if (!res.isEmpty()) {
|
||||||
|
auto glslp_file = res.toUtf8();
|
||||||
|
glslp_t* shaderfile = glslp_parse(glslp_file.data());
|
||||||
|
if (shaderfile) {
|
||||||
|
auto filename = path_get_filename(glslp_file.data());
|
||||||
|
QListWidgetItem* item = new QListWidgetItem(ui->shaderListWidget);
|
||||||
|
item->setText(filename);
|
||||||
|
item->setData(Qt::UserRole + 1, res);
|
||||||
|
item->setData(Qt::UserRole + 2, (uintptr_t)shaderfile);
|
||||||
|
if (ui->shaderListWidget->count()) {
|
||||||
|
ui->shaderListWidget->setCurrentRow(ui->shaderListWidget->count() - 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(this, tr("GLSL error"), tr("Could not load filename %1").arg(res));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_buttonRemove_clicked()
|
||||||
|
{
|
||||||
|
if (ui->shaderListWidget->currentItem()) {
|
||||||
|
auto item = ui->shaderListWidget->takeItem(ui->shaderListWidget->currentRow());
|
||||||
|
|
||||||
|
if (item->data(Qt::UserRole + 2).toULongLong()) {
|
||||||
|
glslp_free((glslp_t*)item->data(Qt::UserRole + 2).toULongLong());
|
||||||
|
}
|
||||||
|
delete item;
|
||||||
|
|
||||||
|
on_shaderListWidget_currentRowChanged(ui->shaderListWidget->currentRow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_OpenGLShaderManagerDialog_accepted()
|
||||||
|
{
|
||||||
|
memset(gl3_shader_file, 0, sizeof(gl3_shader_file));
|
||||||
|
for (int i = 0; i < ui->shaderListWidget->count(); i++) {
|
||||||
|
strncpy(gl3_shader_file[i], ui->shaderListWidget->item(i)->data(Qt::UserRole + 1).toString().toUtf8(), 512);
|
||||||
|
}
|
||||||
|
startblit();
|
||||||
|
video_vsync = ui->checkBoxVSync->isChecked();
|
||||||
|
if (ui->radioButtonTargetFramerate->isChecked()) {
|
||||||
|
video_framerate = ui->horizontalSliderFramerate->value();
|
||||||
|
} else {
|
||||||
|
video_framerate = -1;
|
||||||
|
}
|
||||||
|
config_save();
|
||||||
|
endblit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_buttonConfigure_clicked()
|
||||||
|
{
|
||||||
|
auto item = ui->shaderListWidget->currentItem();
|
||||||
|
if (item) {
|
||||||
|
glslp_t* shader = (glslp_t*)item->data(Qt::UserRole + 2).toULongLong();
|
||||||
|
|
||||||
|
auto configDialog = new OpenGLShaderConfig(this, shader);
|
||||||
|
configDialog->exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_radioButtonVideoSync_clicked()
|
||||||
|
{
|
||||||
|
ui->targetFrameRate->setDisabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_radioButtonTargetFramerate_clicked()
|
||||||
|
{
|
||||||
|
ui->targetFrameRate->setDisabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_horizontalSliderFramerate_sliderMoved(int position)
|
||||||
|
{
|
||||||
|
(void)position;
|
||||||
|
|
||||||
|
if (ui->horizontalSliderFramerate->value() != ui->targetFrameRate->value())
|
||||||
|
ui->targetFrameRate->setValue(ui->horizontalSliderFramerate->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OpenGLShaderManagerDialog::on_targetFrameRate_valueChanged(int arg1)
|
||||||
|
{
|
||||||
|
(void)arg1;
|
||||||
|
|
||||||
|
if (ui->horizontalSliderFramerate->value() != ui->targetFrameRate->value())
|
||||||
|
ui->horizontalSliderFramerate->setValue(ui->targetFrameRate->value());
|
||||||
|
}
|
||||||
|
|
||||||
50
src/qt/qt_openglshadermanagerdialog.hpp
Normal file
50
src/qt/qt_openglshadermanagerdialog.hpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef QT_OPENGLSHADERMANAGERDIALOG_H
|
||||||
|
#define QT_OPENGLSHADERMANAGERDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QAbstractButton>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class OpenGLShaderManagerDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class OpenGLShaderManagerDialog : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit OpenGLShaderManagerDialog(QWidget *parent = nullptr);
|
||||||
|
~OpenGLShaderManagerDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_clicked(QAbstractButton *button);
|
||||||
|
|
||||||
|
void on_buttonMoveUp_clicked();
|
||||||
|
|
||||||
|
void on_shaderListWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
|
||||||
|
|
||||||
|
void on_shaderListWidget_currentRowChanged(int currentRow);
|
||||||
|
|
||||||
|
void on_buttonMoveDown_clicked();
|
||||||
|
|
||||||
|
void on_buttonAdd_clicked();
|
||||||
|
|
||||||
|
void on_buttonRemove_clicked();
|
||||||
|
|
||||||
|
void on_OpenGLShaderManagerDialog_accepted();
|
||||||
|
|
||||||
|
void on_buttonConfigure_clicked();
|
||||||
|
|
||||||
|
void on_radioButtonVideoSync_clicked();
|
||||||
|
|
||||||
|
void on_radioButtonTargetFramerate_clicked();
|
||||||
|
|
||||||
|
void on_horizontalSliderFramerate_sliderMoved(int position);
|
||||||
|
|
||||||
|
void on_targetFrameRate_valueChanged(int arg1);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::OpenGLShaderManagerDialog *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_OPENGLSHADERMANAGERDIALOG_H
|
||||||
204
src/qt/qt_openglshadermanagerdialog.ui
Normal file
204
src/qt/qt_openglshadermanagerdialog.ui
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>OpenGLShaderManagerDialog</class>
|
||||||
|
<widget class="QDialog" name="OpenGLShaderManagerDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>465</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Shader Manager</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBoxShaders">
|
||||||
|
<property name="title">
|
||||||
|
<string>Shaders</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="shaderListWidget">
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::DragDropMode::InternalMove</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectionBehavior::SelectItems</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SizeConstraint::SetFixedSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonAdd">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonRemove">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonConfigure">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Configure</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonMoveUp">
|
||||||
|
<property name="text">
|
||||||
|
<string>Move up</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="buttonMoveDown">
|
||||||
|
<property name="text">
|
||||||
|
<string>Move down</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||||
|
</property>
|
||||||
|
<property name="centerButtons">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Render behavior</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QRadioButton" name="radioButtonTargetFramerate">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use target framerate:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QSlider" name="horizontalSliderFramerate">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>15</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>240</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>60</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="invertedAppearance">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="invertedControls">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QRadioButton" name="radioButtonVideoSync">
|
||||||
|
<property name="text">
|
||||||
|
<string>Synchronize with video</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="checkBoxVSync">
|
||||||
|
<property name="text">
|
||||||
|
<string>VSync</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QSpinBox" name="targetFrameRate">
|
||||||
|
<property name="suffix">
|
||||||
|
<string> fps</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>15</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>240</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>60</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -385,6 +385,7 @@ plat_munmap(void *ptr, size_t size)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern bool cpu_thread_running;
|
||||||
void
|
void
|
||||||
plat_pause(int p)
|
plat_pause(int p)
|
||||||
{
|
{
|
||||||
@@ -392,6 +393,10 @@ plat_pause(int p)
|
|||||||
wchar_t title[1024];
|
wchar_t title[1024];
|
||||||
wchar_t paused_msg[512];
|
wchar_t paused_msg[512];
|
||||||
|
|
||||||
|
if (!cpu_thread_running && p == 1) {
|
||||||
|
p = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if ((!!p) == dopause) {
|
if ((!!p) == dopause) {
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
if (source_hwnd)
|
if (source_hwnd)
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ public:
|
|||||||
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
|
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
|
||||||
/* Reloads options of renderer */
|
/* Reloads options of renderer */
|
||||||
virtual void reloadOptions() { }
|
virtual void reloadOptions() { }
|
||||||
|
/* Make the renderer reload itself */
|
||||||
|
virtual bool reloadRendererOption() { return false; }
|
||||||
|
|
||||||
int r_monitor_index = 0;
|
int r_monitor_index = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -337,6 +337,26 @@ RendererStack::createRenderer(Renderer renderer)
|
|||||||
current.reset(this->createWindowContainer(hw, this));
|
current.reset(this->createWindowContainer(hw, this));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case Renderer::OpenGL3PCem:
|
||||||
|
{
|
||||||
|
this->createWinId();
|
||||||
|
auto hw = new OpenGLRenderer(this);
|
||||||
|
rendererWindow = hw;
|
||||||
|
connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection);
|
||||||
|
connect(hw, &OpenGLRenderer::initialized, [=]() {
|
||||||
|
/* Buffers are available only after initialization. */
|
||||||
|
imagebufs = rendererWindow->getBuffers();
|
||||||
|
endblit();
|
||||||
|
emit rendererChanged();
|
||||||
|
});
|
||||||
|
connect(hw, &OpenGLRenderer::errorInitializing, [=]() {
|
||||||
|
/* Renderer not could initialize, fallback to software. */
|
||||||
|
imagebufs = {};
|
||||||
|
QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });
|
||||||
|
});
|
||||||
|
current.reset(this->createWindowContainer(hw, this));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Renderer::OpenGL3:
|
case Renderer::OpenGL3:
|
||||||
{
|
{
|
||||||
this->createWinId();
|
this->createWinId();
|
||||||
@@ -406,7 +426,7 @@ RendererStack::createRenderer(Renderer renderer)
|
|||||||
|
|
||||||
currentBuf = 0;
|
currentBuf = 0;
|
||||||
|
|
||||||
if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan) {
|
if (renderer != Renderer::OpenGL3 && renderer != Renderer::Vulkan && renderer != Renderer::OpenGL3PCem) {
|
||||||
imagebufs = rendererWindow->getBuffers();
|
imagebufs = rendererWindow->getBuffers();
|
||||||
endblit();
|
endblit();
|
||||||
emit rendererChanged();
|
emit rendererChanged();
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public:
|
|||||||
OpenGLES,
|
OpenGLES,
|
||||||
OpenGL3,
|
OpenGL3,
|
||||||
Vulkan,
|
Vulkan,
|
||||||
|
OpenGL3PCem = 6,
|
||||||
None = -1
|
None = -1
|
||||||
};
|
};
|
||||||
void switchRenderer(Renderer renderer);
|
void switchRenderer(Renderer renderer);
|
||||||
@@ -69,6 +70,8 @@ public:
|
|||||||
void reloadOptions() const { return rendererWindow->reloadOptions(); }
|
void reloadOptions() const { return rendererWindow->reloadOptions(); }
|
||||||
/* Returns options dialog for current renderer */
|
/* Returns options dialog for current renderer */
|
||||||
QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; }
|
QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; }
|
||||||
|
/* Reload the renderer itself */
|
||||||
|
bool reloadRendererOption() { return rendererWindow ? rendererWindow->reloadRendererOption() : false; }
|
||||||
|
|
||||||
void setFocusRenderer();
|
void setFocusRenderer();
|
||||||
void onResize(int width, int height);
|
void onResize(int width, int height);
|
||||||
|
|||||||
Reference in New Issue
Block a user