monitor and output at the same time
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
TARGET ?= forge
|
TARGET ?= forge
|
||||||
INSTALL_DIR ?= $(HOME)/.local/bin
|
INSTALL_DIR ?= $(HOME)/.local/bin
|
||||||
TEST_ARGS ?= --frag=./shaders --frag-config=./config/shaders.cfg --monitor --internal-size=480
|
TEST_ARGS ?= --frag=./shaders --frag-config=./config/shaders.cfg --tempo=30 --internal-size=480
|
||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
|
|||||||
+13
-5
@@ -18,11 +18,11 @@ static void print_help(int status_code) {
|
|||||||
"[-v] "
|
"[-v] "
|
||||||
"[-hr] "
|
"[-hr] "
|
||||||
"[-s=SCREEN] "
|
"[-s=SCREEN] "
|
||||||
|
"[-m=SCREEN] "
|
||||||
"[-f=DIR_PATH] "
|
"[-f=DIR_PATH] "
|
||||||
"[-fc=CFG_PATH] "
|
"[-fc=CFG_PATH] "
|
||||||
"[-is=SIZE] "
|
"[-is=SIZE] "
|
||||||
"[-t=TEMPO] "
|
"[-t=TEMPO] "
|
||||||
"[-m] "
|
|
||||||
"[--demo] "
|
"[--demo] "
|
||||||
"[-w] "
|
"[-w] "
|
||||||
"\n\n"
|
"\n\n"
|
||||||
@@ -32,11 +32,11 @@ static void print_help(int status_code) {
|
|||||||
" -v, --version print version\n"
|
" -v, --version print version\n"
|
||||||
" -hr, --hot-reload hot reload of shaders scripts\n"
|
" -hr, --hot-reload hot reload of shaders scripts\n"
|
||||||
" -s, --screen output screen number (default: primary)\n"
|
" -s, --screen output screen number (default: primary)\n"
|
||||||
|
" -m, --monitor monitor screen number (default: none)\n"
|
||||||
" -f, --frag fragment shaders directory (default: TODO)\n"
|
" -f, --frag fragment shaders directory (default: TODO)\n"
|
||||||
" -fc, --frag-config fragment shaders config file (default: TODO)\n"
|
" -fc, --frag-config fragment shaders config file (default: TODO)\n"
|
||||||
" -is, --internal-size internal texture height (default: 720)\n"
|
" -is, --internal-size internal texture height (default: 720)\n"
|
||||||
" -t, --tempo base tempo (default: 60)\n"
|
" -t, --tempo base tempo (default: 60)\n"
|
||||||
" -m, --monitor output monitor\n"
|
|
||||||
" --demo demonstration mode\n"
|
" --demo demonstration mode\n"
|
||||||
" -w, --windowed not fullscreen\n");
|
" -w, --windowed not fullscreen\n");
|
||||||
exit(status_code);
|
exit(status_code);
|
||||||
@@ -78,11 +78,12 @@ Parameters args_parse(int argc, char **argv) {
|
|||||||
|
|
||||||
params.hot_reload = false;
|
params.hot_reload = false;
|
||||||
params.screen = 0;
|
params.screen = 0;
|
||||||
|
params.monitor_screen = 0;
|
||||||
|
params.monitor = false;
|
||||||
params.frag_path = 0;
|
params.frag_path = 0;
|
||||||
params.frag_config_path = 0;
|
params.frag_config_path = 0;
|
||||||
params.internal_size = 720;
|
params.internal_size = 720;
|
||||||
params.base_tempo = 60.0f;
|
params.base_tempo = 60.0f;
|
||||||
params.monitor = false;
|
|
||||||
params.demo = false;
|
params.demo = false;
|
||||||
params.windowed = false;
|
params.windowed = false;
|
||||||
|
|
||||||
@@ -105,9 +106,10 @@ Parameters args_parse(int argc, char **argv) {
|
|||||||
} else if (is_arg(arg, "-t") || is_arg(arg, "--tempo")) {
|
} else if (is_arg(arg, "-t") || is_arg(arg, "--tempo")) {
|
||||||
params.base_tempo = (float)parse_uint(arg, value);
|
params.base_tempo = (float)parse_uint(arg, value);
|
||||||
} else if (is_arg(arg, "-is") || is_arg(arg, "--internal-size")) {
|
} else if (is_arg(arg, "-is") || is_arg(arg, "--internal-size")) {
|
||||||
params.internal_size = (float)parse_uint(arg, value);
|
params.internal_size = parse_uint(arg, value);
|
||||||
} else if (is_arg(arg, "--monitor")) {
|
} else if (is_arg(arg, "-m") || is_arg(arg, "--monitor")) {
|
||||||
params.monitor = true;
|
params.monitor = true;
|
||||||
|
params.monitor_screen = parse_uint(arg, value);
|
||||||
} else if (is_arg(arg, "--demo")) {
|
} else if (is_arg(arg, "--demo")) {
|
||||||
params.demo = true;
|
params.demo = true;
|
||||||
} else if (is_arg(arg, "-w") || is_arg(arg, "--windowed")) {
|
} else if (is_arg(arg, "-w") || is_arg(arg, "--windowed")) {
|
||||||
@@ -122,6 +124,12 @@ Parameters args_parse(int argc, char **argv) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.monitor && params.monitor_screen == params.screen &&
|
||||||
|
!params.windowed) {
|
||||||
|
log_error("monitor screen cannot be the same as output screen");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
if (params.frag_path == 0) {
|
if (params.frag_path == 0) {
|
||||||
log_error("required argument -fc/--frag-config");
|
log_error("required argument -fc/--frag-config");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|||||||
+61
-17
@@ -16,15 +16,22 @@
|
|||||||
|
|
||||||
static Context context;
|
static Context context;
|
||||||
static ShaderProgram program;
|
static ShaderProgram program;
|
||||||
|
static ShaderProgram program_monitor;
|
||||||
|
|
||||||
static unsigned int compute_fps(Window *window, Timer *timer) {
|
static unsigned int compute_fps(Window *window_out, Window *window_monitor,
|
||||||
|
Timer *timer) {
|
||||||
static double fps;
|
static double fps;
|
||||||
char title[100];
|
char title[100];
|
||||||
|
|
||||||
if (timer_inc(timer)) {
|
if (timer_inc(timer)) {
|
||||||
fps = timer_reset(timer);
|
fps = timer_reset(timer);
|
||||||
sprintf(title, PACKAGE " " VERSION " - %.0ffps", fps);
|
sprintf(title, PACKAGE " " VERSION " - %.0ffps", fps);
|
||||||
window_update_title(window, title);
|
window_update_title(window_out, title);
|
||||||
|
|
||||||
|
if (window_monitor != NULL) {
|
||||||
|
sprintf(title, PACKAGE " " VERSION " (monitor) - %.0ffps", fps);
|
||||||
|
window_update_title(window_monitor, title);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (unsigned int)round(fps);
|
return (unsigned int)round(fps);
|
||||||
@@ -88,20 +95,35 @@ static void hot_reload(File *common_shader_code, File *fragment_shaders) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loop(Window *window, bool hr, File *common_shader_code,
|
static void loop(Window *window_out, Window *window_monitor, bool hr,
|
||||||
File *fragment_shaders, Timer *timer) {
|
File *common_shader_code, File *fragment_shaders,
|
||||||
|
Timer *timer) {
|
||||||
|
|
||||||
if (hr) {
|
if (hr) {
|
||||||
hot_reload(common_shader_code, fragment_shaders);
|
hot_reload(common_shader_code, fragment_shaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
window_get_context(window, &context);
|
context.fps = compute_fps(window_out, window_monitor, timer);
|
||||||
|
|
||||||
context.fps = compute_fps(window, timer);
|
window_get_context(window_out, &context, true);
|
||||||
|
|
||||||
shaders_apply(program, context);
|
window_use(window_out);
|
||||||
|
|
||||||
window_refresh(window);
|
shaders_compute(program, context, false);
|
||||||
|
|
||||||
|
window_refresh(window_out);
|
||||||
|
|
||||||
|
if (window_monitor != NULL) {
|
||||||
|
window_get_context(window_monitor, &context, false);
|
||||||
|
|
||||||
|
window_use(window_monitor);
|
||||||
|
|
||||||
|
shaders_compute(program_monitor, context, true);
|
||||||
|
|
||||||
|
window_refresh(window_monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
window_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
File read_fragment_shader_file(char *frag_path, unsigned int i) {
|
File read_fragment_shader_file(char *frag_path, unsigned int i) {
|
||||||
@@ -170,7 +192,8 @@ void forge_run(Parameters params) {
|
|||||||
unsigned int frag_count;
|
unsigned int frag_count;
|
||||||
File *fragment_shaders;
|
File *fragment_shaders;
|
||||||
File common_shader_code;
|
File common_shader_code;
|
||||||
Window *window;
|
Window *window_out;
|
||||||
|
Window *window_monitor;
|
||||||
Timer timer;
|
Timer timer;
|
||||||
ConfigFile shader_config;
|
ConfigFile shader_config;
|
||||||
|
|
||||||
@@ -183,19 +206,36 @@ void forge_run(Parameters params) {
|
|||||||
init_files(params.frag_path, &common_shader_code, fragment_shaders,
|
init_files(params.frag_path, &common_shader_code, fragment_shaders,
|
||||||
frag_count);
|
frag_count);
|
||||||
|
|
||||||
window = window_init(PACKAGE " " VERSION, params.screen, params.windowed,
|
window_startup(error_callback);
|
||||||
error_callback, key_callback);
|
|
||||||
|
|
||||||
window_get_context(window, &context);
|
window_out = window_init(PACKAGE " " VERSION, params.screen, params.windowed,
|
||||||
|
NULL, key_callback);
|
||||||
|
|
||||||
|
window_get_context(window_out, &context, true);
|
||||||
|
|
||||||
context.internal_size = params.internal_size;
|
context.internal_size = params.internal_size;
|
||||||
|
|
||||||
program = shaders_init(fragment_shaders, shader_config, context);
|
program = shaders_init(fragment_shaders, shader_config, context);
|
||||||
|
|
||||||
|
if (params.monitor) {
|
||||||
|
window_monitor =
|
||||||
|
window_init(PACKAGE " " VERSION " (monitor)", params.monitor_screen,
|
||||||
|
params.windowed, window_out, key_callback);
|
||||||
|
|
||||||
|
window_get_context(window_monitor, &context, false);
|
||||||
|
|
||||||
|
program_monitor = shaders_init(fragment_shaders, shader_config, context);
|
||||||
|
} else {
|
||||||
|
window_monitor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
init_context(params);
|
init_context(params);
|
||||||
|
|
||||||
if (program.error) {
|
if (program.error) {
|
||||||
window_close(window, true);
|
window_close(window_out, true);
|
||||||
|
if (window_monitor != NULL) {
|
||||||
|
window_close(window_monitor, true);
|
||||||
|
}
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,16 +243,20 @@ void forge_run(Parameters params) {
|
|||||||
|
|
||||||
log_success("Initialized");
|
log_success("Initialized");
|
||||||
|
|
||||||
while (!window_should_close(window)) {
|
while (!window_should_close(window_out) &&
|
||||||
loop(window, params.hot_reload, &common_shader_code, fragment_shaders,
|
(window_monitor == NULL || !window_should_close(window_monitor))) {
|
||||||
&timer);
|
loop(window_out, window_monitor, params.hot_reload, &common_shader_code,
|
||||||
|
fragment_shaders, &timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_files(&common_shader_code, fragment_shaders, frag_count);
|
free_files(&common_shader_code, fragment_shaders, frag_count);
|
||||||
|
|
||||||
config_file_free(shader_config);
|
config_file_free(shader_config);
|
||||||
|
|
||||||
window_close(window, true);
|
window_close(window_out, true);
|
||||||
|
if (window_monitor != NULL) {
|
||||||
|
window_close(window_monitor, true);
|
||||||
|
}
|
||||||
|
|
||||||
free_context();
|
free_context();
|
||||||
}
|
}
|
||||||
+5
-3
@@ -46,6 +46,9 @@ static void init_textures(ShaderProgram *program, Context context) {
|
|||||||
// selects which texture unit subsequent texture state calls will affect
|
// selects which texture unit subsequent texture state calls will affect
|
||||||
glActiveTexture(GL_TEXTURE0 + i);
|
glActiveTexture(GL_TEXTURE0 + i);
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, program->textures[i]);
|
glBindTexture(GL_TEXTURE_2D, program->textures[i]);
|
||||||
|
|
||||||
// define texture image as empty
|
// define texture image as empty
|
||||||
@@ -381,7 +384,7 @@ static void use_program(ShaderProgram program, int i, bool output,
|
|||||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void shaders_apply(ShaderProgram program, Context context) {
|
void shaders_compute(ShaderProgram program, Context context, bool monitor) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
update_viewport(program, context);
|
update_viewport(program, context);
|
||||||
@@ -393,7 +396,6 @@ void shaders_apply(ShaderProgram program, Context context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use_program(program,
|
use_program(program,
|
||||||
context.monitor ? program.frag_monitor_index
|
monitor ? program.frag_monitor_index : program.frag_output_index,
|
||||||
: program.frag_output_index,
|
|
||||||
true, context);
|
true, context);
|
||||||
}
|
}
|
||||||
+1
-1
@@ -9,6 +9,6 @@ ShaderProgram shaders_init(File *fragment_shaders, ConfigFile shader_config,
|
|||||||
void shaders_update(ShaderProgram program, File *fragment_shaders,
|
void shaders_update(ShaderProgram program, File *fragment_shaders,
|
||||||
unsigned int i);
|
unsigned int i);
|
||||||
|
|
||||||
void shaders_apply(ShaderProgram program, Context context);
|
void shaders_compute(ShaderProgram program, Context context, bool monitor);
|
||||||
|
|
||||||
#endif /* SHADERS_H */
|
#endif /* SHADERS_H */
|
||||||
+2
-1
@@ -12,11 +12,12 @@
|
|||||||
typedef struct Parameters {
|
typedef struct Parameters {
|
||||||
bool hot_reload;
|
bool hot_reload;
|
||||||
unsigned char screen;
|
unsigned char screen;
|
||||||
|
unsigned char monitor_screen;
|
||||||
|
bool monitor;
|
||||||
char *frag_path;
|
char *frag_path;
|
||||||
char *frag_config_path;
|
char *frag_config_path;
|
||||||
unsigned int internal_size;
|
unsigned int internal_size;
|
||||||
float base_tempo;
|
float base_tempo;
|
||||||
bool monitor;
|
|
||||||
bool demo;
|
bool demo;
|
||||||
bool windowed;
|
bool windowed;
|
||||||
} Parameters;
|
} Parameters;
|
||||||
|
|||||||
+26
-17
@@ -25,11 +25,6 @@ static void init_glfw(void (*error_callback)(int, const char *)) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context related hints
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
|
||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
|
||||||
|
|
||||||
log_success("[GLFS] Initialized...");
|
log_success("[GLFS] Initialized...");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,9 +46,9 @@ static GLFWmonitor *get_monitor(unsigned char monitor_index) {
|
|||||||
return monitors[monitor_index];
|
return monitors[monitor_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWwindow *create_window(GLFWmonitor *monitor, char *title,
|
static GLFWwindow *
|
||||||
void (*key_callback)(Window *, int, int, int,
|
create_window(GLFWmonitor *monitor, char *title, Window *shared_context,
|
||||||
int)) {
|
void (*key_callback)(Window *, int, int, int, int)) {
|
||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
|
|
||||||
log_info("[GLFW] Creating window...");
|
log_info("[GLFW] Creating window...");
|
||||||
@@ -64,8 +59,13 @@ static GLFWwindow *create_window(GLFWmonitor *monitor, char *title,
|
|||||||
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_FALSE);
|
glfwWindowHint(GLFW_CENTER_CURSOR, GLFW_FALSE);
|
||||||
glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
|
glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE);
|
||||||
|
|
||||||
|
// Context related hints
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
// create fullscreen window in selected monitor
|
// create fullscreen window in selected monitor
|
||||||
window = glfwCreateWindow(1, 1, title, monitor, NULL);
|
window = glfwCreateWindow(1, 1, title, monitor, shared_context);
|
||||||
|
|
||||||
// handle window creation fail
|
// handle window creation fail
|
||||||
if (window == NULL) {
|
if (window == NULL) {
|
||||||
@@ -93,17 +93,19 @@ static void use_window(GLFWwindow *window) {
|
|||||||
glfwSwapInterval(1);
|
glfwSwapInterval(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void window_startup(void (*error_callback)(int, const char *)) {
|
||||||
|
init_glfw(error_callback);
|
||||||
|
}
|
||||||
|
|
||||||
Window *window_init(char *title, unsigned char monitor_index, bool windowed,
|
Window *window_init(char *title, unsigned char monitor_index, bool windowed,
|
||||||
void (*error_callback)(int, const char *),
|
Window *shared_context,
|
||||||
void (*key_callback)(Window *, int, int, int, int)) {
|
void (*key_callback)(Window *, int, int, int, int)) {
|
||||||
GLFWwindow *window;
|
GLFWwindow *window;
|
||||||
GLFWmonitor *monitor;
|
GLFWmonitor *monitor;
|
||||||
|
|
||||||
init_glfw(error_callback);
|
|
||||||
|
|
||||||
monitor = windowed ? NULL : get_monitor(monitor_index);
|
monitor = windowed ? NULL : get_monitor(monitor_index);
|
||||||
|
|
||||||
window = create_window(monitor, title, key_callback);
|
window = create_window(monitor, title, shared_context, key_callback);
|
||||||
|
|
||||||
use_window(window);
|
use_window(window);
|
||||||
|
|
||||||
@@ -114,17 +116,24 @@ void window_update_title(Window *window, char *title) {
|
|||||||
glfwSetWindowTitle(window, title);
|
glfwSetWindowTitle(window, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void window_use(Window *window) {
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
gladLoadGL(glfwGetProcAddress);
|
||||||
|
}
|
||||||
|
|
||||||
void window_refresh(Window *window) {
|
void window_refresh(Window *window) {
|
||||||
// swap front and back buffers
|
// swap front and back buffers
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
// listen to mouse and keyboard events
|
|
||||||
glfwPollEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_get_context(Window *window, Context *context) {
|
void window_events() { glfwPollEvents(); }
|
||||||
|
|
||||||
|
void window_get_context(Window *window, Context *context, bool with_time) {
|
||||||
glfwGetFramebufferSize(window, &context->width, &context->height);
|
glfwGetFramebufferSize(window, &context->width, &context->height);
|
||||||
|
|
||||||
context->time = glfwGetTime();
|
if (with_time) {
|
||||||
|
context->time = glfwGetTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void window_close(Window *window, bool hard) {
|
void window_close(Window *window, bool hard) {
|
||||||
|
|||||||
+8
-2
@@ -3,15 +3,21 @@
|
|||||||
#ifndef WINDOW_H
|
#ifndef WINDOW_H
|
||||||
#define WINDOW_H
|
#define WINDOW_H
|
||||||
|
|
||||||
|
void window_startup(void (*error_callback)(int, const char *));
|
||||||
|
|
||||||
Window *window_init(char *title, unsigned char monitor_index, bool windowed,
|
Window *window_init(char *title, unsigned char monitor_index, bool windowed,
|
||||||
void (*error_callback)(int, const char *),
|
Window *shared_context,
|
||||||
void (*key_callback)(Window *, int, int, int, int));
|
void (*key_callback)(Window *, int, int, int, int));
|
||||||
|
|
||||||
void window_update_title(Window *window, char *title);
|
void window_update_title(Window *window, char *title);
|
||||||
|
|
||||||
|
void window_use(Window *window);
|
||||||
|
|
||||||
void window_refresh(Window *window);
|
void window_refresh(Window *window);
|
||||||
|
|
||||||
void window_get_context(Window *window, Context *context);
|
void window_events();
|
||||||
|
|
||||||
|
void window_get_context(Window *window, Context *context, bool with_time);
|
||||||
|
|
||||||
void window_close(Window *window, bool hard);
|
void window_close(Window *window, bool hard);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user