Added gl_wcb interface to abstract out glfw and glx usage

This commit is contained in:
Jarcode
2018-02-11 20:43:52 -08:00
parent 79d06b070e
commit e5f5671acc
5 changed files with 155 additions and 120 deletions

172
render.c
View File

@@ -14,27 +14,6 @@
#include <unistd.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#define GLFW_EXPOSE_NATIVE_X11
/* Hack to make GLFW 3.1 headers work with GLava. We don't use the context APIs from GLFW, but
the old headers require one of them to be selected for exposure in glfw3native.h. */
#if GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR <= 1
#define GLFW_EXPOSE_NATIVE_GLX
#endif
#include <GLFW/glfw3native.h>
/* Fixes for old GLFW versions */
#ifndef GLFW_TRUE
#define GLFW_TRUE GL_TRUE
#endif
#ifndef GLFW_FALSE
#define GLFW_FALSE GL_FALSE
#endif
#include "render.h"
#include "xwin.h"
@@ -56,6 +35,18 @@
#define VERTEX_SHADER_SRC \
"layout(location = 0) in vec3 pos; void main() { gl_Position = vec4(pos.x, pos.y, 0.0F, 1.0F); }"
/* Window creation backend interfaces */
#ifdef GLAVA_GLFW
extern struct gl_wcb wcb_glfw;
#endif
#define INIT_WCBS() \
do { \
wcbs[0] = wcb_glfw; \
} while (0)
struct gl_wcb wcbs[2] = {};
/* GLSL bind source */
struct gl_bind_src {
@@ -110,10 +101,10 @@ struct overlay_data {
struct gl_data {
struct gl_sfbo* stages;
struct overlay_data overlay;
Display* display;
GLuint audio_tex_r, audio_tex_l, bg_tex, sm_prog;
size_t stages_sz, bufscale, avg_frames;
GLFWwindow* w;
void* w;
struct gl_wcb* wcb;
int lww, lwh, lwx, lwy; /* last window dimensions */
int rate; /* framerate */
double tcounter;
@@ -706,6 +697,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
struct gl_data* gl = r->gl;
*gl = (struct gl_data) {
.w = NULL,
.wcb = NULL,
.stages = NULL,
.rate = 0,
.tcounter = 0.0D,
@@ -734,6 +726,28 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
.geometry = { 0, 0, 500, 400 },
.clear_color = { 0.0F, 0.0F, 0.0F, 0.0F }
};
const char* backend = "glfw";
INIT_WCBS();
#ifdef GLAVA_UNIX
if (!getenv("WAYLAND_DISPLAY") && getenv("DISPLAY")) {
// backend = "glx";
}
#endif
for (size_t t = 0; t < sizeof(wcbs) / sizeof(*wcbs); ++t) {
if (wcbs[t].name && !strcmp(wcbs[t].name, backend)) {
gl->wcb = &wcbs[t];
break;
}
};
if (!gl->wcb) {
fprintf(stderr, "Invalid window creation backend selected: '%s'\n", gl->wcb);
abort();
}
#ifdef GLAD_DEBUG
printf("Assigning debug callback\n");
@@ -744,17 +758,11 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
}
#endif
if (!glfwInit())
abort();
gl->wcb->init();
gl->display = glfwGetX11Display();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_FLOATING, GLFW_FALSE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
int shader_version = 330;
int shader_version = 330,
context_version_major = 3,
context_version_minor = 3;
const char* module = force_mod;
char* xwintype = NULL, * wintitle = "GLava";
char** xwinstates = malloc(1);
@@ -763,15 +771,9 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
struct gl_sfbo* current = NULL;
size_t t_count = 0;
#define WINDOW_HINT(request, attr) \
{ .name = request, .fmt = "b", \
.handler = RHANDLER(name, args, { glfwWindowHint(attr, *(bool*) args[0]); }) }
#define STUB(request, f) \
{ .name = request, .fmt = f, \
.handler = RHANDLER(name, args, { \
fprintf(stderr, "warning: '%s' request is not implemented for this build\n", \
request); }) }
#define WINDOW_HINT(request) \
{ .name = "set" #request, .fmt = "b", \
.handler = RHANDLER(name, args, { gl->wcb->set_##request(gl->w, *(bool*) args[0]); }) }
struct request_handler handlers[] = {
{
@@ -781,18 +783,8 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
bool native_opacity = !strcmp("native", (char*) args[0]);
gl->use_alpha = true;
#ifdef GLFW_TRANSPARENT_FRAMEBUFFER
glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, native_opacity ? GLFW_TRUE : GLFW_FALSE);
// if (native_opacity) gl->use_alpha = false;
#elif GLFW_TRANSPARENT
glfwWindowHint(GLFW_TRANSPARENT, native_opacity ? GLFW_TRUE : GLFW_FALSE);
// if (native_opacity) gl->use_alpha = false;
#else
if (native_opacity)
printf("WARNING: the linked version of GLFW3 does not have transparency support"
" (GLFW_TRANSPARENT[_FRAMEBUFFER])!\n");
#endif
gl->wcb->set_transparent(gl->w, native_opacity);
if (!strcmp("xroot", (char*) args[0]))
gl->copy_desktop = true;
@@ -840,19 +832,15 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
}
})
},
WINDOW_HINT("setfloating", GLFW_FLOATING),
WINDOW_HINT("setdecorated", GLFW_DECORATED),
WINDOW_HINT("setfocused", GLFW_FOCUSED),
#ifdef GLFW_MAXIMIZED
WINDOW_HINT("setmaximized", GLFW_MAXIMIZED),
#else
STUB("setmaximized", "b"),
#endif
WINDOW_HINT(floating),
WINDOW_HINT(decorated),
WINDOW_HINT(focused),
WINDOW_HINT(maximized),
{
.name = "setversion", .fmt = "ii",
.handler = RHANDLER(name, args, {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, *(int*) args[0]);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, *(int*) args[1]);
context_version_major = *(int*) args[0];
context_version_minor = *(int*) args[1];
})
},
{
@@ -882,7 +870,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
{ .name = "setshaderversion", .fmt = "i",
.handler = RHANDLER(name, args, { shader_version = *(int*) args[0]; }) },
{ .name = "setswap", .fmt = "i",
.handler = RHANDLER(name, args, { glfwSwapInterval(*(int*) args[0]); }) },
.handler = RHANDLER(name, args, { gl->wcb->set_swap(gl->w, *(int*) args[0]); }) },
{ .name = "setframerate", .fmt = "i",
.handler = RHANDLER(name, args, { gl->rate = *(int*) args[0]; }) },
{ .name = "setprintframes", .fmt = "b",
@@ -1052,26 +1040,16 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
exit(EXIT_FAILURE);
}
if (!(gl->w = glfwCreateWindow(500, 400, wintitle, NULL, NULL))) {
glfwTerminate();
if (!(gl->w = gl->wcb->create_and_bind(wintitle, "GLava", xwintype,
(const char**) xwinstates, xwinstates_sz,
gl->geometry[2], gl->geometry[3],
gl->geometry[0], gl->geometry[1],
context_version_major, context_version_minor))) {
abort();
}
if (xwintype) {
xwin_settype(r, xwintype);
free(xwintype);
}
for (size_t t = 0; t < xwinstates_sz; ++t) {
xwin_addstate(r, xwinstates[t]);
}
free(xwinstates);
glfwSetWindowPos(gl->w, gl->geometry[0], gl->geometry[1]);
glfwSetWindowSize(gl->w, gl->geometry[2], gl->geometry[3]);
glfwMakeContextCurrent(gl->w);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
if (xwintype) free(xwintype);
if (xwinstates) free(xwinstates);
glDisable(GL_DEPTH_TEST);
glDisable(GL_DEPTH_CLAMP);
@@ -1161,7 +1139,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
as it can rendered directly */
if (idx != count) {
int w, h;
glfwGetFramebufferSize(gl->w, &w, &h);
gl->wcb->get_fbsize(gl->w, &w, &h);
setup_sfbo(&stages[idx - 1], w, h);
}
@@ -1234,7 +1212,7 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
glClearColor(gl->clear_color.r, gl->clear_color.g, gl->clear_color.b, gl->clear_color.a);
glfwShowWindow(gl->w);
gl->wcb->set_visible(gl->w, true);
return r;
}
@@ -1242,14 +1220,14 @@ struct renderer* rd_new(const char** paths, const char* entry, const char* force
void rd_time(struct renderer* r) {
struct gl_data* gl = r->gl;
glfwSetTime(0.0D); /* reset time for measuring this frame */
gl->wcb->set_time(gl->w, 0.0D); /* reset time for measuring this frame */
}
void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modified) {
struct gl_data* gl = r->gl;
size_t t, a, fbsz = bsz * sizeof(float);
r->alive = !glfwWindowShouldClose(gl->w);
r->alive = !gl->wcb->should_close(gl->w);
if (!r->alive)
return;
@@ -1304,8 +1282,8 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
}
}
int ww, wh, wx, wy;
glfwGetFramebufferSize(gl->w, &ww, &wh);
glfwGetWindowPos(gl->w, &wx, &wy);
gl->wcb->get_fbsize(gl->w, &ww, &wh);
gl->wcb->get_pos(gl->w, &wx, &wy);
/* Resize screen textures if needed */
if (ww != gl->lww || wh != gl->lwh) {
@@ -1544,10 +1522,9 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
}
/* Swap buffers, handle events, etc. (vsync is potentially included here, too) */
glfwSwapBuffers(gl->w);
glfwPollEvents();
gl->wcb->swap_buffers(gl->w);
double duration = glfwGetTime(); /* frame execution time */
double duration = gl->wcb->get_time(gl->w); /* frame execution time */
/* Handling sleeping (to meet target framerate) */
if (gl->rate > 0) {
@@ -1583,8 +1560,9 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
/* Refresh window position and size if we are forcing it */
if (gl->force_geometry) {
glfwSetWindowPos(gl->w, gl->geometry[0], gl->geometry[1]);
glfwSetWindowSize(gl->w, gl->geometry[2], gl->geometry[3]);
gl->wcb->set_geometry(gl->w,
gl->geometry[0], gl->geometry[1],
gl->geometry[2], gl->geometry[3]);
}
}
@@ -1592,15 +1570,11 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
gl->interpolate = old_interpolate;
}
void* rd_get_impl_window(struct renderer* r) { return r->gl->w; }
Display* rd_get_x11_display(struct renderer* r) { return r->gl->display; }
Window rd_get_x11_window(struct renderer* r) { return glfwGetX11Window(r->gl->w); }
void rd_get_fbsize(struct renderer* r, int* w, int* h) { glfwGetFramebufferSize(r->gl->w, w, h); }
void rd_get_wpos(struct renderer* r, int* x, int* y) { glfwGetWindowPos(r->gl->w, x, y); }
void* rd_get_impl_window (struct renderer* r) { return r->gl->w; }
struct gl_wcb* rd_get_wcb (struct renderer* r) { return r->gl->wcb; }
void rd_destroy(struct renderer* r) {
/* TODO: delete everything else, not really needed though (as the application exits after here) */
glfwTerminate();
free(r->gl);
free(r);
}