Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c99124556 | ||
|
|
9d1c3a177c |
50
glsl_ext.c
50
glsl_ext.c
@@ -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);
|
||||
}
|
||||
|
||||
14
glsl_ext.h
14
glsl_ext.h
@@ -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 */
|
||||
|
||||
73
glx_wcb.c
73
glx_wcb.c
@@ -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) {
|
||||
|
||||
70
render.c
70
render.c
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user