X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=liberebus%2Fsrc%2Ferebus.c;h=dbc253bee2003dcb6643d82348a133d57e49403d;hb=d4eaf9f47882dc99d6523b8464dcaa1cc2789f26;hp=af2b2d9df078d2298a35e693a6e5f8521b6a53ad;hpb=399df0323dcd1cafe860565fd82598321aff52ee;p=erebus2020 diff --git a/liberebus/src/erebus.c b/liberebus/src/erebus.c index af2b2d9..dbc253b 100644 --- a/liberebus/src/erebus.c +++ b/liberebus/src/erebus.c @@ -1,16 +1,37 @@ #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; + int fb_width, fb_height, fb_size; float *fb_pixels; - 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; } @@ -27,36 +48,25 @@ void erb_destroy(struct erb_rend *erb) int erb_allocframe(struct erb_rend *erb, int width, int height) { float *newfb; - int *newns; - int npix; + int sz; if(width == erb->fb_width && height == erb->fb_height) { return 0; } - npix = width * height; - - if(!(newfb = malloc(npix * 3 * sizeof *erb->fb_pixels))) { - goto err; - } - if(!(newns = malloc(npix * sizeof *erb->fb_nsamples))) { - free(newfb); - goto err; + sz = width * height * 4 * sizeof *erb->fb_pixels; + if(!(newfb = malloc(sz))) { + fprintf(stderr, "erb_allocframe: failed to allocate %dx%d framebuffer\n", width, height); + return -1; } free(erb->fb_pixels); - free(erb->fb_nsamples); erb->fb_pixels = newfb; - erb->fb_nsamples = newns; erb->fb_width = width; erb->fb_height = height; - erb->fb_npix = npix; + erb->fb_size = sz; return 0; - -err: - fprintf(stderr, "erb_allocframe: failed to allocate %dx%d framebuffer\n", width, height); - return -1; } float *erb_getframe(struct erb_rend *erb) @@ -66,30 +76,128 @@ float *erb_getframe(struct erb_rend *erb) void erb_begin(struct erb_rend *erb) { - memset(erb->fb_pixels, 0, erb->fb_npix * 3 * sizeof *erb->fb_pixels); - memset(erb->fb_nsamples, 0, erb->fb_npix * sizeof *erb->fb_nsamples); + memset(erb->fb_pixels, 0, erb->fb_size); } float *erb_end(struct erb_rend *erb) { - int i, n; + int i, npix = erb->fb_width * erb->fb_height; float s; float *pptr = erb->fb_pixels; - int *nptr = erb->fb_nsamples; - for(i=0; ifb_npix; i++) { - n = *nptr; - if(n > 1) { - s = 1.0f / n; + for(i=0; i 1) { + s = 1.0f / pptr[3]; *pptr++ *= s; *pptr++ *= s; *pptr++ *= s; - *nptr++ = 1; + *pptr++ = 1.0f; } else { - pptr += 3; - nptr++; + pptr += 4; } } 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; + struct erb_ray ray; + + erb = job->erb; + fboffs = job->y * erb->fb_width + job->x; + fbptr = erb->fb_pixels + fboffs * 4; + + for(i=0; iheight; i++) { + for(j=0; jwidth; j++) { + erb_primary_ray(erb, &ray, (int)fbptr[3]); + erb_sample_ray(erb, &ray, fbptr); + fbptr += 4; + } + fbptr += (erb->fb_width - job->width) * 4; + } + 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); +}