Added Clang build support

This commit is contained in:
Jarcode
2019-09-08 18:25:04 -07:00
parent d821eeaf0a
commit 563792599a
5 changed files with 80 additions and 53 deletions

View File

@@ -19,7 +19,13 @@ struct request_handler {
.fmt = "ffb" // takes two floats, then a boolean
*/
const char* fmt;
#if defined(__clang__)
void (^handler)(const char* name, void** args);
#elif defined(__GNUC__) || defined(__GNUG__)
void (*handler)(const char* name, void** args);
#else
#error "no nested function/block syntax available"
#endif
};
struct glsl_ext {

View File

@@ -186,18 +186,6 @@ static Atom ATOM__MOTIF_WM_HINTS, ATOM_WM_DELETE_WINDOW, ATOM_WM_PROTOCOLS, ATOM
static GLXContext sharelist_ctx;
static bool sharelist_assigned = false;
/* XQuartz */
#ifdef __APPLE__
static const char *dl_names[] = {
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
};
#else
static const char *dl_names[] = {"libGL.so.1", "libGL.so"};
#endif
static bool offscreen(void) {
return sharelist_assigned;
}
@@ -209,7 +197,29 @@ __attribute__((visibility("default"))) void glava_assign_external_ctx(void* ctx)
sharelist_assigned = true;
}
static void* resolve_f(const char* symbol, void* gl) {
void* s = NULL;
if (gl) s = dlsym(gl, symbol);
if (!s) {
fprintf(stderr, "Failed to resolve GLX symbol: `%s`\n", symbol);
glava_abort();
}
return s;
}
static void init(void) {
/* XQuartz */
#ifdef __APPLE__
static const char *dl_names[] = {
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
};
#else
static const char *dl_names[] = {"libGL.so.1", "libGL.so"};
#endif
display = XOpenDisplay(NULL);
if (!display) {
fprintf(stderr, "XOpenDisplay(): could not establish connection to X11 server\n");
@@ -223,24 +233,14 @@ static void init(void) {
void* hgl = NULL;
for(size_t i = 0; i < (sizeof(dl_names) / sizeof(dl_names[0])) && hgl == NULL; ++i)
hgl = dlopen("libGL.so.1", RTLD_LAZY);
hgl = dlopen(dl_names[1], RTLD_LAZY);
if (!hgl) {
fprintf(stderr, "Failed to load GLX functions (libGL and libGLX do not exist!)\n");
glava_abort();
}
void* resolve_f(const char* symbol) {
void* s = NULL;
if (hgl) s = dlsym(hgl, symbol);
if (!s) {
fprintf(stderr, "Failed to resolve GLX symbol: `%s`\n", symbol);
glava_abort();
}
return s;
}
#define resolve(name) do { name = (typeof(name)) resolve_f(#name); } while (0)
#define resolve(name) do { name = (typeof(name)) resolve_f(#name, hgl); } while (0)
#define intern(name, only_if_exists) \
do { ATOM_##name = XInternAtom(display, #name, only_if_exists); } while (0)
@@ -370,7 +370,7 @@ static void* create_and_bind(const char* name, const char* class,
struct glxwin* w = malloc(sizeof(struct glxwin));
*w = (struct glxwin) {
.override_state = '\0',
.time = 0.0D,
.time = 0.0,
.should_close = false,
.should_render = true,
.bg_changed = false,
@@ -634,7 +634,7 @@ static double get_timert(void) {
if (clock_gettime(CLOCK_REALTIME, &tv)) {
fprintf(stderr, "clock_gettime(CLOCK_REALTIME, ...): %s\n", strerror(errno));
}
return (double) tv.tv_sec + ((double) tv.tv_nsec / 1000000000.0D);
return (double) tv.tv_sec + ((double) tv.tv_nsec / 1000000000.0);
}
static void destroy(struct glxwin* w) {

View File

@@ -801,6 +801,25 @@ static struct gl_bind_src* lookup_bind_src(const char* str) {
return NULL;
}
#if defined(__clang__)
#define MUTABLE __block
#define INLINE(t, x) MUTABLE __auto_type x = ^t
#else
#define MUTABLE
#define INLINE(t, x) t x
#endif
#if defined(__clang__)
void (^block_storage)(const char*, void**);
#define RHANDLER(name, args, ...) \
({ block_storage = ^(const char* name, void** args) __VA_ARGS__; block_storage; })
#elif defined(__GNUC__) || defined(__GNUG__)
#define RHANDLER(name, args, ...) \
({ void _handler(const char* name, void** args) __VA_ARGS__ _handler; })
#else
#error "no nested function/block syntax available"
#endif
struct glava_renderer* rd_new(const char** paths, const char* entry,
const char** requests, const char* force_backend,
struct rd_bind* bindings, int stdin_type,
@@ -809,7 +828,7 @@ struct glava_renderer* rd_new(const char** paths, const char* entry,
xwin_wait_for_wm();
glava_renderer* r = malloc(sizeof(struct glava_renderer));
MUTABLE glava_renderer* r = malloc(sizeof(struct glava_renderer));
*r = (struct glava_renderer) {
.alive = true,
.mirror_input = false,
@@ -827,13 +846,13 @@ struct glava_renderer* rd_new(const char** paths, const char* entry,
pthread_mutex_lock(&r->lock);
struct gl_data* gl = r->gl;
MUTABLE struct gl_data* gl = r->gl;
*gl = (struct gl_data) {
.w = NULL,
.wcb = NULL,
.stages = NULL,
.rate = 0,
.tcounter = 0.0D,
.tcounter = 0.0,
.fcounter = 0,
.ucounter = 0,
.kcounter = 0,
@@ -945,20 +964,18 @@ struct glava_renderer* rd_new(const char** paths, const char* entry,
gl->wcb->init();
int shader_version = 330,
MUTABLE int
shader_version = 330,
context_version_major = 3,
context_version_minor = 3;
const char* module = NULL;
MUTABLE const char* module = NULL;
const char* wintitle_default = "GLava";
char* xwintype = NULL, * wintitle = (char*) wintitle_default;
char** xwinstates = malloc(1);
size_t xwinstates_sz = 0;
MUTABLE char* xwintype = NULL, * wintitle = (char*) wintitle_default;
MUTABLE char** xwinstates = malloc(1);
MUTABLE size_t xwinstates_sz = 0;
bool loading_module = true, loading_smooth_pass = false, loading_presets = false;;
struct gl_sfbo* current = NULL;
size_t t_count = 0;
#define RHANDLER(name, args, ...) \
({ void _handler(const char* name, void** args) __VA_ARGS__ _handler; })
MUTABLE struct gl_sfbo* current = NULL;
MUTABLE size_t t_count = 0;
#define WINDOW_HINT(request) \
{ .name = "set" #request, .fmt = "b", \
@@ -967,7 +984,6 @@ struct glava_renderer* rd_new(const char** paths, const char* entry,
struct request_handler handlers[] = {
{ .name = "setopacity", .fmt = "s",
.handler = RHANDLER(name, args, {
bool native_opacity = !strcmp("native", (char*) args[0]);
gl->premultiply_alpha = native_opacity;
@@ -1576,7 +1592,7 @@ struct glava_renderer* rd_new(const char** paths, const char* entry,
void rd_time(struct glava_renderer* r) {
struct gl_data* gl = r->gl;
gl->wcb->set_time(gl->w, 0.0D); /* reset time for measuring this frame */
gl->wcb->set_time(gl->w, 0.0); /* reset time for measuring this frame */
}
bool rd_update(struct glava_renderer* r, float* lb, float* rb, size_t bsz, bool modified) {
@@ -1847,7 +1863,8 @@ bool rd_update(struct glava_renderer* r, float* lb, float* rb, size_t bsz, bool
for (t = 0; t < gl->stages_sz; ++t) {
bool load_flags[64] = { [ 0 ... 63 ] = false }; /* Load flags for each texture position */
MUTABLE bool load_flags_s[64] = { [ 0 ... 63 ] = false };
MUTABLE bool* load_flags = load_flags_s; /* Load flags for each texture position */
/* Current shader program */
struct gl_sfbo* current = &gl->stages[t];
@@ -1940,13 +1957,13 @@ bool rd_update(struct glava_renderer* r, float* lb, float* rb, size_t bsz, bool
/* Iterate through each uniform binding, transforming and passing the
data into the shader. */
size_t b, c = 0;
MUTABLE size_t b, c = 0;
for (b = 0; b < current->binds_sz; ++b) {
struct gl_bind* bind = &current->binds[b];
/* Handle transformations and bindings for 1D samplers */
void handle_1d_tex(GLuint tex, float* buf, float* ubuf, size_t sz, int offset, bool audio) {
INLINE(void, handle_1d_tex)(GLuint tex, float* buf, float* ubuf,
size_t sz, int offset, bool audio) {
if (load_flags[offset])
goto bind_uniform;
load_flags[offset] = true;
@@ -2041,12 +2058,11 @@ bool rd_update(struct glava_renderer* r, float* lb, float* rb, size_t bsz, bool
glBindTexture(GL_TEXTURE_1D, tex);
bind_uniform:
glUniform1i(bind->uniform, offset);
}
}; /* <-- this pesky semicolon is only required in clang because of how blocks work */
/* Handle each binding source; only bother to handle transformations
for 1D samplers, since that's the only transformation type that
(currently) exists. */
switch (bind->src_type) {
case SRC_PREV:
/* bind texture and pass it to the shader uniform if we need to pass
@@ -2095,12 +2111,12 @@ bool rd_update(struct glava_renderer* r, float* lb, float* rb, size_t bsz, bool
/* Handling sleeping (to meet target framerate) */
if (gl->rate > 0) {
double target = 1.0D / (double) gl->rate; /* 1 / freq = time per frame */
double target = 1.0 / (double) gl->rate; /* 1 / freq = time per frame */
if (duration < target) {
double sleep = target - duration;
struct timespec tv = {
.tv_sec = (time_t) floor(sleep),
.tv_nsec = (long) (double) ((sleep - floor(sleep)) * 1000000000.0D)
.tv_nsec = (long) (double) ((sleep - floor(sleep)) * 1000000000.0)
};
nanosleep(&tv, NULL);
duration = target; /* update duration to reflect our sleep time */
@@ -2118,7 +2134,7 @@ bool rd_update(struct glava_renderer* r, float* lb, float* rb, size_t bsz, bool
gl->kcounter = 0; /* reset keyframe counter (for interpolation) */
} else ++gl->kcounter; /* increment keyframe counter otherwise */
gl->tcounter += duration; /* timer counter, measuring when a >1s has occurred */
if (gl->tcounter >= 1.0D) {
if (gl->tcounter >= 1.0) {
gl->fr = gl->fcounter / gl->tcounter; /* frame rate (FPS) */
gl->ur = gl->ucounter / gl->tcounter; /* update rate (UPS) */
if (gl->print_fps) { /* print FPS */

View File

@@ -217,6 +217,8 @@ const char* xwin_detect_wm(struct gl_wcb* wcb) {
}
static int stub_handler(Display* d, XErrorEvent* e) { return 0; }
bool xwin_should_render(struct gl_wcb* wcb, void* impl) {
bool ret = true, should_close = false;
Display* d = wcb->get_x11_display();
@@ -233,9 +235,7 @@ bool xwin_should_render(struct gl_wcb* wcb, void* impl) {
unsigned long nitems, bytes_after;
unsigned char* data = NULL;
int handler(Display* d, XErrorEvent* e) { return 0; }
XSetErrorHandler(handler); /* dummy error handler */
XSetErrorHandler(stub_handler); /* dummy error handler */
if (Success != XGetWindowProperty(d, DefaultRootWindow(d), prop, 0, 1, false, AnyPropertyType,
&actual_type, &actual_format, &nitems, &bytes_after, &data)) {

View File

@@ -24,6 +24,11 @@ glava_dependencies = [
cc.find_library('Xext')
]
if cc.get_id() == 'clang'
add_project_arguments('-fblocks', language: 'c')
glava_dependencies += cc.find_library('BlocksRuntime')
endif
shader_dir = get_option('shader_install_dir')
glava_version = meson.project_version()
if glava_version == ''