Initial PCem OpenGL 3.x renderer port
This commit is contained in:
@@ -252,6 +252,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;
|
||||||
|
|||||||
@@ -88,6 +88,9 @@ kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main)
|
|||||||
{
|
{
|
||||||
if (main) {
|
if (main) {
|
||||||
kbc_at_dev_log("%s: dev->queue[%02X] = %02X;\n", dev->name, dev->queue_end, val);
|
kbc_at_dev_log("%s: dev->queue[%02X] = %02X;\n", dev->name, dev->queue_end, val);
|
||||||
|
if (!is_cpu_thread && kbc_at_dev_queue_pos(dev, 1) == dev->fifo_mask) {
|
||||||
|
while (kbc_at_dev_queue_pos(dev, 1) == dev->fifo_mask) {}
|
||||||
|
}
|
||||||
dev->queue[dev->queue_end] = val;
|
dev->queue[dev->queue_end] = val;
|
||||||
dev->queue_end = (dev->queue_end + 1) & dev->fifo_mask;
|
dev->queue_end = (dev->queue_end + 1) & dev->fifo_mask;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -188,6 +188,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);
|
||||||
|
|||||||
@@ -58,6 +58,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)
|
||||||
|
|
||||||
@@ -90,6 +91,33 @@ extern ini_section_t ini_find_or_create_section(ini_t ini, const char *name);
|
|||||||
extern void ini_rename_section(ini_section_t section, const char *name);
|
extern void ini_rename_section(ini_section_t section, const char *name);
|
||||||
extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section);
|
extern void ini_delete_section_if_empty(ini_t ini, ini_section_t section);
|
||||||
|
|
||||||
|
static inline void *wx_config_load(const char *path) { return (void*) ini_read(path); };
|
||||||
|
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;
|
||||||
|
strncpy(dst, str, size);
|
||||||
|
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); };
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,6 +22,13 @@
|
|||||||
#ifndef EMU_KEYBOARD_H
|
#ifndef EMU_KEYBOARD_H
|
||||||
#define EMU_KEYBOARD_H
|
#define EMU_KEYBOARD_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# include <atomic>
|
||||||
|
using atomic_uint = std::atomic_uint;
|
||||||
|
#else
|
||||||
|
# include <stdatomic.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DEV_KBD = 0,
|
DEV_KBD = 0,
|
||||||
DEV_AUX = 1
|
DEV_AUX = 1
|
||||||
@@ -54,16 +61,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;
|
atomic_uint queue_start;
|
||||||
uint8_t queue_end;
|
atomic_uint 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
|
||||||
56
src/include/86box/qt-glslp-parser.h
Normal file
56
src/include/86box/qt-glslp-parser.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#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);
|
||||||
|
|
||||||
|
#endif /* SRC_WX_GLSLP_PARSER_H_ */
|
||||||
22
src/ini.c
22
src/ini.c
@@ -157,6 +157,23 @@ 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;
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
@@ -593,6 +610,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,6 +89,9 @@ add_library(ui STATIC
|
|||||||
qt_hardwarerenderer.hpp
|
qt_hardwarerenderer.hpp
|
||||||
qt_openglrenderer.cpp
|
qt_openglrenderer.cpp
|
||||||
qt_openglrenderer.hpp
|
qt_openglrenderer.hpp
|
||||||
|
qt_openglrenderer_pcem.cpp
|
||||||
|
qt_openglrenderer_pcem.hpp
|
||||||
|
qt_glsl_parser.cpp
|
||||||
qt_opengloptions.cpp
|
qt_opengloptions.cpp
|
||||||
qt_opengloptions.hpp
|
qt_opengloptions.hpp
|
||||||
qt_opengloptionsdialog.cpp
|
qt_opengloptionsdialog.cpp
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
308
src/qt/qt_glsl_parser.cpp
Normal file
308
src/qt/qt_glsl_parser.cpp
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
#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/qt-glslp-parser.h>
|
||||||
|
#include <86box/path.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#define safe_strncpy(a, b, n) \
|
||||||
|
do { \
|
||||||
|
strncpy((a), (b), (n)-1); \
|
||||||
|
(a)[(n)-1] = 0; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
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) {
|
||||||
|
//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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -389,6 +389,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();
|
||||||
|
|||||||
@@ -452,6 +452,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)
|
||||||
|
|||||||
1679
src/qt/qt_openglrenderer_pcem.cpp
Normal file
1679
src/qt/qt_openglrenderer_pcem.cpp
Normal file
File diff suppressed because it is too large
Load Diff
127
src/qt/qt_openglrenderer_pcem.hpp
Normal file
127
src/qt/qt_openglrenderer_pcem.hpp
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* 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 file for OpenGL renderer
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Authors: Teemu Korhonen
|
||||||
|
*
|
||||||
|
* Copyright 2022 Teemu Korhonen
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef QT_OpenGLRendererPCem_HPP
|
||||||
|
#define QT_OpenGLRendererPCem_HPP
|
||||||
|
|
||||||
|
#if defined Q_OS_MACOS || __arm__
|
||||||
|
# define NO_BUFFER_STORAGE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QOpenGLContext>
|
||||||
|
#include <QOpenGLExtraFunctions>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QWindow>
|
||||||
|
#if !defined NO_BUFFER_STORAGE && !(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
# include <QtOpenGLExtensions/QOpenGLExtensions>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "qt_opengloptions.hpp"
|
||||||
|
#include "qt_renderercommon.hpp"
|
||||||
|
|
||||||
|
typedef void(QOPENGLF_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC_LOCAL)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
|
||||||
|
|
||||||
|
class OpenGLRendererPCem : public QWindow, public RendererCommon {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QOpenGLContext *context;
|
||||||
|
|
||||||
|
OpenGLRendererPCem(QWidget *parent = nullptr);
|
||||||
|
~OpenGLRendererPCem();
|
||||||
|
|
||||||
|
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> getBuffers() override;
|
||||||
|
|
||||||
|
void finalize() override final;
|
||||||
|
//bool hasOptions() const override { return true; }
|
||||||
|
//QDialog *getOptions(QWidget *parent) override;
|
||||||
|
//void reloadOptions() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void initialized();
|
||||||
|
void errorInitializing();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onBlit(int buf_idx, int x, int y, int w, int h);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void exposeEvent(QExposeEvent *event) override;
|
||||||
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
bool event(QEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr int INIT_WIDTH = 640;
|
||||||
|
static constexpr int INIT_HEIGHT = 400;
|
||||||
|
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). */
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<uint8_t>, 2> imagebufs;
|
||||||
|
|
||||||
|
QTimer *renderTimer;
|
||||||
|
OpenGLOptions *options;
|
||||||
|
|
||||||
|
QString glslVersion;
|
||||||
|
|
||||||
|
bool isInitialized = false;
|
||||||
|
bool isFinalized = false;
|
||||||
|
|
||||||
|
GLuint unpackBufferID = 0;
|
||||||
|
GLuint vertexArrayID = 0;
|
||||||
|
GLuint vertexBufferID = 0;
|
||||||
|
GLuint textureID = 0;
|
||||||
|
int frameCounter = 0;
|
||||||
|
|
||||||
|
OpenGLOptions::FilterType currentFilter;
|
||||||
|
|
||||||
|
void *unpackBuffer = nullptr;
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
void initializeExtensions();
|
||||||
|
void initializeBuffers();
|
||||||
|
void applyOptions();
|
||||||
|
void applyShader(const OpenGLShaderPass &shader);
|
||||||
|
bool notReady() const { return !isInitialized || isFinalized; }
|
||||||
|
|
||||||
|
/* GL_ARB_buffer_storage */
|
||||||
|
bool hasBufferStorage = false;
|
||||||
|
#ifndef NO_BUFFER_STORAGE
|
||||||
|
PFNGLBUFFERSTORAGEEXTPROC_LOCAL glBufferStorage = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void render();
|
||||||
|
//void updateOptions(OpenGLOptions *newOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
class opengl_init_error_pcem : public std::runtime_error {
|
||||||
|
public:
|
||||||
|
opengl_init_error_pcem(const QString &what)
|
||||||
|
: std::runtime_error(what.toStdString())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "qt_hardwarerenderer.hpp"
|
#include "qt_hardwarerenderer.hpp"
|
||||||
#include "qt_openglrenderer.hpp"
|
#include "qt_openglrenderer.hpp"
|
||||||
|
#include "qt_openglrenderer_pcem.hpp"
|
||||||
#include "qt_softwarerenderer.hpp"
|
#include "qt_softwarerenderer.hpp"
|
||||||
#include "qt_vulkanwindowrenderer.hpp"
|
#include "qt_vulkanwindowrenderer.hpp"
|
||||||
|
|
||||||
@@ -337,19 +338,39 @@ RendererStack::createRenderer(Renderer renderer)
|
|||||||
current.reset(this->createWindowContainer(hw, this));
|
current.reset(this->createWindowContainer(hw, this));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Renderer::OpenGL3:
|
case Renderer::OpenGL3PCem:
|
||||||
{
|
{
|
||||||
this->createWinId();
|
this->createWinId();
|
||||||
auto hw = new OpenGLRenderer(this);
|
auto hw = new OpenGLRendererPCem(this);
|
||||||
rendererWindow = hw;
|
rendererWindow = hw;
|
||||||
connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection);
|
connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection);
|
||||||
connect(hw, &OpenGLRenderer::initialized, [=]() {
|
connect(hw, &OpenGLRendererPCem::initialized, [=]() {
|
||||||
/* Buffers are available only after initialization. */
|
/* Buffers are available only after initialization. */
|
||||||
imagebufs = rendererWindow->getBuffers();
|
imagebufs = rendererWindow->getBuffers();
|
||||||
endblit();
|
endblit();
|
||||||
emit rendererChanged();
|
emit rendererChanged();
|
||||||
});
|
});
|
||||||
connect(hw, &OpenGLRenderer::errorInitializing, [=]() {
|
connect(hw, &OpenGLRendererPCem::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:
|
||||||
|
{
|
||||||
|
this->createWinId();
|
||||||
|
auto hw = new OpenGLRendererPCem(this);
|
||||||
|
rendererWindow = hw;
|
||||||
|
connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRendererPCem::onBlit, Qt::QueuedConnection);
|
||||||
|
connect(hw, &OpenGLRendererPCem::initialized, [=]() {
|
||||||
|
/* Buffers are available only after initialization. */
|
||||||
|
imagebufs = rendererWindow->getBuffers();
|
||||||
|
endblit();
|
||||||
|
emit rendererChanged();
|
||||||
|
});
|
||||||
|
connect(hw, &OpenGLRendererPCem::errorInitializing, [=]() {
|
||||||
/* Renderer not could initialize, fallback to software. */
|
/* Renderer not could initialize, fallback to software. */
|
||||||
imagebufs = {};
|
imagebufs = {};
|
||||||
QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });
|
QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });
|
||||||
@@ -406,7 +427,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);
|
||||||
|
|||||||
Reference in New Issue
Block a user