macros for rectangle center and size
[blender.git] / source / blender / render / intern / source / render_result.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/render/intern/source/render_result.c
29  *  \ingroup render
30  */
31
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "MEM_guardedalloc.h"
36
37 #include "BKE_image.h"
38 #include "BKE_global.h"
39 #include "BKE_main.h"
40 #include "BKE_report.h"
41 #include "BKE_utildefines.h"
42
43 #include "BLI_fileops.h"
44 #include "BLI_listbase.h"
45 #include "BLI_path_util.h"
46 #include "BLI_rect.h"
47 #include "BLI_string.h"
48 #include "BLI_threads.h"
49 #include "BLI_utildefines.h"
50
51 #include "IMB_imbuf.h"
52 #include "IMB_imbuf_types.h"
53
54 #include "intern/openexr/openexr_multi.h"
55
56 #include "render_result.h"
57 #include "render_types.h"
58
59 /********************************** Free *************************************/
60
61 void render_result_free(RenderResult *res)
62 {
63         if (res == NULL) return;
64
65         while (res->layers.first) {
66                 RenderLayer *rl = res->layers.first;
67                 
68                 if (rl->rectf) MEM_freeN(rl->rectf);
69                 /* acolrect and scolrect are optionally allocated in shade_tile, only free here since it can be used for drawing */
70                 if (rl->acolrect) MEM_freeN(rl->acolrect);
71                 if (rl->scolrect) MEM_freeN(rl->scolrect);
72                 
73                 while (rl->passes.first) {
74                         RenderPass *rpass = rl->passes.first;
75                         if (rpass->rect) MEM_freeN(rpass->rect);
76                         BLI_remlink(&rl->passes, rpass);
77                         MEM_freeN(rpass);
78                 }
79                 BLI_remlink(&res->layers, rl);
80                 MEM_freeN(rl);
81         }
82         
83         if (res->rect32)
84                 MEM_freeN(res->rect32);
85         if (res->rectz)
86                 MEM_freeN(res->rectz);
87         if (res->rectf)
88                 MEM_freeN(res->rectf);
89         if (res->text)
90                 MEM_freeN(res->text);
91         
92         MEM_freeN(res);
93 }
94
95 /* version that's compatible with fullsample buffers */
96 void render_result_free_list(ListBase *lb, RenderResult *rr)
97 {
98         RenderResult *rrnext;
99         
100         for (; rr; rr = rrnext) {
101                 rrnext = rr->next;
102                 
103                 if (lb && lb->first)
104                         BLI_remlink(lb, rr);
105                 
106                 render_result_free(rr);
107         }
108 }
109
110 /********************************* Names *************************************/
111
112 /* NOTE: OpenEXR only supports 32 chars for layer+pass names
113  * In blender we now use max 10 chars for pass, max 20 for layer */
114 static const char *get_pass_name(int passtype, int channel)
115 {
116         
117         if (passtype == SCE_PASS_COMBINED) {
118                 if (channel == -1) return "Combined";
119                 if (channel == 0) return "Combined.R";
120                 if (channel == 1) return "Combined.G";
121                 if (channel == 2) return "Combined.B";
122                 return "Combined.A";
123         }
124         if (passtype == SCE_PASS_Z) {
125                 if (channel == -1) return "Depth";
126                 return "Depth.Z";
127         }
128         if (passtype == SCE_PASS_VECTOR) {
129                 if (channel == -1) return "Vector";
130                 if (channel == 0) return "Vector.X";
131                 if (channel == 1) return "Vector.Y";
132                 if (channel == 2) return "Vector.Z";
133                 return "Vector.W";
134         }
135         if (passtype == SCE_PASS_NORMAL) {
136                 if (channel == -1) return "Normal";
137                 if (channel == 0) return "Normal.X";
138                 if (channel == 1) return "Normal.Y";
139                 return "Normal.Z";
140         }
141         if (passtype == SCE_PASS_UV) {
142                 if (channel == -1) return "UV";
143                 if (channel == 0) return "UV.U";
144                 if (channel == 1) return "UV.V";
145                 return "UV.A";
146         }
147         if (passtype == SCE_PASS_RGBA) {
148                 if (channel == -1) return "Color";
149                 if (channel == 0) return "Color.R";
150                 if (channel == 1) return "Color.G";
151                 if (channel == 2) return "Color.B";
152                 return "Color.A";
153         }
154         if (passtype == SCE_PASS_EMIT) {
155                 if (channel == -1) return "Emit";
156                 if (channel == 0) return "Emit.R";
157                 if (channel == 1) return "Emit.G";
158                 return "Emit.B";
159         }
160         if (passtype == SCE_PASS_DIFFUSE) {
161                 if (channel == -1) return "Diffuse";
162                 if (channel == 0) return "Diffuse.R";
163                 if (channel == 1) return "Diffuse.G";
164                 return "Diffuse.B";
165         }
166         if (passtype == SCE_PASS_SPEC) {
167                 if (channel == -1) return "Spec";
168                 if (channel == 0) return "Spec.R";
169                 if (channel == 1) return "Spec.G";
170                 return "Spec.B";
171         }
172         if (passtype == SCE_PASS_SHADOW) {
173                 if (channel == -1) return "Shadow";
174                 if (channel == 0) return "Shadow.R";
175                 if (channel == 1) return "Shadow.G";
176                 return "Shadow.B";
177         }
178         if (passtype == SCE_PASS_AO) {
179                 if (channel == -1) return "AO";
180                 if (channel == 0) return "AO.R";
181                 if (channel == 1) return "AO.G";
182                 return "AO.B";
183         }
184         if (passtype == SCE_PASS_ENVIRONMENT) {
185                 if (channel == -1) return "Env";
186                 if (channel == 0) return "Env.R";
187                 if (channel == 1) return "Env.G";
188                 return "Env.B";
189         }
190         if (passtype == SCE_PASS_INDIRECT) {
191                 if (channel == -1) return "Indirect";
192                 if (channel == 0) return "Indirect.R";
193                 if (channel == 1) return "Indirect.G";
194                 return "Indirect.B";
195         }
196         if (passtype == SCE_PASS_REFLECT) {
197                 if (channel == -1) return "Reflect";
198                 if (channel == 0) return "Reflect.R";
199                 if (channel == 1) return "Reflect.G";
200                 return "Reflect.B";
201         }
202         if (passtype == SCE_PASS_REFRACT) {
203                 if (channel == -1) return "Refract";
204                 if (channel == 0) return "Refract.R";
205                 if (channel == 1) return "Refract.G";
206                 return "Refract.B";
207         }
208         if (passtype == SCE_PASS_INDEXOB) {
209                 if (channel == -1) return "IndexOB";
210                 return "IndexOB.X";
211         }
212         if (passtype == SCE_PASS_INDEXMA) {
213                 if (channel == -1) return "IndexMA";
214                 return "IndexMA.X";
215         }
216         if (passtype == SCE_PASS_MIST) {
217                 if (channel == -1) return "Mist";
218                 return "Mist.Z";
219         }
220         if (passtype == SCE_PASS_RAYHITS) {
221                 if (channel == -1) return "Rayhits";
222                 if (channel == 0) return "Rayhits.R";
223                 if (channel == 1) return "Rayhits.G";
224                 return "Rayhits.B";
225         }
226         if (passtype == SCE_PASS_DIFFUSE_DIRECT) {
227                 if (channel == -1) return "DiffDir";
228                 if (channel == 0) return "DiffDir.R";
229                 if (channel == 1) return "DiffDir.G";
230                 return "DiffDir.B";
231         }
232         if (passtype == SCE_PASS_DIFFUSE_INDIRECT) {
233                 if (channel == -1) return "DiffInd";
234                 if (channel == 0) return "DiffInd.R";
235                 if (channel == 1) return "DiffInd.G";
236                 return "DiffInd.B";
237         }
238         if (passtype == SCE_PASS_DIFFUSE_COLOR) {
239                 if (channel == -1) return "DiffCol";
240                 if (channel == 0) return "DiffCol.R";
241                 if (channel == 1) return "DiffCol.G";
242                 return "DiffCol.B";
243         }
244         if (passtype == SCE_PASS_GLOSSY_DIRECT) {
245                 if (channel == -1) return "GlossDir";
246                 if (channel == 0) return "GlossDir.R";
247                 if (channel == 1) return "GlossDir.G";
248                 return "GlossDir.B";
249         }
250         if (passtype == SCE_PASS_GLOSSY_INDIRECT) {
251                 if (channel == -1) return "GlossInd";
252                 if (channel == 0) return "GlossInd.R";
253                 if (channel == 1) return "GlossInd.G";
254                 return "GlossInd.B";
255         }
256         if (passtype == SCE_PASS_GLOSSY_COLOR) {
257                 if (channel == -1) return "GlossCol";
258                 if (channel == 0) return "GlossCol.R";
259                 if (channel == 1) return "GlossCol.G";
260                 return "GlossCol.B";
261         }
262         if (passtype == SCE_PASS_TRANSM_DIRECT) {
263                 if (channel == -1) return "TransDir";
264                 if (channel == 0) return "TransDir.R";
265                 if (channel == 1) return "TransDir.G";
266                 return "TransDir.B";
267         }
268         if (passtype == SCE_PASS_TRANSM_INDIRECT) {
269                 if (channel == -1) return "TransInd";
270                 if (channel == 0) return "TransInd.R";
271                 if (channel == 1) return "TransInd.G";
272                 return "TransInd.B";
273         }
274         if (passtype == SCE_PASS_TRANSM_COLOR) {
275                 if (channel == -1) return "TransCol";
276                 if (channel == 0) return "TransCol.R";
277                 if (channel == 1) return "TransCol.G";
278                 return "TransCol.B";
279         }
280         return "Unknown";
281 }
282
283 static int passtype_from_name(const char *str)
284 {
285         
286         if (strcmp(str, "Combined") == 0)
287                 return SCE_PASS_COMBINED;
288
289         if (strcmp(str, "Depth") == 0)
290                 return SCE_PASS_Z;
291
292         if (strcmp(str, "Vector") == 0)
293                 return SCE_PASS_VECTOR;
294
295         if (strcmp(str, "Normal") == 0)
296                 return SCE_PASS_NORMAL;
297
298         if (strcmp(str, "UV") == 0)
299                 return SCE_PASS_UV;
300
301         if (strcmp(str, "Color") == 0)
302                 return SCE_PASS_RGBA;
303
304         if (strcmp(str, "Emit") == 0)
305                 return SCE_PASS_EMIT;
306
307         if (strcmp(str, "Diffuse") == 0)
308                 return SCE_PASS_DIFFUSE;
309
310         if (strcmp(str, "Spec") == 0)
311                 return SCE_PASS_SPEC;
312
313         if (strcmp(str, "Shadow") == 0)
314                 return SCE_PASS_SHADOW;
315         
316         if (strcmp(str, "AO") == 0)
317                 return SCE_PASS_AO;
318
319         if (strcmp(str, "Env") == 0)
320                 return SCE_PASS_ENVIRONMENT;
321
322         if (strcmp(str, "Indirect") == 0)
323                 return SCE_PASS_INDIRECT;
324
325         if (strcmp(str, "Reflect") == 0)
326                 return SCE_PASS_REFLECT;
327
328         if (strcmp(str, "Refract") == 0)
329                 return SCE_PASS_REFRACT;
330
331         if (strcmp(str, "IndexOB") == 0)
332                 return SCE_PASS_INDEXOB;
333
334         if (strcmp(str, "IndexMA") == 0)
335                 return SCE_PASS_INDEXMA;
336
337         if (strcmp(str, "Mist") == 0)
338                 return SCE_PASS_MIST;
339         
340         if (strcmp(str, "RayHits") == 0)
341                 return SCE_PASS_RAYHITS;
342
343         if (strcmp(str, "DiffDir") == 0)
344                 return SCE_PASS_DIFFUSE_DIRECT;
345
346         if (strcmp(str, "DiffInd") == 0)
347                 return SCE_PASS_DIFFUSE_INDIRECT;
348
349         if (strcmp(str, "DiffCol") == 0)
350                 return SCE_PASS_DIFFUSE_COLOR;
351
352         if (strcmp(str, "GlossDir") == 0)
353                 return SCE_PASS_GLOSSY_DIRECT;
354
355         if (strcmp(str, "GlossInd") == 0)
356                 return SCE_PASS_GLOSSY_INDIRECT;
357
358         if (strcmp(str, "GlossCol") == 0)
359                 return SCE_PASS_GLOSSY_COLOR;
360
361         if (strcmp(str, "TransDir") == 0)
362                 return SCE_PASS_TRANSM_DIRECT;
363
364         if (strcmp(str, "TransInd") == 0)
365                 return SCE_PASS_TRANSM_INDIRECT;
366
367         if (strcmp(str, "TransCol") == 0)
368                 return SCE_PASS_TRANSM_COLOR;
369
370         return 0;
371 }
372
373 /********************************** New **************************************/
374
375 static void render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, int passtype)
376 {
377         const char *typestr = get_pass_name(passtype, 0);
378         RenderPass *rpass = MEM_callocN(sizeof(RenderPass), typestr);
379         int rectsize = rr->rectx * rr->recty * channels;
380         
381         BLI_addtail(&rl->passes, rpass);
382         rpass->passtype = passtype;
383         rpass->channels = channels;
384         rpass->rectx = rl->rectx;
385         rpass->recty = rl->recty;
386         BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
387         
388         if (rr->exrhandle) {
389                 int a;
390                 for (a = 0; a < channels; a++)
391                         IMB_exr_add_channel(rr->exrhandle, rl->name, get_pass_name(passtype, a), 0, 0, NULL);
392         }
393         else {
394                 float *rect;
395                 int x;
396                 
397                 rpass->rect = MEM_mapallocN(sizeof(float) * rectsize, typestr);
398                 
399                 if (passtype == SCE_PASS_VECTOR) {
400                         /* initialize to max speed */
401                         rect = rpass->rect;
402                         for (x = rectsize - 1; x >= 0; x--)
403                                 rect[x] = PASS_VECTOR_MAX;
404                 }
405                 else if (passtype == SCE_PASS_Z) {
406                         rect = rpass->rect;
407                         for (x = rectsize - 1; x >= 0; x--)
408                                 rect[x] = 10e10;
409                 }
410         }
411 }
412
413 /* called by main render as well for parts */
414 /* will read info from Render *re to define layers */
415 /* called in threads */
416 /* re->winx,winy is coordinate space of entire image, partrct the part within */
417 RenderResult *render_result_new(Render *re, rcti *partrct, int crop, int savebuffers)
418 {
419         RenderResult *rr;
420         RenderLayer *rl;
421         SceneRenderLayer *srl;
422         int rectx, recty, nr;
423         
424         rectx = BLI_RCT_SIZE_X(partrct);
425         recty = BLI_RCT_SIZE_Y(partrct);
426         
427         if (rectx <= 0 || recty <= 0)
428                 return NULL;
429         
430         rr = MEM_callocN(sizeof(RenderResult), "new render result");
431         rr->rectx = rectx;
432         rr->recty = recty;
433         rr->renrect.xmin = 0; rr->renrect.xmax = rectx - 2 * crop;
434         /* crop is one or two extra pixels rendered for filtering, is used for merging and display too */
435         rr->crop = crop;
436         
437         /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
438         rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
439         rr->tilerect.xmax = partrct->xmax - re->disprect.xmax;
440         rr->tilerect.ymin = partrct->ymin - re->disprect.ymin;
441         rr->tilerect.ymax = partrct->ymax - re->disprect.ymax;
442         
443         if (savebuffers) {
444                 rr->exrhandle = IMB_exr_get_handle();
445         }
446         
447         /* check renderdata for amount of layers */
448         for (nr = 0, srl = re->r.layers.first; srl; srl = srl->next, nr++) {
449                 
450                 if ((re->r.scemode & R_SINGLE_LAYER) && nr != re->r.actlay)
451                         continue;
452                 if (srl->layflag & SCE_LAY_DISABLE)
453                         continue;
454                 
455                 rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
456                 BLI_addtail(&rr->layers, rl);
457                 
458                 BLI_strncpy(rl->name, srl->name, sizeof(rl->name));
459                 rl->lay = srl->lay;
460                 rl->lay_zmask = srl->lay_zmask;
461                 rl->lay_exclude = srl->lay_exclude;
462                 rl->layflag = srl->layflag;
463                 rl->passflag = srl->passflag; /* for debugging: srl->passflag | SCE_PASS_RAYHITS; */
464                 rl->pass_xor = srl->pass_xor;
465                 rl->light_override = srl->light_override;
466                 rl->mat_override = srl->mat_override;
467                 rl->rectx = rectx;
468                 rl->recty = recty;
469                 
470                 if (rr->exrhandle) {
471                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
472                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
473                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
474                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
475                 }
476                 else
477                         rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
478                 
479                 if (srl->passflag  & SCE_PASS_Z)
480                         render_layer_add_pass(rr, rl, 1, SCE_PASS_Z);
481                 if (srl->passflag  & SCE_PASS_VECTOR)
482                         render_layer_add_pass(rr, rl, 4, SCE_PASS_VECTOR);
483                 if (srl->passflag  & SCE_PASS_NORMAL)
484                         render_layer_add_pass(rr, rl, 3, SCE_PASS_NORMAL);
485                 if (srl->passflag  & SCE_PASS_UV) 
486                         render_layer_add_pass(rr, rl, 3, SCE_PASS_UV);
487                 if (srl->passflag  & SCE_PASS_RGBA)
488                         render_layer_add_pass(rr, rl, 4, SCE_PASS_RGBA);
489                 if (srl->passflag  & SCE_PASS_EMIT)
490                         render_layer_add_pass(rr, rl, 3, SCE_PASS_EMIT);
491                 if (srl->passflag  & SCE_PASS_DIFFUSE)
492                         render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE);
493                 if (srl->passflag  & SCE_PASS_SPEC)
494                         render_layer_add_pass(rr, rl, 3, SCE_PASS_SPEC);
495                 if (srl->passflag  & SCE_PASS_AO)
496                         render_layer_add_pass(rr, rl, 3, SCE_PASS_AO);
497                 if (srl->passflag  & SCE_PASS_ENVIRONMENT)
498                         render_layer_add_pass(rr, rl, 3, SCE_PASS_ENVIRONMENT);
499                 if (srl->passflag  & SCE_PASS_INDIRECT)
500                         render_layer_add_pass(rr, rl, 3, SCE_PASS_INDIRECT);
501                 if (srl->passflag  & SCE_PASS_SHADOW)
502                         render_layer_add_pass(rr, rl, 3, SCE_PASS_SHADOW);
503                 if (srl->passflag  & SCE_PASS_REFLECT)
504                         render_layer_add_pass(rr, rl, 3, SCE_PASS_REFLECT);
505                 if (srl->passflag  & SCE_PASS_REFRACT)
506                         render_layer_add_pass(rr, rl, 3, SCE_PASS_REFRACT);
507                 if (srl->passflag  & SCE_PASS_INDEXOB)
508                         render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXOB);
509                 if (srl->passflag  & SCE_PASS_INDEXMA)
510                         render_layer_add_pass(rr, rl, 1, SCE_PASS_INDEXMA);
511                 if (srl->passflag  & SCE_PASS_MIST)
512                         render_layer_add_pass(rr, rl, 1, SCE_PASS_MIST);
513                 if (rl->passflag & SCE_PASS_RAYHITS)
514                         render_layer_add_pass(rr, rl, 4, SCE_PASS_RAYHITS);
515                 if (srl->passflag  & SCE_PASS_DIFFUSE_DIRECT)
516                         render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_DIRECT);
517                 if (srl->passflag  & SCE_PASS_DIFFUSE_INDIRECT)
518                         render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_INDIRECT);
519                 if (srl->passflag  & SCE_PASS_DIFFUSE_COLOR)
520                         render_layer_add_pass(rr, rl, 3, SCE_PASS_DIFFUSE_COLOR);
521                 if (srl->passflag  & SCE_PASS_GLOSSY_DIRECT)
522                         render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_DIRECT);
523                 if (srl->passflag  & SCE_PASS_GLOSSY_INDIRECT)
524                         render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_INDIRECT);
525                 if (srl->passflag  & SCE_PASS_GLOSSY_COLOR)
526                         render_layer_add_pass(rr, rl, 3, SCE_PASS_GLOSSY_COLOR);
527                 if (srl->passflag  & SCE_PASS_TRANSM_DIRECT)
528                         render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_DIRECT);
529                 if (srl->passflag  & SCE_PASS_TRANSM_INDIRECT)
530                         render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_INDIRECT);
531                 if (srl->passflag  & SCE_PASS_TRANSM_COLOR)
532                         render_layer_add_pass(rr, rl, 3, SCE_PASS_TRANSM_COLOR);
533                 
534         }
535         /* sss, previewrender and envmap don't do layers, so we make a default one */
536         if (rr->layers.first == NULL) {
537                 rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
538                 BLI_addtail(&rr->layers, rl);
539                 
540                 rl->rectx = rectx;
541                 rl->recty = recty;
542
543                 /* duplicate code... */
544                 if (rr->exrhandle) {
545                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.R", 0, 0, NULL);
546                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.G", 0, 0, NULL);
547                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.B", 0, 0, NULL);
548                         IMB_exr_add_channel(rr->exrhandle, rl->name, "Combined.A", 0, 0, NULL);
549                 }
550                 else
551                         rl->rectf = MEM_mapallocN(rectx * recty * sizeof(float) * 4, "Combined rgba");
552                 
553                 /* note, this has to be in sync with scene.c */
554                 rl->lay = (1 << 20) - 1;
555                 rl->layflag = 0x7FFF;    /* solid ztra halo strand */
556                 rl->passflag = SCE_PASS_COMBINED;
557                 
558                 re->r.actlay = 0;
559         }
560         
561         /* border render; calculate offset for use in compositor. compo is centralized coords */
562         rr->xof = re->disprect.xmin + BLI_RCT_CENTER_X(&re->disprect) - (re->winx / 2);
563         rr->yof = re->disprect.ymin + BLI_RCT_CENTER_Y(&re->disprect) - (re->winy / 2);
564         
565         return rr;
566 }
567
568 /* allocate osa new results for samples */
569 RenderResult *render_result_new_full_sample(Render *re, ListBase *lb, rcti *partrct, int crop, int savebuffers)
570 {
571         int a;
572         
573         if (re->osa == 0)
574                 return render_result_new(re, partrct, crop, savebuffers);
575         
576         for (a = 0; a < re->osa; a++) {
577                 RenderResult *rr = render_result_new(re, partrct, crop, savebuffers);
578                 BLI_addtail(lb, rr);
579                 rr->sample_nr = a;
580         }
581         
582         return lb->first;
583 }
584
585 /* callbacks for render_result_new_from_exr */
586 static void *ml_addlayer_cb(void *base, const char *str)
587 {
588         RenderResult *rr = base;
589         RenderLayer *rl;
590         
591         rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
592         BLI_addtail(&rr->layers, rl);
593         
594         BLI_strncpy(rl->name, str, EXR_LAY_MAXNAME);
595         return rl;
596 }
597
598 static void ml_addpass_cb(void *UNUSED(base), void *lay, const char *str, float *rect, int totchan, const char *chan_id)
599 {
600         RenderLayer *rl = lay;
601         RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
602         int a;
603         
604         BLI_addtail(&rl->passes, rpass);
605         rpass->channels = totchan;
606
607         rpass->passtype = passtype_from_name(str);
608         if (rpass->passtype == 0) printf("unknown pass %s\n", str);
609         rl->passflag |= rpass->passtype;
610         
611         BLI_strncpy(rpass->name, str, EXR_PASS_MAXNAME);
612         /* channel id chars */
613         for (a = 0; a < totchan; a++)
614                 rpass->chan_id[a] = chan_id[a];
615         
616         rpass->rect = rect;
617 }
618
619 /* from imbuf, if a handle was returned we convert this to render result */
620 RenderResult *render_result_new_from_exr(void *exrhandle, int rectx, int recty)
621 {
622         RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
623         RenderLayer *rl;
624         RenderPass *rpass;
625         
626         rr->rectx = rectx;
627         rr->recty = recty;
628         
629         IMB_exr_multilayer_convert(exrhandle, rr, ml_addlayer_cb, ml_addpass_cb);
630
631         for (rl = rr->layers.first; rl; rl = rl->next) {
632                 rl->rectx = rectx;
633                 rl->recty = recty;
634
635                 for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
636                         rpass->rectx = rectx;
637                         rpass->recty = recty;
638                 }
639         }
640         
641         return rr;
642 }
643
644 /*********************************** Merge ***********************************/
645
646 static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
647 {
648         int y, ofs, copylen, tilex, tiley;
649         
650         copylen = tilex = rrpart->rectx;
651         tiley = rrpart->recty;
652         
653         if (rrpart->crop) { /* filters add pixel extra */
654                 tile += pixsize * (rrpart->crop + rrpart->crop * tilex);
655                 
656                 copylen = tilex - 2 * rrpart->crop;
657                 tiley -= 2 * rrpart->crop;
658                 
659                 ofs = (rrpart->tilerect.ymin + rrpart->crop) * rr->rectx + (rrpart->tilerect.xmin + rrpart->crop);
660                 target += pixsize * ofs;
661         }
662         else {
663                 ofs = (rrpart->tilerect.ymin * rr->rectx + rrpart->tilerect.xmin);
664                 target += pixsize * ofs;
665         }
666
667         copylen *= sizeof(float) * pixsize;
668         tilex *= pixsize;
669         ofs = pixsize * rr->rectx;
670
671         for (y = 0; y < tiley; y++) {
672                 memcpy(target, tile, copylen);
673                 target += ofs;
674                 tile += tilex;
675         }
676 }
677
678 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
679 /* no test happens here if it fits... we also assume layers are in sync */
680 /* is used within threads */
681 void render_result_merge(RenderResult *rr, RenderResult *rrpart)
682 {
683         RenderLayer *rl, *rlp;
684         RenderPass *rpass, *rpassp;
685         
686         for (rl = rr->layers.first, rlp = rrpart->layers.first; rl && rlp; rl = rl->next, rlp = rlp->next) {
687                 
688                 /* combined */
689                 if (rl->rectf && rlp->rectf)
690                         do_merge_tile(rr, rrpart, rl->rectf, rlp->rectf, 4);
691                 
692                 /* passes are allocated in sync */
693                 for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp; rpass = rpass->next, rpassp = rpassp->next) {
694                         do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
695                 }
696         }
697 }
698
699 /* for passes read from files, these have names stored */
700 static char *make_pass_name(RenderPass *rpass, int chan)
701 {
702         static char name[16];
703         int len;
704         
705         BLI_strncpy(name, rpass->name, EXR_PASS_MAXNAME);
706         len = strlen(name);
707         name[len] = '.';
708         name[len + 1] = rpass->chan_id[chan];
709         name[len + 2] = 0;
710
711         return name;
712 }
713
714 /* filename already made absolute */
715 /* called from within UI, saves both rendered result as a file-read result */
716 int RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, int compress)
717 {
718         RenderLayer *rl;
719         RenderPass *rpass;
720         void *exrhandle = IMB_exr_get_handle();
721         int success;
722
723         BLI_make_existing_file(filename);
724         
725         /* composite result */
726         if (rr->rectf) {
727                 IMB_exr_add_channel(exrhandle, "Composite", "Combined.R", 4, 4 * rr->rectx, rr->rectf);
728                 IMB_exr_add_channel(exrhandle, "Composite", "Combined.G", 4, 4 * rr->rectx, rr->rectf + 1);
729                 IMB_exr_add_channel(exrhandle, "Composite", "Combined.B", 4, 4 * rr->rectx, rr->rectf + 2);
730                 IMB_exr_add_channel(exrhandle, "Composite", "Combined.A", 4, 4 * rr->rectx, rr->rectf + 3);
731         }
732         
733         /* add layers/passes and assign channels */
734         for (rl = rr->layers.first; rl; rl = rl->next) {
735                 
736                 /* combined */
737                 if (rl->rectf) {
738                         int a, xstride = 4;
739                         for (a = 0; a < xstride; a++)
740                                 IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
741                                                     xstride, xstride * rr->rectx, rl->rectf + a);
742                 }
743                 
744                 /* passes are allocated in sync */
745                 for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
746                         int a, xstride = rpass->channels;
747                         for (a = 0; a < xstride; a++) {
748                                 if (rpass->passtype)
749                                         IMB_exr_add_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
750                                                             xstride, xstride * rr->rectx, rpass->rect + a);
751                                 else
752                                         IMB_exr_add_channel(exrhandle, rl->name, make_pass_name(rpass, a), 
753                                                             xstride, xstride * rr->rectx, rpass->rect + a);
754                         }
755                 }
756         }
757
758         /* when the filename has no permissions, this can fail */
759         if (IMB_exr_begin_write(exrhandle, filename, rr->rectx, rr->recty, compress)) {
760                 IMB_exr_write_channels(exrhandle);
761                 success = TRUE;
762         }
763         else {
764                 /* TODO, get the error from openexr's exception */
765                 BKE_report(reports, RPT_ERROR, "Error Writing Render Result, see console");
766                 success = FALSE;
767         }
768         IMB_exr_close(exrhandle);
769
770         return success;
771 }
772
773 /**************************** Single Layer Rendering *************************/
774
775 void render_result_single_layer_begin(Render *re)
776 {
777         /* all layers except the active one get temporally pushed away */
778
779         /* officially pushed result should be NULL... error can happen with do_seq */
780         RE_FreeRenderResult(re->pushedresult);
781         
782         re->pushedresult = re->result;
783         re->result = NULL;
784 }
785
786 /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
787 void render_result_single_layer_end(Render *re)
788 {
789         SceneRenderLayer *srl;
790         RenderLayer *rlpush;
791         RenderLayer *rl;
792         int nr;
793
794         if (re->result == NULL) {
795                 printf("pop render result error; no current result!\n");
796                 return;
797         }
798
799         if (!re->pushedresult)
800                 return;
801
802         if (re->pushedresult->rectx == re->result->rectx && re->pushedresult->recty == re->result->recty) {
803                 /* find which layer in re->pushedresult should be replaced */
804                 rl = re->result->layers.first;
805                 
806                 /* render result should be empty after this */
807                 BLI_remlink(&re->result->layers, rl);
808                 
809                 /* reconstruct render result layers */
810                 for (nr = 0, srl = re->scene->r.layers.first; srl; srl = srl->next, nr++) {
811                         if (nr == re->r.actlay)
812                                 BLI_addtail(&re->result->layers, rl);
813                         else {
814                                 rlpush = RE_GetRenderLayer(re->pushedresult, srl->name);
815                                 if (rlpush) {
816                                         BLI_remlink(&re->pushedresult->layers, rlpush);
817                                         BLI_addtail(&re->result->layers, rlpush);
818                                 }
819                         }
820                 }
821         }
822
823         RE_FreeRenderResult(re->pushedresult);
824         re->pushedresult = NULL;
825 }
826
827 /************************* EXR Tile File Rendering ***************************/
828
829 static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart)
830 {
831         RenderLayer *rlp;
832         RenderPass *rpassp;
833         int offs, partx, party;
834         
835         BLI_lock_thread(LOCK_IMAGE);
836         
837         for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
838                 
839                 if (rrpart->crop) { /* filters add pixel extra */
840                         offs = (rrpart->crop + rrpart->crop * rrpart->rectx);
841                 }
842                 else {
843                         offs = 0;
844                 }
845                 
846                 /* combined */
847                 if (rlp->rectf) {
848                         int a, xstride = 4;
849                         for (a = 0; a < xstride; a++)
850                                 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(SCE_PASS_COMBINED, a), 
851                                                     xstride, xstride * rrpart->rectx, rlp->rectf + a + xstride * offs);
852                 }
853                 
854                 /* passes are allocated in sync */
855                 for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
856                         int a, xstride = rpassp->channels;
857                         for (a = 0; a < xstride; a++)
858                                 IMB_exr_set_channel(rr->exrhandle, rlp->name, get_pass_name(rpassp->passtype, a), 
859                                                     xstride, xstride * rrpart->rectx, rpassp->rect + a + xstride * offs);
860                 }
861                 
862         }
863
864         party = rrpart->tilerect.ymin + rrpart->crop;
865         partx = rrpart->tilerect.xmin + rrpart->crop;
866         IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
867
868         BLI_unlock_thread(LOCK_IMAGE);
869 }
870
871 static void save_empty_result_tiles(Render *re)
872 {
873         RenderPart *pa;
874         RenderResult *rr;
875         
876         for (rr = re->result; rr; rr = rr->next) {
877                 IMB_exrtile_clear_channels(rr->exrhandle);
878                 
879                 for (pa = re->parts.first; pa; pa = pa->next) {
880                         if (pa->ready == 0) {
881                                 int party = pa->disprect.ymin - re->disprect.ymin + pa->crop;
882                                 int partx = pa->disprect.xmin - re->disprect.xmin + pa->crop;
883                                 IMB_exrtile_write_channels(rr->exrhandle, partx, party, 0);
884                         }
885                 }
886         }
887 }
888
889 /* begin write of exr tile file */
890 void render_result_exr_file_begin(Render *re)
891 {
892         RenderResult *rr;
893         char str[FILE_MAX];
894         
895         for (rr = re->result; rr; rr = rr->next) {
896                 render_result_exr_file_path(re->scene, rr->sample_nr, str);
897         
898                 printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
899                 IMB_exrtile_begin_write(rr->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
900         }
901 }
902
903 /* end write of exr tile file, read back first sample */
904 void render_result_exr_file_end(Render *re)
905 {
906         RenderResult *rr;
907
908         save_empty_result_tiles(re);
909         
910         for (rr = re->result; rr; rr = rr->next) {
911                 IMB_exr_close(rr->exrhandle);
912                 rr->exrhandle = NULL;
913         }
914         
915         render_result_free_list(&re->fullresult, re->result);
916         re->result = NULL;
917
918         render_result_exr_file_read(re, 0);
919 }
920
921 /* save part into exr file */
922 void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart)
923 {
924         for (; rr && rrpart; rr = rr->next, rrpart = rrpart->next)
925                 save_render_result_tile(rr, rrpart);
926 }
927
928 /* path to temporary exr file */
929 void render_result_exr_file_path(Scene *scene, int sample, char *filepath)
930 {
931         char di[FILE_MAX], name[FILE_MAXFILE + MAX_ID_NAME + 100], fi[FILE_MAXFILE];
932         
933         BLI_strncpy(di, G.main->name, FILE_MAX);
934         BLI_splitdirstring(di, fi);
935         
936         if (sample == 0)
937                 BLI_snprintf(name, sizeof(name), "%s_%s.exr", fi, scene->id.name + 2);
938         else
939                 BLI_snprintf(name, sizeof(name), "%s_%s%d.exr", fi, scene->id.name + 2, sample);
940
941         BLI_make_file_string("/", filepath, BLI_temporary_dir(), name);
942 }
943
944 /* only for temp buffer files, makes exact copy of render result */
945 int render_result_exr_file_read(Render *re, int sample)
946 {
947         char str[FILE_MAX];
948         int success;
949
950         RE_FreeRenderResult(re->result);
951         re->result = render_result_new(re, &re->disprect, 0, RR_USE_MEM);
952
953         render_result_exr_file_path(re->scene, sample, str);
954         printf("read exr tmp file: %s\n", str);
955
956         if (render_result_exr_file_read_path(re->result, str)) {
957                 success = TRUE;
958         }
959         else {
960                 printf("cannot read: %s\n", str);
961                 success = FALSE;
962
963         }
964
965         return success;
966 }
967
968 /* called for reading temp files, and for external engines */
969 int render_result_exr_file_read_path(RenderResult *rr, const char *filepath)
970 {
971         RenderLayer *rl;
972         RenderPass *rpass;
973         void *exrhandle = IMB_exr_get_handle();
974         int rectx, recty;
975
976         if (IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty) == 0) {
977                 printf("failed being read %s\n", filepath);
978                 IMB_exr_close(exrhandle);
979                 return 0;
980         }
981
982         if (rr == NULL || rectx != rr->rectx || recty != rr->recty) {
983                 if (rr)
984                         printf("error in reading render result: dimensions don't match\n");
985                 else
986                         printf("error in reading render result: NULL result pointer\n");
987                 IMB_exr_close(exrhandle);
988                 return 0;
989         }
990
991         for (rl = rr->layers.first; rl; rl = rl->next) {
992                 /* combined */
993                 if (rl->rectf) {
994                         int a, xstride = 4;
995                         for (a = 0; a < xstride; a++)
996                                 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(SCE_PASS_COMBINED, a), 
997                                                     xstride, xstride * rectx, rl->rectf + a);
998                 }
999                 
1000                 /* passes are allocated in sync */
1001                 for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
1002                         int a, xstride = rpass->channels;
1003                         for (a = 0; a < xstride; a++)
1004                                 IMB_exr_set_channel(exrhandle, rl->name, get_pass_name(rpass->passtype, a), 
1005                                                     xstride, xstride * rectx, rpass->rect + a);
1006
1007                         BLI_strncpy(rpass->name, get_pass_name(rpass->passtype, -1), sizeof(rpass->name));
1008                 }
1009         }
1010
1011         IMB_exr_read_channels(exrhandle);
1012         IMB_exr_close(exrhandle);
1013
1014         return 1;
1015 }
1016
1017 /*************************** Combined Pixel Rect *****************************/
1018
1019 ImBuf *render_result_rect_to_ibuf(RenderResult *rr, RenderData *rd)
1020 {
1021         int flags = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE) ? IB_cm_predivide : 0;
1022         ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, flags);
1023         
1024         /* if not exists, BKE_imbuf_write makes one */
1025         ibuf->rect = (unsigned int *)rr->rect32;
1026         ibuf->rect_float = rr->rectf;
1027         ibuf->zbuf_float = rr->rectz;
1028         
1029         /* float factor for random dither, imbuf takes care of it */
1030         ibuf->dither = rd->dither_intensity;
1031         
1032         /* prepare to gamma correct to sRGB color space */
1033         if (rd->color_mgt_flag & R_COLOR_MANAGEMENT) {
1034                 /* sequence editor can generate 8bpc render buffers */
1035                 if (ibuf->rect) {
1036                         ibuf->profile = IB_PROFILE_SRGB;
1037                         if (BKE_imtype_valid_depths(rd->im_format.imtype) & (R_IMF_CHAN_DEPTH_12 | R_IMF_CHAN_DEPTH_16 | R_IMF_CHAN_DEPTH_24 | R_IMF_CHAN_DEPTH_32))
1038                                 IMB_float_from_rect(ibuf);
1039                 }
1040                 else {
1041                         ibuf->profile = IB_PROFILE_LINEAR_RGB;
1042                 }
1043         }
1044
1045         /* color -> grayscale */
1046         /* editing directly would alter the render view */
1047         if (rd->im_format.planes == R_IMF_PLANES_BW) {
1048                 ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
1049                 IMB_color_to_bw(ibuf_bw);
1050                 IMB_freeImBuf(ibuf);
1051                 ibuf = ibuf_bw;
1052         }
1053
1054         return ibuf;
1055 }
1056
1057 void render_result_rect_from_ibuf(RenderResult *rr, RenderData *rd, ImBuf *ibuf)
1058 {
1059         if (ibuf->rect_float) {
1060                 /* color management: when off ensure rectf is non-lin, since thats what the internal
1061                  * render engine delivers */
1062                 int profile_to = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
1063                 int profile_from = (ibuf->profile == IB_PROFILE_LINEAR_RGB) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
1064                 int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
1065
1066                 if (!rr->rectf)
1067                         rr->rectf = MEM_mallocN(4 * sizeof(float) * rr->rectx * rr->recty, "render_seq rectf");
1068                 
1069                 IMB_buffer_float_from_float(rr->rectf, ibuf->rect_float,
1070                                             4, profile_to, profile_from, predivide,
1071                                             rr->rectx, rr->recty, rr->rectx, rr->rectx);
1072                 
1073                 /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
1074                  * can hang around when sequence render has rendered a 32 bits one before */
1075                 if (rr->rect32) {
1076                         MEM_freeN(rr->rect32);
1077                         rr->rect32 = NULL;
1078                 }
1079         }
1080         else if (ibuf->rect) {
1081                 if (!rr->rect32)
1082                         rr->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
1083
1084                 memcpy(rr->rect32, ibuf->rect, 4 * rr->rectx * rr->recty);
1085
1086                 /* Same things as above, old rectf can hang around from previous render. */
1087                 if (rr->rectf) {
1088                         MEM_freeN(rr->rectf);
1089                         rr->rectf = NULL;
1090                 }
1091         }
1092 }
1093
1094 void render_result_rect_fill_zero(RenderResult *rr)
1095 {
1096         if (rr->rectf)
1097                 memset(rr->rectf, 0, 4 * sizeof(float) * rr->rectx * rr->recty);
1098         else if (rr->rect32)
1099                 memset(rr->rect32, 0, 4 * rr->rectx * rr->recty);
1100         else
1101                 rr->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
1102 }
1103
1104 void render_result_rect_get_pixels(RenderResult *rr, RenderData *rd, unsigned int *rect, int rectx, int recty)
1105 {
1106         if (rr->rect32) {
1107                 memcpy(rect, rr->rect32, sizeof(int) * rr->rectx * rr->recty);
1108         }
1109         else if (rr->rectf) {
1110                 int profile_from = (rd->color_mgt_flag & R_COLOR_MANAGEMENT) ? IB_PROFILE_LINEAR_RGB : IB_PROFILE_SRGB;
1111                 int predivide = (rd->color_mgt_flag & R_COLOR_MANAGEMENT_PREDIVIDE);
1112                 int dither = 0;
1113
1114                 IMB_buffer_byte_from_float((unsigned char *)rect, rr->rectf,
1115                                            4, dither, IB_PROFILE_SRGB, profile_from, predivide,
1116                                            rr->rectx, rr->recty, rr->rectx, rr->rectx);
1117         }
1118         else
1119                 /* else fill with black */
1120                 memset(rect, 0, sizeof(int) * rectx * recty);
1121 }
1122