X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=erebus2020;a=blobdiff_plain;f=liberebus%2Fsrc%2Ferebus.c;h=32af87be9a749f512208a3143f48cb905610c87a;hp=af2b2d9df078d2298a35e693a6e5f8521b6a53ad;hb=c70b7e63be9882e589a17b457900b05aca96ebb9;hpb=399df0323dcd1cafe860565fd82598321aff52ee diff --git a/liberebus/src/erebus.c b/liberebus/src/erebus.c index af2b2d9..32af87b 100644 --- a/liberebus/src/erebus.c +++ b/liberebus/src/erebus.c @@ -1,5 +1,13 @@ #include +#include #include "erebus.h" +#include "tpool.h" + +struct render_job { + struct erb_rend *erb; + int x, y, width, height; + struct render_job *next; +}; struct erb_rend { int fb_width, fb_height, fb_npix; @@ -7,10 +15,24 @@ struct erb_rend { int *fb_nsamples; }; +static void proc_render_job(void *cls); +static struct render_job *alloc_job(void); +static void free_job(struct render_job *job); + +static struct thread_pool *tpool; + + struct erb_rend *erb_create(void) { struct erb_rend *erb; + if(!tpool) { + if(!(tpool = tpool_create(0))) { + fprintf(stderr, "erb_create: fatal error, failed to create thread pool!\n"); + return 0; + } + } + if(!(erb = calloc(1, sizeof *erb))) { return 0; } @@ -93,3 +115,106 @@ float *erb_end(struct erb_rend *erb) return erb->fb_pixels; } + +void erb_queue_frame(struct erb_rend *erb) +{ + erb_queue_block(erb, 0, 0, erb->fb_width, erb->fb_height); +} + +void erb_queue_block(struct erb_rend *erb, int x, int y, int width, int height) +{ + struct render_job *job; + + if(!(job = alloc_job())) { + fprintf(stderr, "erb_queue_block: failed to allocate rendering job\n"); + return; + } + + job->erb = erb; + job->x = x; + job->y = y; + job->width = width; + job->height = height; + + tpool_enqueue(tpool, job, proc_render_job, 0); +} + +void erb_wait(struct erb_rend *erb) +{ + /* XXX should we have a per-renderer instance thread pool, to wait only for our own jobs? */ + tpool_wait(tpool); +} + +void erb_primary_ray(struct erb_rend *erb, struct erb_ray *ray, int sample) +{ + /* TODO */ +} + +void erb_sample_ray(struct erb_rend *erb, struct erb_ray *ray, float *col) +{ + /* TODO */ + col[0] = fmod(col[0] + 1.0f, 1.0f); + col[1] = col[2] = fmod(col[1] + 0.33f, 1.0f); +} + +static void proc_render_job(void *cls) +{ + int i, j, fboffs; + struct erb_rend *erb; + struct render_job *job = cls; + float *fbptr; + int *nsptr; + struct erb_ray ray; + + erb = job->erb; + fboffs = job->y * erb->fb_width + job->x; + fbptr = erb->fb_pixels + fboffs * 3; + nsptr = erb->fb_nsamples + fboffs; + + for(i=0; iheight; i++) { + for(j=0; jwidth; j++) { + erb_primary_ray(erb, &ray, *nsptr++); + erb_sample_ray(erb, &ray, fbptr); + fbptr += 3; + } + } + free_job(job); +} + + +#define MAX_JOB_POOL 128 +static struct render_job *job_pool; +static int num_free_jobs; +static pthread_mutex_t job_pool_lock = PTHREAD_MUTEX_INITIALIZER; + +static struct render_job *alloc_job(void) +{ + struct render_job *job; + + pthread_mutex_lock(&job_pool_lock); + if(!job_pool) { + pthread_mutex_unlock(&job_pool_lock); + return malloc(sizeof *job); + } + + job = job_pool; + job_pool = job->next; + num_free_jobs--; + pthread_mutex_unlock(&job_pool_lock); + return job; +} + +static void free_job(struct render_job *job) +{ + pthread_mutex_lock(&job_pool_lock); + if(num_free_jobs >= MAX_JOB_POOL) { + pthread_mutex_unlock(&job_pool_lock); + free(job); + return; + } + + job->next = job_pool; + job_pool = job; + num_free_jobs++; + pthread_mutex_unlock(&job_pool_lock); +}