8 int x, y, width, height;
9 struct render_job *next;
13 int fb_width, fb_height, fb_size;
17 static void proc_render_job(void *cls);
18 static struct render_job *alloc_job(void);
19 static void free_job(struct render_job *job);
21 static struct thread_pool *tpool;
24 struct erb_rend *erb_create(void)
29 if(!(tpool = tpool_create(0))) {
30 fprintf(stderr, "erb_create: fatal error, failed to create thread pool!\n");
35 if(!(erb = calloc(1, sizeof *erb))) {
41 void erb_destroy(struct erb_rend *erb)
48 int erb_allocframe(struct erb_rend *erb, int width, int height)
53 if(width == erb->fb_width && height == erb->fb_height) {
57 sz = width * height * 4 * sizeof *erb->fb_pixels;
58 if(!(newfb = malloc(sz))) {
59 fprintf(stderr, "erb_allocframe: failed to allocate %dx%d framebuffer\n", width, height);
65 erb->fb_pixels = newfb;
66 erb->fb_width = width;
67 erb->fb_height = height;
72 float *erb_getframe(struct erb_rend *erb)
74 return erb->fb_pixels;
77 void erb_begin(struct erb_rend *erb)
79 memset(erb->fb_pixels, 0, erb->fb_size);
82 float *erb_end(struct erb_rend *erb)
84 int i, npix = erb->fb_width * erb->fb_height;
86 float *pptr = erb->fb_pixels;
88 for(i=0; i<npix; i++) {
100 return erb->fb_pixels;
103 void erb_queue_frame(struct erb_rend *erb)
105 erb_queue_block(erb, 0, 0, erb->fb_width, erb->fb_height);
108 void erb_queue_block(struct erb_rend *erb, int x, int y, int width, int height)
110 struct render_job *job;
112 if(!(job = alloc_job())) {
113 fprintf(stderr, "erb_queue_block: failed to allocate rendering job\n");
121 job->height = height;
123 tpool_enqueue(tpool, job, proc_render_job, 0);
126 void erb_wait(struct erb_rend *erb)
128 /* XXX should we have a per-renderer instance thread pool, to wait only for our own jobs? */
132 void erb_primary_ray(struct erb_rend *erb, struct erb_ray *ray, int sample)
137 void erb_sample_ray(struct erb_rend *erb, struct erb_ray *ray, float *col)
140 col[0] = fmod(col[0] + 1.0f, 1.0f);
141 col[1] = col[2] = fmod(col[1] + 0.33f, 1.0f);
144 static void proc_render_job(void *cls)
147 struct erb_rend *erb;
148 struct render_job *job = cls;
153 fboffs = job->y * erb->fb_width + job->x;
154 fbptr = erb->fb_pixels + fboffs * 4;
156 for(i=0; i<job->height; i++) {
157 for(j=0; j<job->width; j++) {
158 erb_primary_ray(erb, &ray, (int)fbptr[3]);
159 erb_sample_ray(erb, &ray, fbptr);
162 fbptr += (erb->fb_width - job->width) * 4;
168 #define MAX_JOB_POOL 128
169 static struct render_job *job_pool;
170 static int num_free_jobs;
171 static pthread_mutex_t job_pool_lock = PTHREAD_MUTEX_INITIALIZER;
173 static struct render_job *alloc_job(void)
175 struct render_job *job;
177 pthread_mutex_lock(&job_pool_lock);
179 pthread_mutex_unlock(&job_pool_lock);
180 return malloc(sizeof *job);
184 job_pool = job->next;
186 pthread_mutex_unlock(&job_pool_lock);
190 static void free_job(struct render_job *job)
192 pthread_mutex_lock(&job_pool_lock);
193 if(num_free_jobs >= MAX_JOB_POOL) {
194 pthread_mutex_unlock(&job_pool_lock);
199 job->next = job_pool;
202 pthread_mutex_unlock(&job_pool_lock);