From d28ceb85a6b43a503c608116798945baab0e060f Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sat, 22 Apr 2017 15:29:49 -0700 Subject: *: add module context machinery introduces create_context() and destroy_context() methods, and adds a 'void *context' first parameter to the module methods. If a module doesn't supply create_context() then NULL is simply passed around as the context, so trivial modules can continue to only implement render_fragment(). A subsequent commit will update the modules to encapsulate their global state in module-specific contexts. --- src/modules/julia/julia.c | 4 ++-- src/modules/plasma/plasma.c | 4 ++-- src/modules/ray/ray.c | 4 ++-- src/modules/roto/roto.c | 6 +++--- src/modules/sparkler/sparkler.c | 2 +- src/modules/stars/stars.c | 2 +- src/rototiller.c | 23 ++++++++++++++++------- src/rototiller.h | 6 ++++-- src/threads.c | 12 +++++++----- src/threads.h | 2 +- 10 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/modules/julia/julia.c b/src/modules/julia/julia.c index 69d1022..3811d0d 100644 --- a/src/modules/julia/julia.c +++ b/src/modules/julia/julia.c @@ -42,7 +42,7 @@ static inline unsigned julia_iter(float real, float imag, float creal, float cim /* Prepare a frame for concurrent drawing of fragment using multiple fragments */ -static void julia_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) +static void julia_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) { res_frame->n_fragments = n_cpus; fb_fragment_divide(fragment, n_cpus, res_frame->fragments); @@ -59,7 +59,7 @@ static void julia_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rototi /* Draw a morphing Julia set */ -static void julia_render_fragment(fb_fragment_t *fragment) +static void julia_render_fragment(void *context, fb_fragment_t *fragment) { static uint32_t colors[] = { /* this palette is just something I slapped together, definitely needs improvement. TODO */ diff --git a/src/modules/plasma/plasma.c b/src/modules/plasma/plasma.c index 8c3e921..9acd73f 100644 --- a/src/modules/plasma/plasma.c +++ b/src/modules/plasma/plasma.c @@ -43,7 +43,7 @@ static void init_plasma(int32_t *costab, int32_t *sintab) /* Prepare a frame for concurrent drawing of fragment using multiple fragments */ -static void plasma_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) +static void plasma_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) { static int initialized; @@ -61,7 +61,7 @@ static void plasma_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rotot /* Draw a plasma effect */ -static void plasma_render_fragment(fb_fragment_t *fragment) +static void plasma_render_fragment(void *context, fb_fragment_t *fragment) { unsigned stride = fragment->stride / 4, width = fragment->width, height = fragment->height; diff --git a/src/modules/ray/ray.c b/src/modules/ray/ray.c index e79bfaf..a934c30 100644 --- a/src/modules/ray/ray.c +++ b/src/modules/ray/ray.c @@ -112,7 +112,7 @@ static float r; /* prepare a frame for concurrent rendering */ -static void ray_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) +static void ray_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) { /* TODO experiment with tiled fragments vs. rows */ res_frame->n_fragments = n_cpus; @@ -146,7 +146,7 @@ static void ray_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rototill /* ray trace a simple scene into the fragment */ -static void ray_render_fragment(fb_fragment_t *fragment) +static void ray_render_fragment(void *context, fb_fragment_t *fragment) { ray_scene_render_fragment(&scene, &camera, fragment); } diff --git a/src/modules/roto/roto.c b/src/modules/roto/roto.c index b889a55..9c7ac18 100644 --- a/src/modules/roto/roto.c +++ b/src/modules/roto/roto.c @@ -154,7 +154,7 @@ static void init_roto(uint8_t texture[256][256], int32_t *costab, int32_t *sinta /* prepare a frame for concurrent rendering */ -static void roto_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) +static void roto_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame) { static int initialized; @@ -174,7 +174,7 @@ static void roto_prepare_frame(unsigned n_cpus, fb_fragment_t *fragment, rototil /* Draw a rotating checkered 256x256 texture into fragment. (32-bit version) */ -static void roto32_render_fragment(fb_fragment_t *fragment) +static void roto32_render_fragment(void *context, fb_fragment_t *fragment) { int y_cos_r, y_sin_r, x_cos_r, x_sin_r, x_cos_r_init, x_sin_r_init, cos_r, sin_r; int x, y, stride = fragment->stride / 4, frame_width = fragment->frame_width, frame_height = fragment->frame_height; @@ -223,7 +223,7 @@ static void roto32_render_fragment(fb_fragment_t *fragment) /* Draw a rotating checkered 256x256 texture into fragment. (64-bit version) */ -static void roto64_render_fragment(fb_fragment_t *fragment) +static void roto64_render_fragment(void *context, fb_fragment_t *fragment) { int y_cos_r, y_sin_r, x_cos_r, x_sin_r, x_cos_r_init, x_sin_r_init, cos_r, sin_r; int x, y, stride = fragment->stride / 8, frame_width = fragment->frame_width, frame_height = fragment->frame_height, width = fragment->width; diff --git a/src/modules/sparkler/sparkler.c b/src/modules/sparkler/sparkler.c index 67d68cf..deb3c53 100644 --- a/src/modules/sparkler/sparkler.c +++ b/src/modules/sparkler/sparkler.c @@ -20,7 +20,7 @@ extern particle_ops_t simple_ops; /* Render a 3D particle system */ -static void sparkler_render_fragment(fb_fragment_t *fragment) +static void sparkler_render_fragment(void *context, fb_fragment_t *fragment) { static particles_t *particles; static int initialized; diff --git a/src/modules/stars/stars.c b/src/modules/stars/stars.c index f624a62..3712e33 100644 --- a/src/modules/stars/stars.c +++ b/src/modules/stars/stars.c @@ -13,7 +13,7 @@ /* Copyright (C) 2017 Philip J. Freeman */ -static void stars_render_fragment(fb_fragment_t *fragment) +static void stars_render_fragment(void *context, fb_fragment_t *fragment) { static int initialized, z; static struct universe* u; diff --git a/src/rototiller.c b/src/rototiller.c index f9cfece..4d84c91 100644 --- a/src/rototiller.c +++ b/src/rototiller.c @@ -57,24 +57,24 @@ static void module_select(int *module) } -static void module_render_page_threaded(rototiller_module_t *module, threads_t *threads, fb_page_t *page) +static void module_render_page_threaded(rototiller_module_t *module, void *context, threads_t *threads, fb_page_t *page) { rototiller_frame_t frame; unsigned i; - module->prepare_frame(threads_num_threads(threads), &page->fragment, &frame); + module->prepare_frame(context, threads_num_threads(threads), &page->fragment, &frame); - threads_frame_submit(threads, &frame, module->render_fragment); + threads_frame_submit(threads, &frame, module->render_fragment, context); threads_wait_idle(threads); } -static void module_render_page(rototiller_module_t *module, threads_t *threads, fb_page_t *page) +static void module_render_page(rototiller_module_t *module, void *context, threads_t *threads, fb_page_t *page) { if (!module->prepare_frame) - return module->render_fragment(&page->fragment); + return module->render_fragment(context, &page->fragment); - module_render_page_threaded(module, threads, page); + module_render_page_threaded(module, context, threads, page); } @@ -87,6 +87,7 @@ int main(int argc, const char *argv[]) threads_t *threads; int module; fb_t *fb; + void *context = NULL; drm_setup(&drm_fd, &drm_crtc_id, &drm_connector_id, &drm_mode); module_select(&module); @@ -97,6 +98,10 @@ int main(int argc, const char *argv[]) pexit_if(!fps_setup(), "unable to setup fps counter"); + exit_if(modules[module]->create_context && + !(context = modules[module]->create_context()), + "unable to create module context"); + pexit_if(!(threads = threads_create()), "unable to create threads"); @@ -106,11 +111,15 @@ int main(int argc, const char *argv[]) fps_print(fb); page = fb_page_get(fb); - module_render_page(modules[module], threads, page); + module_render_page(modules[module], context, threads, page); fb_page_put(fb, page); } threads_destroy(threads); + + if (context) + modules[module]->destroy_context(context); + fb_free(fb); close(drm_fd); diff --git a/src/rototiller.h b/src/rototiller.h index d1578fb..933f733 100644 --- a/src/rototiller.h +++ b/src/rototiller.h @@ -12,8 +12,10 @@ typedef struct rototiller_frame_t { } rototiller_frame_t; typedef struct rototiller_module_t { - void (*prepare_frame)(unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame); - void (*render_fragment)(fb_fragment_t *fragment); + void * (*create_context)(void); + void (*destroy_context)(void *context); + void (*prepare_frame)(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_frame_t *res_frame); + void (*render_fragment)(void *context, fb_fragment_t *fragment); char *name; char *description; char *author; diff --git a/src/threads.c b/src/threads.c index cc32f63..865fe21 100644 --- a/src/threads.c +++ b/src/threads.c @@ -24,7 +24,8 @@ typedef struct thread_t { pthread_t thread; pthread_mutex_t mutex; pthread_cond_t cond; - void (*render_fragment_func)(fb_fragment_t *fragment); + void (*render_fragment_func)(void *context, fb_fragment_t *fragment); + void *context; fragment_node_t *fragments; } thread_t; @@ -46,7 +47,7 @@ static void * thread_func(void *_thread) pthread_cond_wait(&thread->cond, &thread->mutex); do { - thread->render_fragment_func(thread->fragments->fragment); + thread->render_fragment_func(thread->context, thread->fragments->fragment); thread->fragments = thread->fragments->next; } while (thread->fragments); @@ -59,13 +60,14 @@ static void * thread_func(void *_thread) /* submit a list of fragments to render using the specified thread and render_fragment_func */ -static void thread_fragments_submit(thread_t *thread, void (*render_fragment_func)(fb_fragment_t *fragment), fragment_node_t *fragments) +static void thread_fragments_submit(thread_t *thread, void (*render_fragment_func)(void *context, fb_fragment_t *fragment), void *context, fragment_node_t *fragments) { pthread_mutex_lock(&thread->mutex); while (thread->fragments != NULL) /* XXX: never true due to thread_wait_idle() */ pthread_cond_wait(&thread->cond, &thread->mutex); thread->render_fragment_func = render_fragment_func; + thread->context = context; thread->fragments = fragments; pthread_mutex_unlock(&thread->mutex); @@ -84,7 +86,7 @@ static void thread_wait_idle(thread_t *thread) /* submit a frame's fragments to the threads */ -void threads_frame_submit(threads_t *threads, rototiller_frame_t *frame, void (*render_fragment_func)(fb_fragment_t *fragment)) +void threads_frame_submit(threads_t *threads, rototiller_frame_t *frame, void (*render_fragment_func)(void *context, fb_fragment_t *fragment), void *context) { unsigned i, t; fragment_node_t *lists[threads->n_threads]; @@ -103,7 +105,7 @@ void threads_frame_submit(threads_t *threads, rototiller_frame_t *frame, void (* } for (i = 0; i < threads->n_threads; i++) - thread_fragments_submit(&threads->threads[i], render_fragment_func, lists[i]); + thread_fragments_submit(&threads->threads[i], render_fragment_func, context, lists[i]); } diff --git a/src/threads.h b/src/threads.h index 5926328..f7eec81 100644 --- a/src/threads.h +++ b/src/threads.h @@ -11,7 +11,7 @@ typedef struct threads_t threads_t; threads_t * threads_create(); void threads_destroy(threads_t *threads); -void threads_frame_submit(threads_t *threads, rototiller_frame_t *frame, void (*render_fragment_func)(fb_fragment_t *fragment)); +void threads_frame_submit(threads_t *threads, rototiller_frame_t *frame, void (*render_fragment_func)(void *context, fb_fragment_t *fragment), void *context); void threads_wait_idle(threads_t *threads); unsigned threads_num_threads(threads_t *threads); -- cgit v1.2.1