working on the transformation node system
[erebus2020] / liberebus / src / erebus.c
index 32af87b..de8598f 100644 (file)
@@ -5,17 +5,23 @@
 
 struct render_job {
        struct erb_rend *erb;
-       int x, y, width, height;
+       unsigned int id;
+       struct erb_rect rect;
        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;
+
+       erb_done_func donecb;
+       void *donecls;
+
+       float vfov;
 };
 
 static void proc_render_job(void *cls);
+static void done_render_job(void *cls);
 static struct render_job *alloc_job(void);
 static void free_job(struct render_job *job);
 
@@ -36,6 +42,9 @@ struct erb_rend *erb_create(void)
        if(!(erb = calloc(1, sizeof *erb))) {
                return 0;
        }
+
+       erb->vfov = cgm_deg_to_rad(50.0f);
+
        return erb;
 }
 
@@ -49,36 +58,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)
@@ -86,42 +84,50 @@ float *erb_getframe(struct erb_rend *erb)
        return erb->fb_pixels;
 }
 
+void erb_setfov(struct erb_rend *erb, float vfov_deg)
+{
+       erb->vfov = cgm_deg_to_rad(vfov_deg);
+}
+
 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; i<erb->fb_npix; i++) {
-               n = *nptr;
-               if(n > 1) {
-                       s = 1.0f / n;
+       for(i=0; i<npix; i++) {
+               if(pptr[3] > 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)
+void erb_set_done_callback(struct erb_rend *erb, erb_done_func donecb, void *cls)
+{
+       erb->donecb = donecb;
+       erb->donecls = cls;
+}
+
+void erb_queue_frame(struct erb_rend *erb, unsigned int job_id)
 {
-       erb_queue_block(erb, 0, 0, erb->fb_width, erb->fb_height);
+       erb_queue_block(erb, job_id, 0, 0, erb->fb_width, erb->fb_height);
 }
 
-void erb_queue_block(struct erb_rend *erb, int x, int y, int width, int height)
+void erb_queue_block(struct erb_rend *erb, unsigned int job_id, int x, int y,
+               int width, int height)
 {
        struct render_job *job;
 
@@ -131,12 +137,13 @@ void erb_queue_block(struct erb_rend *erb, int x, int y, int width, int height)
        }
 
        job->erb = erb;
-       job->x = x;
-       job->y = y;
-       job->width = width;
-       job->height = height;
+       job->id = job_id;
+       job->rect.x = x;
+       job->rect.y = y;
+       job->rect.w = width;
+       job->rect.h = height;
 
-       tpool_enqueue(tpool, job, proc_render_job, 0);
+       tpool_enqueue(tpool, job, proc_render_job, done_render_job);
 }
 
 void erb_wait(struct erb_rend *erb)
@@ -163,21 +170,32 @@ static void proc_render_job(void *cls)
        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;
+       fboffs = job->rect.y * erb->fb_width + job->rect.x;
+       fbptr = erb->fb_pixels + fboffs * 4;
 
-       for(i=0; i<job->height; i++) {
-               for(j=0; j<job->width; j++) {
-                       erb_primary_ray(erb, &ray, *nsptr++);
+       for(i=0; i<job->rect.h; i++) {
+               for(j=0; j<job->rect.w; j++) {
+                       erb_primary_ray(erb, &ray, (int)fbptr[3]);
                        erb_sample_ray(erb, &ray, fbptr);
-                       fbptr += 3;
+                       fbptr += 4;
                }
+               fbptr += (erb->fb_width - job->rect.w) * 4;
        }
+}
+
+static void done_render_job(void *cls)
+{
+       struct erb_rend *erb;
+       struct render_job *job = cls;
+
+       erb = job->erb;
+       if(erb->donecb) {
+               erb->donecb(job->id, &job->rect, erb->donecls);
+       }
+
        free_job(job);
 }