Added graceful renderer and audio thread destruction, fixes #47
This commit is contained in:
7
glava.c
7
glava.c
@@ -292,5 +292,12 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
audio.terminate = 1;
|
||||||
|
int return_status;
|
||||||
|
if ((return_status = pthread_join(thread, NULL))) {
|
||||||
|
fprintf(stderr, "Failed to join with audio thread: %s\n", strerror(return_status));
|
||||||
|
}
|
||||||
|
|
||||||
|
free(audio.source);
|
||||||
rd_destroy(r);
|
rd_destroy(r);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,6 +134,8 @@ static double get_time (GLFWwindow* w) { return glfwGetT
|
|||||||
static void set_time (GLFWwindow* w, double time) { glfwSetTime(time); }
|
static void set_time (GLFWwindow* w, double time) { glfwSetTime(time); }
|
||||||
static void set_swap (int i) { glfwSwapInterval(i); }
|
static void set_swap (int i) { glfwSwapInterval(i); }
|
||||||
static void raise (GLFWwindow* w) { glfwShowWindow(w); }
|
static void raise (GLFWwindow* w) { glfwShowWindow(w); }
|
||||||
|
static void destroy (GLFWwindow* w) { glfwDestroyWindow(w); }
|
||||||
|
static void terminate (void) { glfwTerminate(); }
|
||||||
|
|
||||||
static const char* get_environment(void) { return xwin_detect_wm(&wcb_glfw); }
|
static const char* get_environment(void) { return xwin_detect_wm(&wcb_glfw); }
|
||||||
|
|
||||||
|
|||||||
12
glx_wcb.c
12
glx_wcb.c
@@ -160,6 +160,7 @@ Bool (*glXMakeCurrent) (Display* dpy, GLXDrawable drawable,
|
|||||||
GLXDrawable (*glXGetCurrentDrawable) (void);
|
GLXDrawable (*glXGetCurrentDrawable) (void);
|
||||||
__GLXextFuncPtr (*glXGetProcAddressARB) (const GLubyte *);
|
__GLXextFuncPtr (*glXGetProcAddressARB) (const GLubyte *);
|
||||||
void (*glXSwapBuffers) (Display* dpy, GLXDrawable drawable);
|
void (*glXSwapBuffers) (Display* dpy, GLXDrawable drawable);
|
||||||
|
void (*glXDestroyContext) (Display* dpy, GLXContext ctx);
|
||||||
|
|
||||||
extern struct gl_wcb wcb_glx;
|
extern struct gl_wcb wcb_glx;
|
||||||
|
|
||||||
@@ -222,6 +223,7 @@ static void init(void) {
|
|||||||
resolve(glXGetCurrentDrawable);
|
resolve(glXGetCurrentDrawable);
|
||||||
resolve(glXGetProcAddressARB);
|
resolve(glXGetProcAddressARB);
|
||||||
resolve(glXSwapBuffers);
|
resolve(glXSwapBuffers);
|
||||||
|
resolve(glXDestroyContext);
|
||||||
|
|
||||||
intern(_MOTIF_WM_HINTS, false);
|
intern(_MOTIF_WM_HINTS, false);
|
||||||
intern(WM_DELETE_WINDOW, true);
|
intern(WM_DELETE_WINDOW, true);
|
||||||
@@ -481,6 +483,16 @@ static double get_timert(void) {
|
|||||||
return (double) tv.tv_sec + ((double) tv.tv_nsec / 1000000000.0D);
|
return (double) tv.tv_sec + ((double) tv.tv_nsec / 1000000000.0D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void destroy(struct glxwin* w) {
|
||||||
|
glXMakeCurrent(display, None, NULL); /* release context */
|
||||||
|
glXDestroyContext(display, w->context);
|
||||||
|
XDestroyWindow(display, w->w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void terminate(void) {
|
||||||
|
XCloseDisplay(display);
|
||||||
|
}
|
||||||
|
|
||||||
static double get_time (struct glxwin* w) { return get_timert() - w->time; }
|
static double get_time (struct glxwin* w) { return get_timert() - w->time; }
|
||||||
static void set_time (struct glxwin* w, double time) { w->time = get_timert() - time; }
|
static void set_time (struct glxwin* w, double time) { w->time = get_timert() - time; }
|
||||||
static Display* get_x11_display(struct glxwin* w) { return display; }
|
static Display* get_x11_display(struct glxwin* w) { return display; }
|
||||||
|
|||||||
36
render.c
36
render.c
@@ -791,7 +791,8 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
context_version_major = 3,
|
context_version_major = 3,
|
||||||
context_version_minor = 3;
|
context_version_minor = 3;
|
||||||
const char* module = force_mod;
|
const char* module = force_mod;
|
||||||
char* xwintype = NULL, * wintitle = "GLava";
|
const char* wintitle_default = "GLava";
|
||||||
|
char* xwintype = NULL, * wintitle = (char*) wintitle_default;
|
||||||
char** xwinstates = malloc(1);
|
char** xwinstates = malloc(1);
|
||||||
size_t xwinstates_sz = 0;
|
size_t xwinstates_sz = 0;
|
||||||
bool loading_module = true, loading_smooth_pass = false, loading_presets = false;;
|
bool loading_module = true, loading_smooth_pass = false, loading_presets = false;;
|
||||||
@@ -860,6 +861,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
.name = "mod", .fmt = "s",
|
.name = "mod", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, {
|
.handler = RHANDLER(name, args, {
|
||||||
if (loading_module && !force_mod) {
|
if (loading_module && !force_mod) {
|
||||||
|
if (module != NULL && module != force_mod) free((char*) module);
|
||||||
size_t len = strlen((char*) args[0]);
|
size_t len = strlen((char*) args[0]);
|
||||||
char* str = malloc(sizeof(char) * (len + 1));
|
char* str = malloc(sizeof(char) * (len + 1));
|
||||||
strncpy(str, (char*) args[0], len + 1);
|
strncpy(str, (char*) args[0], len + 1);
|
||||||
@@ -910,6 +912,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
},
|
},
|
||||||
{ .name = "setsource", .fmt = "s",
|
{ .name = "setsource", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, {
|
.handler = RHANDLER(name, args, {
|
||||||
|
if (r->audio_source_request) free(r->audio_source_request);
|
||||||
r->audio_source_request = strdup((char*) args[0]); }) },
|
r->audio_source_request = strdup((char*) args[0]); }) },
|
||||||
{ .name = "setclickthrough", .fmt = "b",
|
{ .name = "setclickthrough", .fmt = "b",
|
||||||
.handler = RHANDLER(name, args, { gl->clickthrough = *(bool*) args[0]; }) },
|
.handler = RHANDLER(name, args, { gl->clickthrough = *(bool*) args[0]; }) },
|
||||||
@@ -918,7 +921,9 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
{ .name = "setforceraised", .fmt = "b",
|
{ .name = "setforceraised", .fmt = "b",
|
||||||
.handler = RHANDLER(name, args, { gl->force_raised = *(bool*) args[0]; }) },
|
.handler = RHANDLER(name, args, { gl->force_raised = *(bool*) args[0]; }) },
|
||||||
{ .name = "setxwintype", .fmt = "s",
|
{ .name = "setxwintype", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, { xwintype = strdup((char*) args[0]); }) },
|
.handler = RHANDLER(name, args, {
|
||||||
|
if (xwintype) free(xwintype);
|
||||||
|
xwintype = strdup((char*) args[0]); }) },
|
||||||
{ .name = "setshaderversion", .fmt = "i",
|
{ .name = "setshaderversion", .fmt = "i",
|
||||||
.handler = RHANDLER(name, args, { shader_version = *(int*) args[0]; }) },
|
.handler = RHANDLER(name, args, { shader_version = *(int*) args[0]; }) },
|
||||||
{ .name = "setswap", .fmt = "i",
|
{ .name = "setswap", .fmt = "i",
|
||||||
@@ -928,7 +933,9 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
{ .name = "setprintframes", .fmt = "b",
|
{ .name = "setprintframes", .fmt = "b",
|
||||||
.handler = RHANDLER(name, args, { gl->print_fps = *(bool*) args[0]; }) },
|
.handler = RHANDLER(name, args, { gl->print_fps = *(bool*) args[0]; }) },
|
||||||
{ .name = "settitle", .fmt = "s",
|
{ .name = "settitle", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, { wintitle = strdup((char*) args[0]); }) },
|
.handler = RHANDLER(name, args, {
|
||||||
|
if (wintitle && wintitle != wintitle_default) free((char*) wintitle);
|
||||||
|
wintitle = strdup((char*) args[0]); }) },
|
||||||
{ .name = "setbufsize", .fmt = "i",
|
{ .name = "setbufsize", .fmt = "i",
|
||||||
.handler = RHANDLER(name, args, { r->bufsize_request = *(int*) args[0]; }) },
|
.handler = RHANDLER(name, args, { r->bufsize_request = *(int*) args[0]; }) },
|
||||||
{ .name = "setbufscale", .fmt = "i",
|
{ .name = "setbufscale", .fmt = "i",
|
||||||
@@ -1138,9 +1145,13 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
gl->geometry[2], gl->geometry[3], gl->geometry[0], gl->geometry[1],
|
gl->geometry[2], gl->geometry[3], gl->geometry[0], gl->geometry[1],
|
||||||
context_version_major, context_version_minor, gl->clickthrough);
|
context_version_major, context_version_minor, gl->clickthrough);
|
||||||
if (!gl->w) abort();
|
if (!gl->w) abort();
|
||||||
|
|
||||||
|
for (size_t t = 0; t < xwinstates_sz; ++t)
|
||||||
|
free(xwinstates[t]);
|
||||||
|
|
||||||
if (xwintype) free(xwintype);
|
if (xwintype) free(xwintype);
|
||||||
if (xwinstates) free(xwinstates);
|
if (xwinstates) free(xwinstates);
|
||||||
|
if (wintitle && wintitle != wintitle_default) free(wintitle);
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_DEPTH_CLAMP);
|
glDisable(GL_DEPTH_CLAMP);
|
||||||
@@ -1698,7 +1709,24 @@ 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; }
|
struct gl_wcb* rd_get_wcb (struct renderer* r) { return r->gl->wcb; }
|
||||||
|
|
||||||
void rd_destroy(struct renderer* r) {
|
void rd_destroy(struct renderer* r) {
|
||||||
/* TODO: delete everything else, not really needed though (as the application exits after here) */
|
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;
|
||||||
|
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) {
|
||||||
|
struct gl_bind* bind = &stage->binds[b];
|
||||||
|
free(bind->transformations);
|
||||||
|
free((char*) bind->name); /* strdup */
|
||||||
|
}
|
||||||
|
free(stage->binds);
|
||||||
|
free((char*) stage->name); /* strdup */
|
||||||
|
}
|
||||||
|
free(r->gl->stages);
|
||||||
|
r->gl->wcb->terminate();
|
||||||
free(r->gl);
|
free(r->gl);
|
||||||
|
if (r->audio_source_request)
|
||||||
|
free(r->audio_source_request);
|
||||||
free(r);
|
free(r);
|
||||||
}
|
}
|
||||||
|
|||||||
4
render.h
4
render.h
@@ -35,6 +35,8 @@ struct gl_wcb {
|
|||||||
bool (*should_close) (void* ptr);
|
bool (*should_close) (void* ptr);
|
||||||
void (*swap_buffers) (void* ptr);
|
void (*swap_buffers) (void* ptr);
|
||||||
void (*raise) (void* ptr);
|
void (*raise) (void* ptr);
|
||||||
|
void (*destroy) (void* ptr);
|
||||||
|
void (*terminate) (void);
|
||||||
void (*get_pos) (void* ptr, int* x, int* y);
|
void (*get_pos) (void* ptr, int* x, int* y);
|
||||||
void (*get_fbsize) (void* ptr, int* w, int* h);
|
void (*get_fbsize) (void* ptr, int* w, int* h);
|
||||||
void (*set_geometry) (void* ptr, int x, int y, int w, int h);
|
void (*set_geometry) (void* ptr, int x, int y, int w, int h);
|
||||||
@@ -68,6 +70,8 @@ struct gl_wcb {
|
|||||||
WCB_FUNC(should_close), \
|
WCB_FUNC(should_close), \
|
||||||
WCB_FUNC(swap_buffers), \
|
WCB_FUNC(swap_buffers), \
|
||||||
WCB_FUNC(raise), \
|
WCB_FUNC(raise), \
|
||||||
|
WCB_FUNC(destroy), \
|
||||||
|
WCB_FUNC(terminate), \
|
||||||
WCB_FUNC(set_swap), \
|
WCB_FUNC(set_swap), \
|
||||||
WCB_FUNC(get_pos), \
|
WCB_FUNC(get_pos), \
|
||||||
WCB_FUNC(get_fbsize), \
|
WCB_FUNC(get_fbsize), \
|
||||||
|
|||||||
Reference in New Issue
Block a user