Cycles: Make all #include statements relative to cycles source directory
[blender.git] / intern / cycles / render / buffers.cpp
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18
19 #include "render/buffers.h"
20 #include "device/device.h"
21
22 #include "util/util_debug.h"
23 #include "util/util_foreach.h"
24 #include "util/util_hash.h"
25 #include "util/util_image.h"
26 #include "util/util_math.h"
27 #include "util/util_opengl.h"
28 #include "util/util_time.h"
29 #include "util/util_types.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 /* Buffer Params */
34
35 BufferParams::BufferParams()
36 {
37         width = 0;
38         height = 0;
39
40         full_x = 0;
41         full_y = 0;
42         full_width = 0;
43         full_height = 0;
44
45         Pass::add(PASS_COMBINED, passes);
46 }
47
48 void BufferParams::get_offset_stride(int& offset, int& stride)
49 {
50         offset = -(full_x + full_y*width);
51         stride = width;
52 }
53
54 bool BufferParams::modified(const BufferParams& params)
55 {
56         return !(full_x == params.full_x
57                 && full_y == params.full_y
58                 && width == params.width
59                 && height == params.height
60                 && full_width == params.full_width
61                 && full_height == params.full_height
62                 && Pass::equals(passes, params.passes));
63 }
64
65 int BufferParams::get_passes_size()
66 {
67         int size = 0;
68
69         for(size_t i = 0; i < passes.size(); i++)
70                 size += passes[i].components;
71         
72         return align_up(size, 4);
73 }
74
75 /* Render Buffer Task */
76
77 RenderTile::RenderTile()
78 {
79         x = 0;
80         y = 0;
81         w = 0;
82         h = 0;
83
84         sample = 0;
85         start_sample = 0;
86         num_samples = 0;
87         resolution = 0;
88
89         offset = 0;
90         stride = 0;
91
92         buffer = 0;
93         rng_state = 0;
94
95         buffers = NULL;
96 }
97
98 /* Render Buffers */
99
100 RenderBuffers::RenderBuffers(Device *device_)
101 {
102         device = device_;
103 }
104
105 RenderBuffers::~RenderBuffers()
106 {
107         device_free();
108 }
109
110 void RenderBuffers::device_free()
111 {
112         if(buffer.device_pointer) {
113                 device->mem_free(buffer);
114                 buffer.clear();
115         }
116
117         if(rng_state.device_pointer) {
118                 device->mem_free(rng_state);
119                 rng_state.clear();
120         }
121 }
122
123 void RenderBuffers::reset(Device *device, BufferParams& params_)
124 {
125         params = params_;
126
127         /* free existing buffers */
128         device_free();
129         
130         /* allocate buffer */
131         buffer.resize(params.width*params.height*params.get_passes_size());
132         device->mem_alloc("render_buffer", buffer, MEM_READ_WRITE);
133         device->mem_zero(buffer);
134
135         /* allocate rng state */
136         rng_state.resize(params.width, params.height);
137
138         device->mem_alloc("rng_state", rng_state, MEM_READ_WRITE);
139 }
140
141 bool RenderBuffers::copy_from_device()
142 {
143         if(!buffer.device_pointer)
144                 return false;
145
146         device->mem_copy_from(buffer, 0, params.width, params.height, params.get_passes_size()*sizeof(float));
147
148         return true;
149 }
150
151 bool RenderBuffers::get_pass_rect(PassType type, float exposure, int sample, int components, float *pixels)
152 {
153         int pass_offset = 0;
154
155         for(size_t j = 0; j < params.passes.size(); j++) {
156                 Pass& pass = params.passes[j];
157
158                 if(pass.type != type) {
159                         pass_offset += pass.components;
160                         continue;
161                 }
162
163                 float *in = (float*)buffer.data_pointer + pass_offset;
164                 int pass_stride = params.get_passes_size();
165
166                 float scale = (pass.filter)? 1.0f/(float)sample: 1.0f;
167                 float scale_exposure = (pass.exposure)? scale*exposure: scale;
168
169                 int size = params.width*params.height;
170
171                 if(components == 1) {
172                         assert(pass.components == components);
173
174                         /* scalar */
175                         if(type == PASS_DEPTH) {
176                                 for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
177                                         float f = *in;
178                                         pixels[0] = (f == 0.0f)? 1e10f: f*scale_exposure;
179                                 }
180                         }
181                         else if(type == PASS_MIST) {
182                                 for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
183                                         float f = *in;
184                                         pixels[0] = saturate(f*scale_exposure);
185                                 }
186                         }
187 #ifdef WITH_CYCLES_DEBUG
188                         else if(type == PASS_BVH_TRAVERSED_NODES ||
189                                 type == PASS_BVH_TRAVERSED_INSTANCES ||
190                                 type == PASS_BVH_INTERSECTIONS ||
191                                 type == PASS_RAY_BOUNCES)
192                         {
193                                 for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
194                                         float f = *in;
195                                         pixels[0] = f*scale;
196                                 }
197                         }
198 #endif
199                         else {
200                                 for(int i = 0; i < size; i++, in += pass_stride, pixels++) {
201                                         float f = *in;
202                                         pixels[0] = f*scale_exposure;
203                                 }
204                         }
205                 }
206                 else if(components == 3) {
207                         assert(pass.components == 4);
208
209                         /* RGBA */
210                         if(type == PASS_SHADOW) {
211                                 for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
212                                         float4 f = make_float4(in[0], in[1], in[2], in[3]);
213                                         float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;
214
215                                         pixels[0] = f.x*invw;
216                                         pixels[1] = f.y*invw;
217                                         pixels[2] = f.z*invw;
218                                 }
219                         }
220                         else if(pass.divide_type != PASS_NONE) {
221                                 /* RGB lighting passes that need to divide out color */
222                                 pass_offset = 0;
223                                 for(size_t k = 0; k < params.passes.size(); k++) {
224                                         Pass& color_pass = params.passes[k];
225                                         if(color_pass.type == pass.divide_type)
226                                                 break;
227                                         pass_offset += color_pass.components;
228                                 }
229
230                                 float *in_divide = (float*)buffer.data_pointer + pass_offset;
231
232                                 for(int i = 0; i < size; i++, in += pass_stride, in_divide += pass_stride, pixels += 3) {
233                                         float3 f = make_float3(in[0], in[1], in[2]);
234                                         float3 f_divide = make_float3(in_divide[0], in_divide[1], in_divide[2]);
235
236                                         f = safe_divide_even_color(f*exposure, f_divide);
237
238                                         pixels[0] = f.x;
239                                         pixels[1] = f.y;
240                                         pixels[2] = f.z;
241                                 }
242                         }
243                         else {
244                                 /* RGB/vector */
245                                 for(int i = 0; i < size; i++, in += pass_stride, pixels += 3) {
246                                         float3 f = make_float3(in[0], in[1], in[2]);
247
248                                         pixels[0] = f.x*scale_exposure;
249                                         pixels[1] = f.y*scale_exposure;
250                                         pixels[2] = f.z*scale_exposure;
251                                 }
252                         }
253                 }
254                 else if(components == 4) {
255                         assert(pass.components == components);
256
257                         /* RGBA */
258                         if(type == PASS_SHADOW) {
259                                 for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
260                                         float4 f = make_float4(in[0], in[1], in[2], in[3]);
261                                         float invw = (f.w > 0.0f)? 1.0f/f.w: 1.0f;
262
263                                         pixels[0] = f.x*invw;
264                                         pixels[1] = f.y*invw;
265                                         pixels[2] = f.z*invw;
266                                         pixels[3] = 1.0f;
267                                 }
268                         }
269                         else if(type == PASS_MOTION) {
270                                 /* need to normalize by number of samples accumulated for motion */
271                                 pass_offset = 0;
272                                 for(size_t k = 0; k < params.passes.size(); k++) {
273                                         Pass& color_pass = params.passes[k];
274                                         if(color_pass.type == PASS_MOTION_WEIGHT)
275                                                 break;
276                                         pass_offset += color_pass.components;
277                                 }
278
279                                 float *in_weight = (float*)buffer.data_pointer + pass_offset;
280
281                                 for(int i = 0; i < size; i++, in += pass_stride, in_weight += pass_stride, pixels += 4) {
282                                         float4 f = make_float4(in[0], in[1], in[2], in[3]);
283                                         float w = in_weight[0];
284                                         float invw = (w > 0.0f)? 1.0f/w: 0.0f;
285
286                                         pixels[0] = f.x*invw;
287                                         pixels[1] = f.y*invw;
288                                         pixels[2] = f.z*invw;
289                                         pixels[3] = f.w*invw;
290                                 }
291                         }
292                         else {
293                                 for(int i = 0; i < size; i++, in += pass_stride, pixels += 4) {
294                                         float4 f = make_float4(in[0], in[1], in[2], in[3]);
295
296                                         pixels[0] = f.x*scale_exposure;
297                                         pixels[1] = f.y*scale_exposure;
298                                         pixels[2] = f.z*scale_exposure;
299
300                                         /* clamp since alpha might be > 1.0 due to russian roulette */
301                                         pixels[3] = saturate(f.w*scale);
302                                 }
303                         }
304                 }
305
306                 return true;
307         }
308
309         return false;
310 }
311
312 /* Display Buffer */
313
314 DisplayBuffer::DisplayBuffer(Device *device_, bool linear)
315 {
316         device = device_;
317         draw_width = 0;
318         draw_height = 0;
319         transparent = true; /* todo: determine from background */
320         half_float = linear;
321 }
322
323 DisplayBuffer::~DisplayBuffer()
324 {
325         device_free();
326 }
327
328 void DisplayBuffer::device_free()
329 {
330         if(rgba_byte.device_pointer) {
331                 device->pixels_free(rgba_byte);
332                 rgba_byte.clear();
333         }
334         if(rgba_half.device_pointer) {
335                 device->pixels_free(rgba_half);
336                 rgba_half.clear();
337         }
338 }
339
340 void DisplayBuffer::reset(Device *device, BufferParams& params_)
341 {
342         draw_width = 0;
343         draw_height = 0;
344
345         params = params_;
346
347         /* free existing buffers */
348         device_free();
349
350         /* allocate display pixels */
351         if(half_float) {
352                 rgba_half.resize(params.width, params.height);
353                 device->pixels_alloc(rgba_half);
354         }
355         else {
356                 rgba_byte.resize(params.width, params.height);
357                 device->pixels_alloc(rgba_byte);
358         }
359 }
360
361 void DisplayBuffer::draw_set(int width, int height)
362 {
363         assert(width <= params.width && height <= params.height);
364
365         draw_width = width;
366         draw_height = height;
367 }
368
369 void DisplayBuffer::draw(Device *device, const DeviceDrawParams& draw_params)
370 {
371         if(draw_width != 0 && draw_height != 0) {
372                 device_memory& rgba = rgba_data();
373
374                 device->draw_pixels(rgba, 0, draw_width, draw_height, params.full_x, params.full_y, params.width, params.height, transparent, draw_params);
375         }
376 }
377
378 bool DisplayBuffer::draw_ready()
379 {
380         return (draw_width != 0 && draw_height != 0);
381 }
382
383 void DisplayBuffer::write(Device *device, const string& filename)
384 {
385         int w = draw_width;
386         int h = draw_height;
387
388         if(w == 0 || h == 0)
389                 return;
390         
391         if(half_float)
392                 return;
393
394         /* read buffer from device */
395         device_memory& rgba = rgba_data();
396         device->pixels_copy_from(rgba, 0, w, h);
397
398         /* write image */
399         ImageOutput *out = ImageOutput::create(filename);
400         ImageSpec spec(w, h, 4, TypeDesc::UINT8);
401         int scanlinesize = w*4*sizeof(uchar);
402
403         out->open(filename, spec);
404
405         /* conversion for different top/bottom convention */
406         out->write_image(TypeDesc::UINT8,
407                 (uchar*)rgba.data_pointer + (h-1)*scanlinesize,
408                 AutoStride,
409                 -scanlinesize,
410                 AutoStride);
411
412         out->close();
413
414         delete out;
415 }
416
417 device_memory& DisplayBuffer::rgba_data()
418 {
419         if(half_float)
420                 return rgba_half;
421         else
422                 return rgba_byte;
423 }
424
425 CCL_NAMESPACE_END
426