8 int x, y, width, height;
9 struct render_job *next;
13 int fb_width, fb_height, fb_npix;
18 static void proc_render_job(void *cls);
19 static struct render_job *alloc_job(void);
20 static void free_job(struct render_job *job);
22 static struct thread_pool *tpool;
25 struct erb_rend *erb_create(void)
30 if(!(tpool = tpool_create(0))) {
31 fprintf(stderr, "erb_create: fatal error, failed to create thread pool!\n");
36 if(!(erb = calloc(1, sizeof *erb))) {
42 void erb_destroy(struct erb_rend *erb)
49 int erb_allocframe(struct erb_rend *erb, int width, int height)
55 if(width == erb->fb_width && height == erb->fb_height) {
59 npix = width * height;
61 if(!(newfb = malloc(npix * 3 * sizeof *erb->fb_pixels))) {
64 if(!(newns = malloc(npix * sizeof *erb->fb_nsamples))) {
70 free(erb->fb_nsamples);
72 erb->fb_pixels = newfb;
73 erb->fb_nsamples = newns;
74 erb->fb_width = width;
75 erb->fb_height = height;
80 fprintf(stderr, "erb_allocframe: failed to allocate %dx%d framebuffer\n", width, height);
84 float *erb_getframe(struct erb_rend *erb)
86 return erb->fb_pixels;
89 void erb_begin(struct erb_rend *erb)
91 memset(erb->fb_pixels, 0, erb->fb_npix * 3 * sizeof *erb->fb_pixels);
92 memset(erb->fb_nsamples, 0, erb->fb_npix * sizeof *erb->fb_nsamples);
95 float *erb_end(struct erb_rend *erb)
99 float *pptr = erb->fb_pixels;
100 int *nptr = erb->fb_nsamples;
102 for(i=0; i<erb->fb_npix; i++) {
116 return erb->fb_pixels;
119 void erb_queue_frame(struct erb_rend *erb)
121 erb_queue_block(erb, 0, 0, erb->fb_width, erb->fb_height);
124 void erb_queue_block(struct erb_rend *erb, int x, int y, int width, int height)
126 struct render_job *job;
128 if(!(job = alloc_job())) {
129 fprintf(stderr, "erb_queue_block: failed to allocate rendering job\n");
137 job->height = height;
139 tpool_enqueue(tpool, job, proc_render_job, 0);
142 void erb_wait(struct erb_rend *erb)
144 /* XXX should we have a per-renderer instance thread pool, to wait only for our own jobs? */
148 void erb_primary_ray(struct erb_rend *erb, struct erb_ray *ray, int sample)
153 void erb_sample_ray(struct erb_rend *erb, struct erb_ray *ray, float *col)
156 col[0] = fmod(col[0] + 1.0f, 1.0f);
157 col[1] = col[2] = fmod(col[1] + 0.33f, 1.0f);
160 static void proc_render_job(void *cls)
163 struct erb_rend *erb;
164 struct render_job *job = cls;
170 fboffs = job->y * erb->fb_width + job->x;
171 fbptr = erb->fb_pixels + fboffs * 3;
172 nsptr = erb->fb_nsamples + fboffs;
174 for(i=0; i<job->height; i++) {
175 for(j=0; j<job->width; j++) {
176 erb_primary_ray(erb, &ray, *nsptr++);
177 erb_sample_ray(erb, &ray, fbptr);
185 #define MAX_JOB_POOL 128
186 static struct render_job *job_pool;
187 static int num_free_jobs;
188 static pthread_mutex_t job_pool_lock = PTHREAD_MUTEX_INITIALIZER;
190 static struct render_job *alloc_job(void)
192 struct render_job *job;
194 pthread_mutex_lock(&job_pool_lock);
196 pthread_mutex_unlock(&job_pool_lock);
197 return malloc(sizeof *job);
201 job_pool = job->next;
203 pthread_mutex_unlock(&job_pool_lock);
207 static void free_job(struct render_job *job)
209 pthread_mutex_lock(&job_pool_lock);
210 if(num_free_jobs >= MAX_JOB_POOL) {
211 pthread_mutex_unlock(&job_pool_lock);
216 job->next = job_pool;
219 pthread_mutex_unlock(&job_pool_lock);