2 Commits

Author SHA1 Message Date
Jarcode
2c99124556 Fixed various static leaks 2018-10-21 10:28:06 -07:00
Jarcode
9d1c3a177c Fixed critical bug that caused GLava to stop rendering if it was obstructed 2018-10-09 17:43:15 -07:00
4 changed files with 120 additions and 87 deletions

View File

@@ -105,8 +105,21 @@ bool ext_parse_color(const char* str, size_t elem_sz, float** results) {
return true;
}
static void free_after(struct glsl_ext* ext, void* ptr) {
++ext->destruct_sz;
ext->destruct = realloc(ext->destruct, sizeof(void*) * ext->destruct_sz);
ext->destruct[ext->destruct_sz - 1] = ptr;
}
static void inherit(struct glsl_ext* parent, struct glsl_ext* child) {
free_after(parent, child->processed);
parent->destruct = realloc(parent->destruct, sizeof(void*) * (parent->destruct_sz + child->destruct_sz));
memcpy(parent->destruct + parent->destruct_sz, child->destruct, sizeof(void*) * child->destruct_sz);
parent->destruct_sz += child->destruct_sz;
free(child->destruct);
}
/* handle raw arguments for #include and #request directives */
/* NOTE: munmap needs to be called on the result */
static struct schar directive(struct glsl_ext* ext, char** args,
size_t args_sz, bool include,
size_t line, const char* f) {
@@ -144,21 +157,23 @@ static struct schar directive(struct glsl_ext* ext, char** args,
}
struct glsl_ext next = {
.source = map,
.source_len = st.st_size,
.cd = ext->cd,
.cfd = ext->cfd,
.handlers = ext->handlers
.source = map,
.source_len = st.st_size,
.cd = ext->cd,
.cfd = ext->cfd,
.handlers = ext->handlers
};
/* recursively process */
ext_process(&next, target);
inherit(ext, &next);
munmap(map, st.st_size);
struct schar ret = {
.buf = next.processed,
.sz = next.p_len
};
return ret;
} else {
@@ -251,6 +266,9 @@ static struct schar directive(struct glsl_ext* ext, char** args,
/* state machine parser */
void ext_process(struct glsl_ext* ext, const char* f) {
ext->destruct = malloc(1);
ext->destruct_sz = 0;
#define LINE_START 0
#define GLSL 1
#define MACRO 2
@@ -272,7 +290,7 @@ void ext_process(struct glsl_ext* ext, const char* f) {
size_t line = 1;
bool quoted = false, arg_start;
char cbuf[9];
char** args = NULL;
char** args = malloc(sizeof(char*));
size_t args_sz = 0;
bool prev_slash = false, comment = false, comment_line = false, prev_asterix = false,
@@ -418,7 +436,6 @@ void ext_process(struct glsl_ext* ext, const char* f) {
{
arg_start_idx = t + 1;
arg_start = true;
args = malloc(sizeof(char*));
args_sz = 0;
*args = NULL;
}
@@ -468,7 +485,6 @@ void ext_process(struct glsl_ext* ext, const char* f) {
n_append(&sbuf, r.sz, r.buf);
append(&sbuf, "\n");
}
munmap(r.buf, r.sz);
state = LINE_START;
}
break;
@@ -497,10 +513,20 @@ void ext_process(struct glsl_ext* ext, const char* f) {
}
ext->processed = sbuf.buf;
ext->p_len = sbuf.at;
if (args)
if (args) {
for (t = 0; t < args_sz; ++t) {
free(args[t]);
}
free(args);
}
}
void ext_free(struct glsl_ext* ext) {
free(ext->processed);
size_t t;
for (t = 0; t < ext->destruct_sz; ++t) {
free(ext->destruct[t]);
}
free(ext->destruct);
}

View File

@@ -21,12 +21,14 @@ struct request_handler {
};
struct glsl_ext {
char* processed; /* OUT: null terminated processed source */
size_t p_len; /* OUT: length of processed buffer, excluding null char */
const char* source; /* IN: raw data passed via ext_process */
size_t source_len; /* IN: raw source len */
const char* cd; /* IN: current directory */
const char* cfd; /* IN: config directory, if NULL it is assumed to cd */
char* processed; /* OUT: null terminated processed source */
size_t p_len; /* OUT: length of processed buffer, excluding null char */
const char* source; /* IN: raw data passed via ext_process */
size_t source_len; /* IN: raw source len */
const char* cd; /* IN: current directory */
const char* cfd; /* IN: config directory, if NULL it is assumed to cd */
void** destruct; /* internal */
size_t destruct_sz; /* internal */
/* IN: NULL (where the last element's 'name' member is NULL) terminated
array of request handlers */

View File

@@ -267,6 +267,41 @@ static void apply_clickthrough(struct glxwin* w) {
}
}
static void process_events(struct glxwin* w) {
while (XPending(display) > 0) {
XEvent ev;
XNextEvent(display, &ev);
switch (ev.type) {
case ClientMessage:
if (ev.xclient.message_type == ATOM_WM_PROTOCOLS
&& ev.xclient.data.l[0] == ATOM_WM_DELETE_WINDOW) {
w->should_close = true;
}
break;
case VisibilityNotify:
switch (ev.xvisibility.state) {
case VisibilityFullyObscured:
w->should_render = false;
break;
case VisibilityUnobscured:
case VisibilityPartiallyObscured:
w->should_render = true;
break;
default:
fprintf(stderr, "Invalid VisibilityNotify event state (%d)\n", ev.xvisibility.state);
break;
}
break;
case PropertyNotify:
if (ev.xproperty.atom == ATOM__XROOTPMAP_ID) {
w->bg_changed = true;
}
break;
default: break;
}
}
}
static void* create_and_bind(const char* name, const char* class,
const char* type, const char** states,
size_t states_sz,
@@ -360,7 +395,7 @@ static void* create_and_bind(const char* name, const char* class,
vi = glXGetVisualFromFBConfig(display, config);
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vi->visual, AllocNone);
attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask;
attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask;
attr.event_mask |= PropertyChangeMask | VisibilityChangeMask;
attr.background_pixmap = None;
attr.border_pixel = 0;
@@ -498,44 +533,13 @@ static bool should_render(struct glxwin* w) {
attributes to see if our window isn't viewable. */
XWindowAttributes attrs;
XGetWindowAttributes(display, w->w, &attrs);
process_events(w);
return w->should_render && attrs.map_state == IsViewable;
}
static void swap_buffers(struct glxwin* w) {
glXSwapBuffers(display, w->w);
while (XPending(display) > 0) {
XEvent ev;
XNextEvent(display, &ev);
switch (ev.type) {
case ClientMessage:
if (ev.xclient.message_type == ATOM_WM_PROTOCOLS
&& ev.xclient.data.l[0] == ATOM_WM_DELETE_WINDOW) {
w->should_close = true;
}
break;
case VisibilityNotify:
switch (ev.xvisibility.state) {
case VisibilityFullyObscured:
w->should_render = false;
break;
case VisibilityUnobscured:
case VisibilityPartiallyObscured:
w->should_render = true;
break;
default:
fprintf(stderr, "Invalid VisibilityNotify event state (%d)\n", ev.xvisibility.state);
break;
}
break;
case PropertyNotify:
if (ev.xproperty.atom == ATOM__XROOTPMAP_ID) {
w->bg_changed = true;
}
break;
default: break;
}
}
process_events(w);
}
static void get_fbsize(struct glxwin* w, int* d, int* h) {
@@ -562,6 +566,7 @@ static void destroy(struct glxwin* w) {
glXMakeCurrent(display, None, NULL); /* release context */
glXDestroyContext(display, w->context);
XDestroyWindow(display, w->w);
free(w);
}
static void terminate(void) {

View File

@@ -69,6 +69,12 @@ struct gl_sampler_data {
size_t sz;
};
/* per-bind data containing the framebuffer and 1D texture to render for smoothing. */
struct sm_fb {
GLuint fbo, tex;
};
/* GLSL uniform bind */
struct gl_bind {
@@ -78,7 +84,7 @@ struct gl_bind {
int src_type;
void (**transformations)(struct gl_data*, void**, void* data);
size_t t_sz;
void* udata;
struct sm_fb sm;
};
/* GL screen framebuffer object */
@@ -112,6 +118,7 @@ struct gl_data {
copy_desktop, smooth_pass, premultiply_alpha, check_fullscreen,
clickthrough;
void** t_data;
size_t t_count;
float gravity_step, target_spu, fr, ur, smooth_distance, smooth_ratio,
smooth_factor, fft_scale, fft_cutoff;
struct {
@@ -465,10 +472,9 @@ static struct gl_bind_src bind_sources[] = {
};
#define window(t, sz) (0.53836 - (0.46164 * cos(TWOPI * (double) t / (double)(sz - 1))))
#define ALLOC_ONCE(u, udata, ...) \
#define ALLOC_ONCE(u, udata, sz) \
if (*udata == NULL) { \
u = malloc(sizeof(*u)); \
*u = (typeof(*u)) __VA_ARGS__; \
u = calloc(sz, sizeof(typeof(*u))); \
*udata = u; \
} else u = (typeof(u)) *udata;
@@ -529,18 +535,16 @@ void transform_gravity(struct gl_data* d, void** udata, void* data) {
float* b = s->buf;
size_t sz = s->sz, t;
struct {
float* applied;
}* u;
ALLOC_ONCE(u, udata, { .applied = calloc(sz, sizeof(float)) });
float* applied;
ALLOC_ONCE(applied, udata, sz);
float g = d->gravity_step * (1.0F / d->ur);
for (t = 0; t < sz; ++t) {
if (b[t] >= u->applied[t]) {
u->applied[t] = b[t] - g;
} else u->applied[t] -= g;
b[t] = u->applied[t];
if (b[t] >= applied[t]) {
applied[t] = b[t] - g;
} else applied[t] -= g;
b[t] = applied[t];
}
}
@@ -553,20 +557,18 @@ void transform_average(struct gl_data* d, void** udata, void* data) {
float v;
bool use_window = d->avg_window;
struct {
float* bufs;
}* u;
ALLOC_ONCE(u, udata, { .bufs = calloc(tsz, sizeof(float)) });
float* bufs;
ALLOC_ONCE(bufs, udata, tsz);
memmove(u->bufs, &u->bufs[sz], (tsz - sz) * sizeof(float));
memcpy(&u->bufs[tsz - sz], b, sz * sizeof(float));
memmove(bufs, &bufs[sz], (tsz - sz) * sizeof(float));
memcpy(&bufs[tsz - sz], b, sz * sizeof(float));
#define DO_AVG(w) \
do { \
for (t = 0; t < sz; ++t) { \
v = 0.0F; \
for (f = 0; f < d->avg_frames; ++f) { \
v += w * u->bufs[(f * sz) + t]; \
v += w * bufs[(f * sz) + t]; \
} \
b[t] = v / d->avg_frames; \
} \
@@ -1038,7 +1040,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
.src_type = src->src_type,
.transformations = malloc(1),
.t_sz = 0,
.udata = NULL
.sm = {}
};
})
},
@@ -1091,6 +1093,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
};
ext_process(&ext, se_buf);
ext_free(&ext);
munmap((void*) map, st.st_size);
@@ -1122,6 +1125,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
loading_presets = true;
ext_process(&ext, se_buf);
ext_free(&ext);
loading_presets = false;
munmap((void*) map, st.st_size);
@@ -1319,7 +1323,8 @@ struct renderer* rd_new(const char** paths, const char* entry,
}
{
gl->t_data = malloc(sizeof(void*) * t_count);
gl->t_data = malloc(sizeof(void*) * t_count);
gl->t_count = t_count;
size_t t;
for (t = 0; t < t_count; ++t) {
gl->t_data[t] = NULL;
@@ -1544,20 +1549,10 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
setup = true;
}
/* Per-bind data containing the framebuffer and 1D texture to render to for
this smoothing step. */
struct sm_fb {
GLuint fbo, tex;
};
/* Allocate and setup our per-bind data, if needed */
struct sm_fb* sm;
if (!bind->udata) {
sm = malloc(sizeof(struct sm_fb));
bind->udata = sm;
struct sm_fb* sm = &bind->sm;
if (sm->tex == 0) {
glGenTextures(1, &sm->tex);
glGenFramebuffers(1, &sm->fbo);
@@ -1582,7 +1577,6 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
}
} else {
/* Just bind our data if it was already allocated and setup */
sm = (struct sm_fb*) bind->udata;
glBindFramebuffer(GL_FRAMEBUFFER, sm->fbo);
glBindTexture(GL_TEXTURE_1D, sm->tex);
}
@@ -1716,8 +1710,14 @@ struct gl_wcb* rd_get_wcb (struct renderer* r) { return r->gl->wcb; }
void rd_destroy(struct renderer* r) {
r->gl->wcb->destroy(r->gl->w);
if (r->gl->interpolate) free(r->gl->interpolate_buf[0]);
if (r->gl->t_data) free(r->gl->t_data);
size_t t, b;
if (r->gl->t_data) {
for (t = 0; t < r->gl->t_count; ++t) {
if (r->gl->t_data[t])
free(r->gl->t_data[t]);
}
free(r->gl->t_data);
}
for (t = 0; t < r->gl->stages_sz; ++t) {
struct gl_sfbo* stage = &r->gl->stages[t];
for (b = 0; b < stage->binds_sz; ++b) {