Blender  V2.93
render_result.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2006 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <errno.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 
29 #include "MEM_guardedalloc.h"
30 
31 #include "BLI_ghash.h"
32 #include "BLI_hash_md5.h"
33 #include "BLI_listbase.h"
34 #include "BLI_path_util.h"
35 #include "BLI_rect.h"
36 #include "BLI_string.h"
37 #include "BLI_string_utils.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40 
41 #include "BKE_appdir.h"
42 #include "BKE_camera.h"
43 #include "BKE_global.h"
44 #include "BKE_image.h"
45 #include "BKE_report.h"
46 #include "BKE_scene.h"
47 
48 #include "IMB_colormanagement.h"
49 #include "IMB_imbuf.h"
50 #include "IMB_imbuf_types.h"
51 
53 
54 #include "RE_engine.h"
55 
56 #include "render_result.h"
57 #include "render_types.h"
58 
59 /********************************** Free *************************************/
60 
62 {
63  while (rr->views.first) {
64  RenderView *rv = rr->views.first;
65  BLI_remlink(&rr->views, rv);
66 
67  if (rv->rect32) {
68  MEM_freeN(rv->rect32);
69  }
70 
71  if (rv->rectz) {
72  MEM_freeN(rv->rectz);
73  }
74 
75  if (rv->rectf) {
76  MEM_freeN(rv->rectf);
77  }
78 
79  MEM_freeN(rv);
80  }
81 
82  rr->have_combined = false;
83 }
84 
86 {
87  if (rr == NULL) {
88  return;
89  }
90 
91  while (rr->layers.first) {
92  RenderLayer *rl = rr->layers.first;
93 
94  while (rl->passes.first) {
95  RenderPass *rpass = rl->passes.first;
96  if (rpass->rect) {
97  MEM_freeN(rpass->rect);
98  }
99  BLI_remlink(&rl->passes, rpass);
100  MEM_freeN(rpass);
101  }
102  BLI_remlink(&rr->layers, rl);
103  MEM_freeN(rl);
104  }
105 
107 
108  if (rr->rect32) {
109  MEM_freeN(rr->rect32);
110  }
111  if (rr->rectz) {
112  MEM_freeN(rr->rectz);
113  }
114  if (rr->rectf) {
115  MEM_freeN(rr->rectf);
116  }
117  if (rr->text) {
118  MEM_freeN(rr->text);
119  }
120  if (rr->error) {
121  MEM_freeN(rr->error);
122  }
123 
125 
126  MEM_freeN(rr);
127 }
128 
131 {
132  RenderResult *rrnext;
133 
134  for (; rr; rr = rrnext) {
135  rrnext = rr->next;
136 
137  if (lb && lb->first) {
138  BLI_remlink(lb, rr);
139  }
140 
141  render_result_free(rr);
142  }
143 }
144 
145 /********************************* multiview *************************************/
146 
147 /* create a new views Listbase in rr without duplicating the memory pointers */
149 {
150  RenderView *rview;
151 
152  if (dst == NULL || src == NULL) {
153  return;
154  }
155 
156  for (rview = src->views.first; rview; rview = rview->next) {
157  RenderView *rv;
158 
159  rv = MEM_mallocN(sizeof(RenderView), "new render view");
160  BLI_addtail(&dst->views, rv);
161 
162  BLI_strncpy(rv->name, rview->name, sizeof(rv->name));
163  rv->rectf = rview->rectf;
164  rv->rectz = rview->rectz;
165  rv->rect32 = rview->rect32;
166  }
167 }
168 
169 /* free the views created temporarily */
171 {
172  if (rr == NULL) {
173  return;
174  }
175 
176  while (rr->views.first) {
177  RenderView *rv = rr->views.first;
178  BLI_remlink(&rr->views, rv);
179  MEM_freeN(rv);
180  }
181 }
182 
183 static char *set_pass_name(char *outname, const char *name, int channel, const char *chan_id)
184 {
185  const char *strings[2];
186  int strings_len = 0;
187  strings[strings_len++] = name;
188  char token[2];
189  if (channel >= 0) {
190  ARRAY_SET_ITEMS(token, chan_id[channel], '\0');
191  strings[strings_len++] = token;
192  }
193  BLI_string_join_array_by_sep_char(outname, EXR_PASS_MAXNAME, '.', strings, strings_len);
194  return outname;
195 }
196 
197 static void set_pass_full_name(
198  char *fullname, const char *name, int channel, const char *view, const char *chan_id)
199 {
200  const char *strings[3];
201  int strings_len = 0;
202  strings[strings_len++] = name;
203  if (view && view[0]) {
204  strings[strings_len++] = view;
205  }
206  char token[2];
207  if (channel >= 0) {
208  ARRAY_SET_ITEMS(token, chan_id[channel], '\0');
209  strings[strings_len++] = token;
210  }
211  BLI_string_join_array_by_sep_char(fullname, EXR_PASS_MAXNAME, '.', strings, strings_len);
212 }
213 
214 /********************************** New **************************************/
215 
217  RenderLayer *rl,
218  int channels,
219  const char *name,
220  const char *viewname,
221  const char *chan_id)
222 {
223  const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
224  RenderPass *rpass = MEM_callocN(sizeof(RenderPass), name);
225  size_t rectsize = ((size_t)rr->rectx) * rr->recty * channels;
226 
227  rpass->channels = channels;
228  rpass->rectx = rl->rectx;
229  rpass->recty = rl->recty;
230  rpass->view_id = view_id;
231 
232  BLI_strncpy(rpass->name, name, sizeof(rpass->name));
233  BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
234  BLI_strncpy(rpass->view, viewname, sizeof(rpass->view));
235  set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
236 
237  if (rl->exrhandle) {
238  int a;
239  for (a = 0; a < channels; a++) {
240  char passname[EXR_PASS_MAXNAME];
242  rl->name,
243  set_pass_name(passname, rpass->name, a, rpass->chan_id),
244  viewname,
245  0,
246  0,
247  NULL,
248  false);
249  }
250  }
251 
252  /* Always allocate combined for display, in case of save buffers
253  * other passes are not allocated and only saved to the EXR file. */
254  if (rl->exrhandle == NULL || STREQ(rpass->name, RE_PASSNAME_COMBINED)) {
255  float *rect;
256  int x;
257 
258  rpass->rect = MEM_callocN(sizeof(float) * rectsize, name);
259  if (rpass->rect == NULL) {
260  MEM_freeN(rpass);
261  return NULL;
262  }
263 
264  if (STREQ(rpass->name, RE_PASSNAME_VECTOR)) {
265  /* initialize to max speed */
266  rect = rpass->rect;
267  for (x = rectsize - 1; x >= 0; x--) {
268  rect[x] = PASS_VECTOR_MAX;
269  }
270  }
271  else if (STREQ(rpass->name, RE_PASSNAME_Z)) {
272  rect = rpass->rect;
273  for (x = rectsize - 1; x >= 0; x--) {
274  rect[x] = 10e10;
275  }
276  }
277  }
278 
279  BLI_addtail(&rl->passes, rpass);
280 
281  return rpass;
282 }
283 
284 /* called by main render as well for parts */
285 /* will read info from Render *re to define layers */
286 /* called in threads */
287 /* re->winx,winy is coordinate space of entire image, partrct the part within */
289  Render *re, rcti *partrct, int savebuffers, const char *layername, const char *viewname)
290 {
291  RenderResult *rr;
292  RenderLayer *rl;
293  RenderView *rv;
294  int rectx, recty;
295 
296  rectx = BLI_rcti_size_x(partrct);
297  recty = BLI_rcti_size_y(partrct);
298 
299  if (rectx <= 0 || recty <= 0) {
300  return NULL;
301  }
302 
303  rr = MEM_callocN(sizeof(RenderResult), "new render result");
304  rr->rectx = rectx;
305  rr->recty = recty;
306  rr->renrect.xmin = 0;
307  rr->renrect.xmax = rectx;
308 
309  /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
310  rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
311  rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
312  rr->tilerect.ymin = partrct->ymin - re->disprect.ymin;
313  rr->tilerect.ymax = partrct->ymax - re->disprect.ymin;
314 
315  if (savebuffers) {
316  rr->do_exr_tile = true;
317  }
318 
319  render_result_views_new(rr, &re->r);
320 
321  /* check renderdata for amount of layers */
322  FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
323  if (layername && layername[0]) {
324  if (!STREQ(view_layer->name, layername)) {
325  continue;
326  }
327  }
328 
329  rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
330  BLI_addtail(&rr->layers, rl);
331 
332  BLI_strncpy(rl->name, view_layer->name, sizeof(rl->name));
333  rl->layflag = view_layer->layflag;
334 
335  /* for debugging: view_layer->passflag | SCE_PASS_RAYHITS; */
336  rl->passflag = view_layer->passflag;
337 
338  rl->rectx = rectx;
339  rl->recty = recty;
340 
341  if (rr->do_exr_tile) {
343  }
344 
345  for (rv = rr->views.first; rv; rv = rv->next) {
346  const char *view = rv->name;
347 
348  if (viewname && viewname[0]) {
349  if (!STREQ(view, viewname)) {
350  continue;
351  }
352  }
353 
354  if (rr->do_exr_tile) {
356  }
357 
358 #define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id) \
359  do { \
360  if (render_layer_add_pass(rr, rl, channels, name, viewname, chan_id) == NULL) { \
361  render_result_free(rr); \
362  return NULL; \
363  } \
364  } while (false)
365 
366  /* a renderlayer should always have a Combined pass*/
367  render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA");
368 
369  if (view_layer->passflag & SCE_PASS_Z) {
371  }
372  if (view_layer->passflag & SCE_PASS_VECTOR) {
374  }
375  if (view_layer->passflag & SCE_PASS_NORMAL) {
377  }
378  if (view_layer->passflag & SCE_PASS_UV) {
379  RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_UV, view, "UVA");
380  }
381  if (view_layer->passflag & SCE_PASS_EMIT) {
383  }
384  if (view_layer->passflag & SCE_PASS_AO) {
385  RENDER_LAYER_ADD_PASS_SAFE(rr, rl, 3, RE_PASSNAME_AO, view, "RGB");
386  }
387  if (view_layer->passflag & SCE_PASS_ENVIRONMENT) {
389  }
390  if (view_layer->passflag & SCE_PASS_SHADOW) {
392  }
393  if (view_layer->passflag & SCE_PASS_INDEXOB) {
395  }
396  if (view_layer->passflag & SCE_PASS_INDEXMA) {
398  }
399  if (view_layer->passflag & SCE_PASS_MIST) {
401  }
402  if (rl->passflag & SCE_PASS_RAYHITS) {
404  }
405  if (view_layer->passflag & SCE_PASS_DIFFUSE_DIRECT) {
407  }
408  if (view_layer->passflag & SCE_PASS_DIFFUSE_INDIRECT) {
410  }
411  if (view_layer->passflag & SCE_PASS_DIFFUSE_COLOR) {
413  }
414  if (view_layer->passflag & SCE_PASS_GLOSSY_DIRECT) {
416  }
417  if (view_layer->passflag & SCE_PASS_GLOSSY_INDIRECT) {
419  }
420  if (view_layer->passflag & SCE_PASS_GLOSSY_COLOR) {
422  }
423  if (view_layer->passflag & SCE_PASS_TRANSM_DIRECT) {
425  }
426  if (view_layer->passflag & SCE_PASS_TRANSM_INDIRECT) {
428  }
429  if (view_layer->passflag & SCE_PASS_TRANSM_COLOR) {
431  }
432  if (view_layer->passflag & SCE_PASS_SUBSURFACE_DIRECT) {
434  }
435  if (view_layer->passflag & SCE_PASS_SUBSURFACE_INDIRECT) {
437  }
438  if (view_layer->passflag & SCE_PASS_SUBSURFACE_COLOR) {
440  }
441 #undef RENDER_LAYER_ADD_PASS_SAFE
442  }
443  }
445 
446  /* Preview-render doesn't do layers, so we make a default one. */
447  if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
448  rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
449  BLI_addtail(&rr->layers, rl);
450 
451  rl->rectx = rectx;
452  rl->recty = recty;
453 
454  /* duplicate code... */
455  if (rr->do_exr_tile) {
457  }
458 
459  for (rv = rr->views.first; rv; rv = rv->next) {
460  const char *view = rv->name;
461 
462  if (viewname && viewname[0]) {
463  if (!STREQ(view, viewname)) {
464  continue;
465  }
466  }
467 
468  if (rr->do_exr_tile) {
470  }
471 
472  /* a renderlayer should always have a Combined pass */
473  render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA");
474  }
475 
476  /* note, this has to be in sync with scene.c */
477  rl->layflag = 0x7FFF; /* solid ztra halo strand */
479 
480  re->active_view_layer = 0;
481  }
482 
483  /* border render; calculate offset for use in compositor. compo is centralized coords */
484  /* XXX obsolete? I now use it for drawing border render offset (ton) */
485  rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
486  rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
487 
488  return rr;
489 }
490 
491 void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
492 {
493  RenderLayer *rl;
494  RenderPass *main_rp;
495 
496  for (rl = rr->layers.first; rl; rl = rl->next) {
497  RenderLayer *main_rl = BLI_findstring(
498  &re->result->layers, rl->name, offsetof(RenderLayer, name));
499  if (!main_rl) {
500  continue;
501  }
502 
503  for (main_rp = main_rl->passes.first; main_rp; main_rp = main_rp->next) {
504  if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) {
505  continue;
506  }
507 
508  /* Compare fullname to make sure that the view also is equal. */
510  &rl->passes, main_rp->fullname, offsetof(RenderPass, fullname));
511  if (!rp) {
513  rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id);
514  }
515  }
516  }
517 }
518 
520  const char *name,
521  int channels,
522  const char *chan_id,
523  const char *layername,
524  const char *viewname)
525 {
526  RenderLayer *rl;
527  RenderPass *rp;
528  RenderView *rv;
529 
530  for (rl = rr->layers.first; rl; rl = rl->next) {
531  if (layername && layername[0] && !STREQ(rl->name, layername)) {
532  continue;
533  }
534 
535  for (rv = rr->views.first; rv; rv = rv->next) {
536  const char *view = rv->name;
537 
538  if (viewname && viewname[0] && !STREQ(view, viewname)) {
539  continue;
540  }
541 
542  /* Ensure that the pass doesn't exist yet. */
543  for (rp = rl->passes.first; rp; rp = rp->next) {
544  if (!STREQ(rp->name, name)) {
545  continue;
546  }
547  if (!STREQ(rp->view, view)) {
548  continue;
549  }
550  break;
551  }
552 
553  if (!rp) {
554  render_layer_add_pass(rr, rl, channels, name, view, chan_id);
555  }
556  }
557  }
558 }
559 
560 static int passtype_from_name(const char *name)
561 {
562  const char delim[] = {'.', '\0'};
563  const char *sep, *suf;
564  int len = BLI_str_partition(name, delim, &sep, &suf);
565 
566 #define CHECK_PASS(NAME) \
567  if (STREQLEN(name, RE_PASSNAME_##NAME, len)) { \
568  return SCE_PASS_##NAME; \
569  } \
570  ((void)0)
571 
572  CHECK_PASS(COMBINED);
573  CHECK_PASS(Z);
574  CHECK_PASS(VECTOR);
576  CHECK_PASS(UV);
577  CHECK_PASS(EMIT);
578  CHECK_PASS(SHADOW);
579  CHECK_PASS(AO);
580  CHECK_PASS(ENVIRONMENT);
581  CHECK_PASS(INDEXOB);
582  CHECK_PASS(INDEXMA);
583  CHECK_PASS(MIST);
584  CHECK_PASS(RAYHITS);
585  CHECK_PASS(DIFFUSE_DIRECT);
586  CHECK_PASS(DIFFUSE_INDIRECT);
587  CHECK_PASS(DIFFUSE_COLOR);
588  CHECK_PASS(GLOSSY_DIRECT);
589  CHECK_PASS(GLOSSY_INDIRECT);
590  CHECK_PASS(GLOSSY_COLOR);
591  CHECK_PASS(TRANSM_DIRECT);
592  CHECK_PASS(TRANSM_INDIRECT);
593  CHECK_PASS(TRANSM_COLOR);
594  CHECK_PASS(SUBSURFACE_DIRECT);
595  CHECK_PASS(SUBSURFACE_INDIRECT);
596  CHECK_PASS(SUBSURFACE_COLOR);
597 
598 #undef CHECK_PASS
599  return 0;
600 }
601 
602 /* callbacks for render_result_new_from_exr */
603 static void *ml_addlayer_cb(void *base, const char *str)
604 {
605  RenderResult *rr = base;
606  RenderLayer *rl;
607 
608  rl = MEM_callocN(sizeof(RenderLayer), "new render layer");
609  BLI_addtail(&rr->layers, rl);
610 
612  return rl;
613 }
614 
615 static void ml_addpass_cb(void *base,
616  void *lay,
617  const char *name,
618  float *rect,
619  int totchan,
620  const char *chan_id,
621  const char *view)
622 {
623  RenderResult *rr = base;
624  RenderLayer *rl = lay;
625  RenderPass *rpass = MEM_callocN(sizeof(RenderPass), "loaded pass");
626 
627  BLI_addtail(&rl->passes, rpass);
628  rpass->channels = totchan;
629  rl->passflag |= passtype_from_name(name);
630 
631  /* channel id chars */
632  BLI_strncpy(rpass->chan_id, chan_id, sizeof(rpass->chan_id));
633 
634  rpass->rect = rect;
635  BLI_strncpy(rpass->name, name, EXR_PASS_MAXNAME);
636  BLI_strncpy(rpass->view, view, sizeof(rpass->view));
637  set_pass_full_name(rpass->fullname, name, -1, view, rpass->chan_id);
638 
639  if (view[0] != '\0') {
640  rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
641  }
642  else {
643  rpass->view_id = 0;
644  }
645 }
646 
647 static void *ml_addview_cb(void *base, const char *str)
648 {
649  RenderResult *rr = base;
650  RenderView *rv;
651 
652  rv = MEM_callocN(sizeof(RenderView), "new render view");
654 
655  /* For stereo drawing we need to ensure:
656  * STEREO_LEFT_NAME == STEREO_LEFT_ID and
657  * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
658 
659  if (STREQ(str, STEREO_LEFT_NAME)) {
660  BLI_addhead(&rr->views, rv);
661  }
662  else if (STREQ(str, STEREO_RIGHT_NAME)) {
663  RenderView *left_rv = BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name));
664 
665  if (left_rv == NULL) {
666  BLI_addhead(&rr->views, rv);
667  }
668  else {
669  BLI_insertlinkafter(&rr->views, left_rv, rv);
670  }
671  }
672  else {
673  BLI_addtail(&rr->views, rv);
674  }
675 
676  return rv;
677 }
678 
679 static int order_render_passes(const void *a, const void *b)
680 {
681  // 1 if a is after b
682  RenderPass *rpa = (RenderPass *)a;
683  RenderPass *rpb = (RenderPass *)b;
684  unsigned int passtype_a = passtype_from_name(rpa->name);
685  unsigned int passtype_b = passtype_from_name(rpb->name);
686 
687  /* Render passes with default type always go first. */
688  if (passtype_b && !passtype_a) {
689  return 1;
690  }
691  if (passtype_a && !passtype_b) {
692  return 0;
693  }
694 
695  if (passtype_a && passtype_b) {
696  if (passtype_a > passtype_b) {
697  return 1;
698  }
699  if (passtype_a < passtype_b) {
700  return 0;
701  }
702  }
703  else {
704  int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME);
705  if (cmp > 0) {
706  return 1;
707  }
708  if (cmp < 0) {
709  return 0;
710  }
711  }
712 
713  /* they have the same type */
714  /* left first */
715  if (STREQ(rpa->view, STEREO_LEFT_NAME)) {
716  return 0;
717  }
718  if (STREQ(rpb->view, STEREO_LEFT_NAME)) {
719  return 1;
720  }
721 
722  /* right second */
723  if (STREQ(rpa->view, STEREO_RIGHT_NAME)) {
724  return 0;
725  }
726  if (STREQ(rpb->view, STEREO_RIGHT_NAME)) {
727  return 1;
728  }
729 
730  /* remaining in ascending id order */
731  return (rpa->view_id < rpb->view_id);
732 }
733 
739  void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
740 {
741  RenderResult *rr = MEM_callocN(sizeof(RenderResult), __func__);
742  RenderLayer *rl;
743  RenderPass *rpass;
744  const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(
746 
747  rr->rectx = rectx;
748  rr->recty = recty;
749 
751 
752  for (rl = rr->layers.first; rl; rl = rl->next) {
753  rl->rectx = rectx;
754  rl->recty = recty;
755 
757 
758  for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
759  rpass->rectx = rectx;
760  rpass->recty = recty;
761 
762  if (rpass->channels >= 3) {
764  rpass->rectx,
765  rpass->recty,
766  rpass->channels,
767  colorspace,
768  to_colorspace,
769  predivide);
770  }
771  }
772  }
773 
774  return rr;
775 }
776 
777 void render_result_view_new(RenderResult *rr, const char *viewname)
778 {
779  RenderView *rv = MEM_callocN(sizeof(RenderView), "new render view");
780  BLI_addtail(&rr->views, rv);
781  BLI_strncpy(rv->name, viewname, sizeof(rv->name));
782 }
783 
785 {
786  SceneRenderView *srv;
787 
788  /* clear previously existing views - for sequencer */
790 
791  /* check renderdata for amount of views */
792  if ((rd->scemode & R_MULTIVIEW)) {
793  for (srv = rd->views.first; srv; srv = srv->next) {
794  if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) {
795  continue;
796  }
797  render_result_view_new(rr, srv->name);
798  }
799  }
800 
801  /* we always need at least one view */
802  if (BLI_listbase_count_at_most(&rr->views, 1) == 0) {
803  render_result_view_new(rr, "");
804  }
805 }
806 
808 {
809  RenderView *rv = rr->views.first;
810  return (rv && (rv->next || rv->name[0]));
811 }
812 
813 /*********************************** Merge ***********************************/
814 
815 static void do_merge_tile(
816  RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
817 {
818  int y, tilex, tiley;
819  size_t ofs, copylen;
820 
821  copylen = tilex = rrpart->rectx;
822  tiley = rrpart->recty;
823 
824  ofs = (((size_t)rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
825  target += pixsize * ofs;
826 
827  copylen *= sizeof(float) * pixsize;
828  tilex *= pixsize;
829  ofs = pixsize * rr->rectx;
830 
831  for (y = 0; y < tiley; y++) {
832  memcpy(target, tile, copylen);
833  target += ofs;
834  tile += tilex;
835  }
836 }
837 
838 /* used when rendering to a full buffer, or when reading the exr part-layer-pass file */
839 /* no test happens here if it fits... we also assume layers are in sync */
840 /* is used within threads */
842 {
843  RenderLayer *rl, *rlp;
844  RenderPass *rpass, *rpassp;
845 
846  for (rl = rr->layers.first; rl; rl = rl->next) {
847  rlp = RE_GetRenderLayer(rrpart, rl->name);
848  if (rlp) {
849  /* Passes are allocated in sync. */
850  for (rpass = rl->passes.first, rpassp = rlp->passes.first; rpass && rpassp;
851  rpass = rpass->next) {
852  /* For save buffers, skip any passes that are only saved to disk. */
853  if (rpass->rect == NULL || rpassp->rect == NULL) {
854  continue;
855  }
856  /* Renderresult have all passes, renderpart only the active view's passes. */
857  if (!STREQ(rpassp->fullname, rpass->fullname)) {
858  continue;
859  }
860 
861  do_merge_tile(rr, rrpart, rpass->rect, rpassp->rect, rpass->channels);
862 
863  /* manually get next render pass */
864  rpassp = rpassp->next;
865  }
866  }
867  }
868 }
869 
870 /* Called from the UI and render pipeline, to save multilayer and multiview
871  * images, optionally isolating a specific, view, layer or RGBA/Z pass. */
873  RenderResult *rr,
874  const char *filename,
875  ImageFormatData *imf,
876  const char *view,
877  int layer)
878 {
879  void *exrhandle = IMB_exr_get_handle();
880  const bool half_float = (imf && imf->depth == R_IMF_CHAN_DEPTH_16);
881  const bool multi_layer = !(imf && imf->imtype == R_IMF_IMTYPE_OPENEXR);
882  const bool write_z = !multi_layer && (imf && (imf->flag & R_IMF_FLAG_ZBUF));
883 
884  /* Write first layer if not multilayer and no layer was specified. */
885  if (!multi_layer && layer == -1) {
886  layer = 0;
887  }
888 
889  /* First add views since IMB_exr_add_channel checks number of views. */
890  if (render_result_has_views(rr)) {
891  LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
892  if (!view || STREQ(view, rview->name)) {
893  IMB_exr_add_view(exrhandle, rview->name);
894  }
895  }
896  }
897 
898  /* Compositing result. */
899  if (rr->have_combined) {
900  LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
901  if (!rview->rectf) {
902  continue;
903  }
904 
905  const char *viewname = rview->name;
906  if (view) {
907  if (!STREQ(view, viewname)) {
908  continue;
909  }
910 
911  viewname = "";
912  }
913 
914  /* Skip compositing if only a single other layer is requested. */
915  if (!multi_layer && layer != 0) {
916  continue;
917  }
918 
919  for (int a = 0; a < 4; a++) {
920  char passname[EXR_PASS_MAXNAME];
921  char layname[EXR_PASS_MAXNAME];
922  const char *chan_id = "RGBA";
923 
924  if (multi_layer) {
925  set_pass_name(passname, "Combined", a, chan_id);
926  BLI_strncpy(layname, "Composite", sizeof(layname));
927  }
928  else {
929  passname[0] = chan_id[a];
930  passname[1] = '\0';
931  layname[0] = '\0';
932  }
933 
934  IMB_exr_add_channel(exrhandle,
935  layname,
936  passname,
937  viewname,
938  4,
939  4 * rr->rectx,
940  rview->rectf + a,
941  half_float);
942  }
943 
944  if (write_z && rview->rectz) {
945  const char *layname = (multi_layer) ? "Composite" : "";
946  IMB_exr_add_channel(exrhandle, layname, "Z", viewname, 1, rr->rectx, rview->rectz, false);
947  }
948  }
949  }
950 
951  /* Other render layers. */
952  int nr = (rr->have_combined) ? 1 : 0;
953  for (RenderLayer *rl = rr->layers.first; rl; rl = rl->next, nr++) {
954  /* Skip other render layers if requested. */
955  if (!multi_layer && nr != layer) {
956  continue;
957  }
958 
959  LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
960  /* Skip non-RGBA and Z passes if not using multi layer. */
961  if (!multi_layer && !(STREQ(rp->name, RE_PASSNAME_COMBINED) || STREQ(rp->name, "") ||
962  (STREQ(rp->name, RE_PASSNAME_Z) && write_z))) {
963  continue;
964  }
965 
966  /* Skip pass if it does not match the requested view(s). */
967  const char *viewname = rp->view;
968  if (view) {
969  if (!STREQ(view, viewname)) {
970  continue;
971  }
972 
973  viewname = "";
974  }
975 
976  /* We only store RGBA passes as half float, for
977  * others precision loss can be problematic. */
978  bool pass_half_float = half_float &&
979  (STR_ELEM(rp->chan_id, "RGB", "RGBA", "R", "G", "B", "A"));
980 
981  for (int a = 0; a < rp->channels; a++) {
982  /* Save Combined as RGBA if single layer save. */
983  char passname[EXR_PASS_MAXNAME];
984  char layname[EXR_PASS_MAXNAME];
985 
986  if (multi_layer) {
987  set_pass_name(passname, rp->name, a, rp->chan_id);
988  BLI_strncpy(layname, rl->name, sizeof(layname));
989  }
990  else {
991  passname[0] = rp->chan_id[a];
992  passname[1] = '\0';
993  layname[0] = '\0';
994  }
995 
996  IMB_exr_add_channel(exrhandle,
997  layname,
998  passname,
999  viewname,
1000  rp->channels,
1001  rp->channels * rr->rectx,
1002  rp->rect + a,
1003  pass_half_float);
1004  }
1005  }
1006  }
1007 
1008  errno = 0;
1009 
1010  BLI_make_existing_file(filename);
1011 
1012  int compress = (imf ? imf->exr_codec : 0);
1013  bool success = IMB_exr_begin_write(
1014  exrhandle, filename, rr->rectx, rr->recty, compress, rr->stamp_data);
1015  if (success) {
1016  IMB_exr_write_channels(exrhandle);
1017  }
1018  else {
1019  /* TODO, get the error from openexr's exception */
1020  BKE_reportf(
1021  reports, RPT_ERROR, "Error writing render result, %s (see console)", strerror(errno));
1022  }
1023 
1024  IMB_exr_close(exrhandle);
1025  return success;
1026 }
1027 
1028 /**************************** Single Layer Rendering *************************/
1029 
1031 {
1032  /* all layers except the active one get temporally pushed away */
1033 
1034  /* officially pushed result should be NULL... error can happen with do_seq */
1036 
1037  re->pushedresult = re->result;
1038  re->result = NULL;
1039 }
1040 
1041 /* if scemode is R_SINGLE_LAYER, at end of rendering, merge the both render results */
1043 {
1044  ViewLayer *view_layer;
1045  RenderLayer *rlpush;
1046  RenderLayer *rl;
1047  int nr;
1048 
1049  if (re->result == NULL) {
1050  printf("pop render result error; no current result!\n");
1051  return;
1052  }
1053 
1054  if (!re->pushedresult) {
1055  return;
1056  }
1057 
1058  if (re->pushedresult->rectx == re->result->rectx &&
1059  re->pushedresult->recty == re->result->recty) {
1060  /* find which layer in re->pushedresult should be replaced */
1061  rl = re->result->layers.first;
1062 
1063  /* render result should be empty after this */
1064  BLI_remlink(&re->result->layers, rl);
1065 
1066  /* reconstruct render result layers */
1067  for (nr = 0, view_layer = re->view_layers.first; view_layer;
1068  view_layer = view_layer->next, nr++) {
1069  if (nr == re->active_view_layer) {
1070  BLI_addtail(&re->result->layers, rl);
1071  }
1072  else {
1073  rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name);
1074  if (rlpush) {
1075  BLI_remlink(&re->pushedresult->layers, rlpush);
1076  BLI_addtail(&re->result->layers, rlpush);
1077  }
1078  }
1079  }
1080  }
1081 
1083  re->pushedresult = NULL;
1084 }
1085 
1086 /************************* EXR Tile File Rendering ***************************/
1087 
1088 static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname)
1089 {
1090  RenderLayer *rlp, *rl;
1091  RenderPass *rpassp;
1092  int partx, party;
1093 
1095 
1096  for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
1097  rl = RE_GetRenderLayer(rr, rlp->name);
1098 
1099  /* should never happen but prevents crash if it does */
1100  BLI_assert(rl);
1101  if (UNLIKELY(rl == NULL)) {
1102  continue;
1103  }
1104 
1105  /* passes are allocated in sync */
1106  for (rpassp = rlp->passes.first; rpassp; rpassp = rpassp->next) {
1107  const int xstride = rpassp->channels;
1108  int a;
1109  char fullname[EXR_PASS_MAXNAME];
1110 
1111  for (a = 0; a < xstride; a++) {
1112  set_pass_full_name(fullname, rpassp->name, a, viewname, rpassp->chan_id);
1113 
1115  rlp->name,
1116  fullname,
1117  xstride,
1118  xstride * rrpart->rectx,
1119  rpassp->rect + a);
1120  }
1121  }
1122  }
1123 
1124  party = rrpart->tilerect.ymin;
1125  partx = rrpart->tilerect.xmin;
1126 
1127  for (rlp = rrpart->layers.first; rlp; rlp = rlp->next) {
1128  rl = RE_GetRenderLayer(rr, rlp->name);
1129 
1130  /* should never happen but prevents crash if it does */
1131  BLI_assert(rl);
1132  if (UNLIKELY(rl == NULL)) {
1133  continue;
1134  }
1135 
1136  IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, viewname, false);
1137  }
1138 
1140 }
1141 
1143 {
1144  RenderResult *rr;
1145  RenderLayer *rl;
1146 
1147  for (rr = re->result; rr; rr = rr->next) {
1148  for (rl = rr->layers.first; rl; rl = rl->next) {
1149  GHashIterator pa_iter;
1150  GHASH_ITER (pa_iter, re->parts) {
1151  RenderPart *pa = BLI_ghashIterator_getValue(&pa_iter);
1152  if (pa->status != PART_STATUS_MERGED) {
1153  int party = pa->disprect.ymin - re->disprect.ymin;
1154  int partx = pa->disprect.xmin - re->disprect.xmin;
1155  IMB_exrtile_write_channels(rl->exrhandle, partx, party, 0, re->viewname, true);
1156  }
1157  }
1158  }
1159  }
1160 }
1161 
1162 /* Compute list of passes needed by render engine. */
1163 static void templates_register_pass_cb(void *userdata,
1164  Scene *UNUSED(scene),
1165  ViewLayer *UNUSED(view_layer),
1166  const char *name,
1167  int channels,
1168  const char *chan_id,
1170 {
1171  ListBase *templates = userdata;
1172  RenderPass *pass = MEM_callocN(sizeof(RenderPass), "RenderPassTemplate");
1173 
1174  pass->channels = channels;
1175  BLI_strncpy(pass->name, name, sizeof(pass->name));
1176  BLI_strncpy(pass->chan_id, chan_id, sizeof(pass->chan_id));
1177 
1178  BLI_addtail(templates, pass);
1179 }
1180 
1182  Render *re,
1183  RenderLayer *rl,
1184  ListBase *templates)
1185 {
1186  BLI_listbase_clear(templates);
1187 
1188  if (engine && engine->type->update_render_passes) {
1189  ViewLayer *view_layer = BLI_findstring(&re->view_layers, rl->name, offsetof(ViewLayer, name));
1190  if (view_layer) {
1192  engine, re->scene, view_layer, templates_register_pass_cb, templates);
1193  }
1194  }
1195 }
1196 
1197 /* begin write of exr tile file */
1199 {
1200  char str[FILE_MAX];
1201 
1202  for (RenderResult *rr = re->result; rr; rr = rr->next) {
1203  LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
1204  /* Get passes needed by engine. Normally we would wait for the
1205  * engine to create them, but for EXR file we need to know in
1206  * advance. */
1207  ListBase templates;
1208  render_result_get_pass_templates(engine, re, rl, &templates);
1209 
1210  /* Create render passes requested by engine. Only this part is
1211  * mutex locked to avoid deadlock with Python GIL. */
1213  LISTBASE_FOREACH (RenderPass *, pass, &templates) {
1215  re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL);
1216  }
1218 
1219  BLI_freelistN(&templates);
1220 
1221  /* Open EXR file for writing. */
1222  render_result_exr_file_path(re->scene, rl->name, rr->sample_nr, str);
1223  printf("write exr tmp file, %dx%d, %s\n", rr->rectx, rr->recty, str);
1224  IMB_exrtile_begin_write(rl->exrhandle, str, 0, rr->rectx, rr->recty, re->partx, re->party);
1225  }
1226  }
1227 }
1228 
1229 /* end write of exr tile file, read back first sample */
1231 {
1232  /* Preserve stamp data. */
1233  struct StampData *stamp_data = re->result->stamp_data;
1234  re->result->stamp_data = NULL;
1235 
1236  /* Close EXR files. */
1237  for (RenderResult *rr = re->result; rr; rr = rr->next) {
1238  LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
1239  IMB_exr_close(rl->exrhandle);
1240  rl->exrhandle = NULL;
1241  }
1242 
1243  rr->do_exr_tile = false;
1244  }
1245 
1246  /* Create new render result in memory instead of on disk. */
1250  re->result->stamp_data = stamp_data;
1252 
1253  LISTBASE_FOREACH (RenderLayer *, rl, &re->result->layers) {
1254  /* Get passes needed by engine. */
1255  ListBase templates;
1256  render_result_get_pass_templates(engine, re, rl, &templates);
1257 
1258  /* Create render passes requested by engine. Only this part is
1259  * mutex locked to avoid deadlock with Python GIL. */
1261  LISTBASE_FOREACH (RenderPass *, pass, &templates) {
1262  RE_create_render_pass(re->result, pass->name, pass->channels, pass->chan_id, rl->name, NULL);
1263  }
1264 
1265  BLI_freelistN(&templates);
1266 
1267  /* Render passes contents from file. */
1268  char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
1269  render_result_exr_file_path(re->scene, rl->name, 0, str);
1270  printf("read exr tmp file: %s\n", str);
1271 
1272  if (!render_result_exr_file_read_path(re->result, rl, str)) {
1273  printf("cannot read: %s\n", str);
1274  }
1276  }
1277 }
1278 
1279 /* save part into exr file */
1280 void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart, const char *viewname)
1281 {
1282  for (; rr && rrpart; rr = rr->next, rrpart = rrpart->next) {
1283  save_render_result_tile(rr, rrpart, viewname);
1284  }
1285 }
1286 
1287 /* path to temporary exr file */
1288 void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath)
1289 {
1290  char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100];
1292 
1293  if (sample == 0) {
1294  BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname);
1295  }
1296  else {
1297  BLI_snprintf(name, sizeof(name), "%s_%s_%s%d.exr", fi, scene->id.name + 2, layname, sample);
1298  }
1299 
1300  /* Make name safe for paths, see T43275. */
1301  BLI_filename_make_safe(name);
1302 
1303  BLI_join_dirfile(filepath, FILE_MAX, BKE_tempdir_session(), name);
1304 }
1305 
1306 /* called for reading temp files, and for external engines */
1308  RenderLayer *rl_single,
1309  const char *filepath)
1310 {
1311  RenderLayer *rl;
1312  RenderPass *rpass;
1313  void *exrhandle = IMB_exr_get_handle();
1314  int rectx, recty;
1315 
1316  if (IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty) == 0) {
1317  printf("failed being read %s\n", filepath);
1318  IMB_exr_close(exrhandle);
1319  return 0;
1320  }
1321 
1322  if (rr == NULL || rectx != rr->rectx || recty != rr->recty) {
1323  if (rr) {
1324  printf("error in reading render result: dimensions don't match\n");
1325  }
1326  else {
1327  printf("error in reading render result: NULL result pointer\n");
1328  }
1329  IMB_exr_close(exrhandle);
1330  return 0;
1331  }
1332 
1333  for (rl = rr->layers.first; rl; rl = rl->next) {
1334  if (rl_single && rl_single != rl) {
1335  continue;
1336  }
1337 
1338  /* passes are allocated in sync */
1339  for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
1340  const int xstride = rpass->channels;
1341  int a;
1342  char fullname[EXR_PASS_MAXNAME];
1343 
1344  for (a = 0; a < xstride; a++) {
1345  set_pass_full_name(fullname, rpass->name, a, rpass->view, rpass->chan_id);
1347  exrhandle, rl->name, fullname, xstride, xstride * rectx, rpass->rect + a);
1348  }
1349 
1350  set_pass_full_name(rpass->fullname, rpass->name, -1, rpass->view, rpass->chan_id);
1351  }
1352  }
1353 
1354  IMB_exr_read_channels(exrhandle);
1355  IMB_exr_close(exrhandle);
1356 
1357  return 1;
1358 }
1359 
1360 static void render_result_exr_file_cache_path(Scene *sce, const char *root, char *r_path)
1361 {
1362  char filename_full[FILE_MAX + MAX_ID_NAME + 100], filename[FILE_MAXFILE], dirname[FILE_MAXDIR];
1363  char path_digest[16] = {0};
1364  char path_hexdigest[33];
1365 
1366  /* If root is relative, use either current .blend file dir, or temp one if not saved. */
1367  const char *blendfile_path = BKE_main_blendfile_path_from_global();
1368  if (blendfile_path[0] != '\0') {
1369  BLI_split_dirfile(blendfile_path, dirname, filename, sizeof(dirname), sizeof(filename));
1370  BLI_path_extension_replace(filename, sizeof(filename), ""); /* strip '.blend' */
1371  BLI_hash_md5_buffer(blendfile_path, strlen(blendfile_path), path_digest);
1372  }
1373  else {
1375  BLI_strncpy(filename, "UNSAVED", sizeof(filename));
1376  }
1377  BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
1378 
1379  /* Default to *non-volatile* tmp dir. */
1380  if (*root == '\0') {
1381  root = BKE_tempdir_base();
1382  }
1383 
1384  BLI_snprintf(filename_full,
1385  sizeof(filename_full),
1386  "cached_RR_%s_%s_%s.exr",
1387  filename,
1388  sce->id.name + 2,
1389  path_hexdigest);
1390  BLI_make_file_string(dirname, r_path, root, filename_full);
1391 }
1392 
1394 {
1395  RenderResult *rr = re->result;
1396  char str[FILE_MAXFILE + FILE_MAXFILE + MAX_ID_NAME + 100];
1397  char *root = U.render_cachedir;
1398 
1400  printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
1401 
1402  RE_WriteRenderResult(NULL, rr, str, NULL, NULL, -1);
1403 }
1404 
1405 /* For cache, makes exact copy of render result */
1407 {
1408  char str[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = "";
1409  char *root = U.render_cachedir;
1410 
1413 
1414  /* First try cache. */
1416 
1417  printf("read exr cache file: %s\n", str);
1419  printf("cannot read: %s\n", str);
1420  return false;
1421  }
1422  return true;
1423 }
1424 
1425 /*************************** Combined Pixel Rect *****************************/
1426 
1427 ImBuf *render_result_rect_to_ibuf(RenderResult *rr, const RenderData *rd, const int view_id)
1428 {
1429  ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, rd->im_format.planes, 0);
1430  RenderView *rv = RE_RenderViewGetById(rr, view_id);
1431 
1432  /* if not exists, BKE_imbuf_write makes one */
1433  ibuf->rect = (unsigned int *)rv->rect32;
1434  ibuf->rect_float = rv->rectf;
1435  ibuf->zbuf_float = rv->rectz;
1436 
1437  /* float factor for random dither, imbuf takes care of it */
1438  ibuf->dither = rd->dither_intensity;
1439 
1440  /* prepare to gamma correct to sRGB color space
1441  * note that sequence editor can generate 8bpc render buffers
1442  */
1443  if (ibuf->rect) {
1446  if (rd->im_format.depth == R_IMF_CHAN_DEPTH_8) {
1447  /* Higher depth bits are supported but not needed for current file output. */
1448  ibuf->rect_float = NULL;
1449  }
1450  else {
1451  IMB_float_from_rect(ibuf);
1452  }
1453  }
1454  else {
1455  /* ensure no float buffer remained from previous frame */
1456  ibuf->rect_float = NULL;
1457  }
1458  }
1459 
1460  /* color -> grayscale */
1461  /* editing directly would alter the render view */
1462  if (rd->im_format.planes == R_IMF_PLANES_BW) {
1463  ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
1464  IMB_color_to_bw(ibuf_bw);
1465  IMB_freeImBuf(ibuf);
1466  ibuf = ibuf_bw;
1467  }
1468 
1469  return ibuf;
1470 }
1471 
1473  RenderData *UNUSED(rd),
1474  ImBuf *ibuf,
1475  const int view_id)
1476 {
1477  RenderView *rv = RE_RenderViewGetById(rr, view_id);
1478 
1479  if (ibuf->rect_float) {
1480  rr->have_combined = true;
1481 
1482  if (!rv->rectf) {
1483  rv->rectf = MEM_mallocN(sizeof(float[4]) * rr->rectx * rr->recty, "render_seq rectf");
1484  }
1485 
1486  memcpy(rv->rectf, ibuf->rect_float, sizeof(float[4]) * rr->rectx * rr->recty);
1487 
1488  /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
1489  * can hang around when sequence render has rendered a 32 bits one before */
1490  MEM_SAFE_FREE(rv->rect32);
1491  }
1492  else if (ibuf->rect) {
1493  rr->have_combined = true;
1494 
1495  if (!rv->rect32) {
1496  rv->rect32 = MEM_mallocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
1497  }
1498 
1499  memcpy(rv->rect32, ibuf->rect, 4 * rr->rectx * rr->recty);
1500 
1501  /* Same things as above, old rectf can hang around from previous render. */
1502  MEM_SAFE_FREE(rv->rectf);
1503  }
1504 }
1505 
1506 void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
1507 {
1508  RenderView *rv = RE_RenderViewGetById(rr, view_id);
1509 
1510  if (rv->rectf) {
1511  memset(rv->rectf, 0, sizeof(float[4]) * rr->rectx * rr->recty);
1512  }
1513  else if (rv->rect32) {
1514  memset(rv->rect32, 0, 4 * rr->rectx * rr->recty);
1515  }
1516  else {
1517  rv->rect32 = MEM_callocN(sizeof(int) * rr->rectx * rr->recty, "render_seq rect");
1518  }
1519 }
1520 
1522  unsigned int *rect,
1523  int rectx,
1524  int recty,
1525  const ColorManagedViewSettings *view_settings,
1526  const ColorManagedDisplaySettings *display_settings,
1527  const int view_id)
1528 {
1529  RenderView *rv = RE_RenderViewGetById(rr, view_id);
1530 
1531  if (rv && rv->rect32) {
1532  memcpy(rect, rv->rect32, sizeof(int) * rr->rectx * rr->recty);
1533  }
1534  else if (rv && rv->rectf) {
1535  IMB_display_buffer_transform_apply((unsigned char *)rect,
1536  rv->rectf,
1537  rr->rectx,
1538  rr->recty,
1539  4,
1540  view_settings,
1541  display_settings,
1542  true);
1543  }
1544  else {
1545  /* else fill with black */
1546  memset(rect, 0, sizeof(int) * rectx * recty);
1547  }
1548 }
1549 
1550 /*************************** multiview functions *****************************/
1551 
1553 {
1554  RenderView *rv;
1555 
1556  if (rr == NULL) {
1557  return false;
1558  }
1559 
1560  rv = rr->views.first;
1561  if (rv == NULL) {
1562  return false;
1563  }
1564 
1565  return (rv->rect32 || rv->rectf);
1566 }
1567 
1569 {
1570  RenderView *rview;
1571 
1572  for (rview = rr->views.first; rview; rview = rview->next) {
1573  if (rview->rect32 && !rview->rectf) {
1574  return false;
1575  }
1576  }
1577 
1578  return true;
1579 }
1580 
1582 {
1583  if (!BLI_findstring(&rr->views, STEREO_LEFT_NAME, offsetof(RenderView, name))) {
1584  return false;
1585  }
1586 
1587  if (!BLI_findstring(&rr->views, STEREO_RIGHT_NAME, offsetof(RenderView, name))) {
1588  return false;
1589  }
1590 
1591  return true;
1592 }
1593 
1595 {
1596  RenderView *rv = BLI_findlink(&rr->views, view_id);
1597  BLI_assert(rr->views.first);
1598  return rv ? rv : rr->views.first;
1599 }
1600 
1602 {
1603  RenderView *rv = BLI_findstring(&rr->views, viewname, offsetof(RenderView, name));
1604  BLI_assert(rr->views.first);
1605  return rv ? rv : rr->views.first;
1606 }
1607 
1609 {
1610  RenderPass *new_rpass = MEM_mallocN(sizeof(RenderPass), "new render pass");
1611  *new_rpass = *rpass;
1612  new_rpass->next = new_rpass->prev = NULL;
1613  if (new_rpass->rect != NULL) {
1614  new_rpass->rect = MEM_dupallocN(new_rpass->rect);
1615  }
1616  return new_rpass;
1617 }
1618 
1620 {
1621  RenderLayer *new_rl = MEM_mallocN(sizeof(RenderLayer), "new render layer");
1622  *new_rl = *rl;
1623  new_rl->next = new_rl->prev = NULL;
1624  new_rl->passes.first = new_rl->passes.last = NULL;
1625  new_rl->exrhandle = NULL;
1626  for (RenderPass *rpass = rl->passes.first; rpass != NULL; rpass = rpass->next) {
1627  RenderPass *new_rpass = duplicate_render_pass(rpass);
1628  BLI_addtail(&new_rl->passes, new_rpass);
1629  }
1630  return new_rl;
1631 }
1632 
1634 {
1635  RenderView *new_rview = MEM_mallocN(sizeof(RenderView), "new render view");
1636  *new_rview = *rview;
1637  if (new_rview->rectf != NULL) {
1638  new_rview->rectf = MEM_dupallocN(new_rview->rectf);
1639  }
1640  if (new_rview->rectz != NULL) {
1641  new_rview->rectz = MEM_dupallocN(new_rview->rectz);
1642  }
1643  if (new_rview->rect32 != NULL) {
1644  new_rview->rect32 = MEM_dupallocN(new_rview->rect32);
1645  }
1646  return new_rview;
1647 }
1648 
1650 {
1651  RenderResult *new_rr = MEM_mallocN(sizeof(RenderResult), "new duplicated render result");
1652  *new_rr = *rr;
1653  new_rr->next = new_rr->prev = NULL;
1654  new_rr->layers.first = new_rr->layers.last = NULL;
1655  new_rr->views.first = new_rr->views.last = NULL;
1656  for (RenderLayer *rl = rr->layers.first; rl != NULL; rl = rl->next) {
1657  RenderLayer *new_rl = duplicate_render_layer(rl);
1658  BLI_addtail(&new_rr->layers, new_rl);
1659  }
1660  for (RenderView *rview = rr->views.first; rview != NULL; rview = rview->next) {
1661  RenderView *new_rview = duplicate_render_view(rview);
1662  BLI_addtail(&new_rr->views, new_rview);
1663  }
1664  if (new_rr->rect32 != NULL) {
1665  new_rr->rect32 = MEM_dupallocN(new_rr->rect32);
1666  }
1667  if (new_rr->rectf != NULL) {
1668  new_rr->rectf = MEM_dupallocN(new_rr->rectf);
1669  }
1670  if (new_rr->rectz != NULL) {
1671  new_rr->rectz = MEM_dupallocN(new_rr->rectz);
1672  }
1673  new_rr->stamp_data = BKE_stamp_data_copy(new_rr->stamp_data);
1674  return new_rr;
1675 }
typedef float(TangentPoint)[2]
const char * BKE_tempdir_base(void)
Definition: appdir.c:1182
Camera data-block and utility functions.
void BKE_stamp_data_free(struct StampData *stamp_data)
Definition: image.c:2757
char BKE_imtype_valid_depths(const char imtype)
Definition: image.c:1541
struct StampData * BKE_stamp_data_copy(const struct StampData *stamp_data)
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:439
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv)
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE void * BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.h:150
#define GHASH_ITER(gh_iter_, ghash_)
Definition: BLI_ghash.h:169
void * BLI_hash_md5_buffer(const char *buffer, size_t len, void *resblock)
Definition: hash_md5.c:370
char * BLI_hash_md5_to_hexdigest(void *resblock, char r_hex_digest[33])
Definition: hash_md5.c:406
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:124
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:87
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:352
int BLI_listbase_count_at_most(const struct ListBase *listbase, const int count_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void * BLI_findstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void void BLI_listbase_sort(struct ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
const char * BLI_path_basename(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
Definition: path_util.c:1868
bool BLI_make_existing_file(const char *name)
Definition: path_util.c:1347
#define FILE_MAXFILE
#define FILE_MAX
void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
Definition: path_util.c:1365
void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1737
bool BLI_path_extension_replace(char *path, size_t maxlen, const char *ext) ATTR_NONNULL()
Definition: path_util.c:1571
bool BLI_filename_make_safe(char *fname) ATTR_NONNULL(1)
Definition: path_util.c:299
void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
Definition: path_util.c:1654
#define FILE_MAXDIR
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:157
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:153
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition: BLI_rect.h:140
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition: BLI_rect.h:136
#define STR_ELEM(...)
Definition: BLI_string.h:218
size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf) ATTR_NONNULL()
Definition: string.c:1056
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
char * BLI_string_join_array_by_sep_char(char *result, size_t result_len, char sep, const char *strings[], uint strings_len) ATTR_NONNULL()
Definition: string_utils.c:439
void BLI_thread_unlock(int type)
Definition: threads.cc:389
void BLI_thread_lock(int type)
Definition: threads.cc:384
#define THREAD_LOCK_WRITE
Definition: BLI_threads.h:122
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
Definition: threads.cc:516
@ LOCK_IMAGE
Definition: BLI_threads.h:67
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
Definition: threads.cc:526
#define ARRAY_SET_ITEMS(...)
#define UNUSED(x)
#define UNLIKELY(x)
#define STREQ(a, b)
const char * dirname(char *path)
#define PASS_VECTOR_MAX
#define MAX_ID_NAME
Definition: DNA_ID.h:269
eNodeSocketDatatype
#define RE_PASSNAME_COMBINED
#define STEREO_LEFT_NAME
#define RE_PASSNAME_UV
#define R_MULTIVIEW
#define R_IMF_PLANES_BW
#define RE_PASSNAME_DIFFUSE_INDIRECT
#define RE_PASSNAME_INDEXMA
#define RE_PASSNAME_SUBSURFACE_DIRECT
#define RE_PASSNAME_NORMAL
#define RE_PASSNAME_TRANSM_DIRECT
#define RE_PASSNAME_VECTOR
#define RE_PASSNAME_TRANSM_COLOR
#define RE_PASSNAME_EMIT
#define RE_PASSNAME_SUBSURFACE_INDIRECT
#define RE_PASSNAME_GLOSSY_COLOR
#define RE_PASSNAME_SUBSURFACE_COLOR
#define RE_PASSNAME_TRANSM_INDIRECT
#define RE_PASSNAME_GLOSSY_DIRECT
#define RE_PASSNAME_SHADOW
#define RE_PASSNAME_MIST
#define RE_PASSNAME_ENVIRONMENT
@ R_IMF_CHAN_DEPTH_24
@ R_IMF_CHAN_DEPTH_8
@ R_IMF_CHAN_DEPTH_16
@ R_IMF_CHAN_DEPTH_12
@ R_IMF_CHAN_DEPTH_32
#define RE_PASSNAME_DIFFUSE_COLOR
#define RE_PASSNAME_GLOSSY_INDIRECT
#define RE_PASSNAME_AO
#define RE_PASSNAME_Z
#define STEREO_RIGHT_NAME
#define RE_PASSNAME_RAYHITS
#define RE_PASSNAME_DIFFUSE_DIRECT
#define R_IMF_FLAG_ZBUF
#define R_IMF_IMTYPE_OPENEXR
#define RE_PASSNAME_INDEXOB
@ SCE_PASS_NORMAL
@ SCE_PASS_GLOSSY_DIRECT
@ SCE_PASS_AO
@ SCE_PASS_DIFFUSE_COLOR
@ SCE_PASS_UV
@ SCE_PASS_SUBSURFACE_INDIRECT
@ SCE_PASS_TRANSM_DIRECT
@ SCE_PASS_SUBSURFACE_COLOR
@ SCE_PASS_GLOSSY_COLOR
@ SCE_PASS_DIFFUSE_DIRECT
@ SCE_PASS_GLOSSY_INDIRECT
@ SCE_PASS_INDEXMA
@ SCE_PASS_INDEXOB
@ SCE_PASS_TRANSM_INDIRECT
@ SCE_PASS_COMBINED
@ SCE_PASS_Z
@ SCE_PASS_VECTOR
@ SCE_PASS_DIFFUSE_INDIRECT
@ SCE_PASS_SUBSURFACE_DIRECT
@ SCE_PASS_SHADOW
@ SCE_PASS_TRANSM_COLOR
@ SCE_PASS_MIST
@ SCE_PASS_EMIT
@ SCE_PASS_ENVIRONMENT
@ SCE_PASS_RAYHITS
static AppView * view
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
#define Z
Definition: GeomUtils.cpp:215
void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, int channels, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, bool predivide)
const char * IMB_colormanagement_role_colorspace_name_get(int role)
@ COLOR_ROLE_SCENE_LINEAR
void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
void IMB_float_from_rect(struct ImBuf *ibuf)
Definition: divers.c:780
void IMB_color_to_bw(struct ImBuf *ibuf)
Definition: divers.c:842
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
Definition: allocimbuf.c:478
struct ImBuf * IMB_dupImBuf(const struct ImBuf *ibuf1)
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group RGB to NORMAL
unsigned int U
Definition: btGjkEpa3.h:78
Scene scene
void RE_engine_update_render_passes(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer, update_render_passes_cb_t callback, void *callback_data)
Definition: engine.c:1071
#define str(s)
void * BKE_tempdir_session
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static unsigned a[3]
Definition: RandGen.cpp:92
static void sample(SocketReader *reader, int x, int y, float color[4])
void IMB_exr_add_view(void *handle, const char *name)
void IMB_exr_close(void *handle)
void IMB_exrtile_begin_write(void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley)
void IMB_exr_add_channel(void *handle, const char *layname, const char *passname, const char *viewname, int xstride, int ystride, float *rect, bool use_half_float)
void IMB_exr_write_channels(void *handle)
int IMB_exr_begin_write(void *handle, const char *filename, int width, int height, int compress, const StampData *stamp)
void IMB_exr_read_channels(void *handle)
void IMB_exrtile_write_channels(void *handle, int partx, int party, int level, const char *viewname, bool empty)
void IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
void * IMB_exr_get_handle(void)
int IMB_exr_begin_read(void *handle, const char *filename, int *width, int *height)
void IMB_exr_multilayer_convert(void *handle, void *base, void *(*addview)(void *base, const char *str), void *(*addlayer)(void *base, const char *str), void(*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id, const char *view))
#define EXR_LAY_MAXNAME
Definition: openexr_multi.h:30
#define EXR_VIEW_MAXNAME
Definition: openexr_multi.h:32
#define EXR_PASS_MAXNAME
Definition: openexr_multi.h:31
void RE_FreeRenderResult(RenderResult *rr)
Definition: pipeline.c:265
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
Definition: pipeline.c:276
static int order_render_passes(const void *a, const void *b)
static void render_result_views_free(RenderResult *rr)
Definition: render_result.c:61
static void render_result_get_pass_templates(RenderEngine *engine, Render *re, RenderLayer *rl, ListBase *templates)
bool RE_WriteRenderResult(ReportList *reports, RenderResult *rr, const char *filename, ImageFormatData *imf, const char *view, int layer)
void render_result_single_layer_end(Render *re)
bool RE_HasCombinedLayer(RenderResult *rr)
void render_result_exr_file_cache_write(Render *re)
static void set_pass_full_name(char *fullname, const char *name, int channel, const char *view, const char *chan_id)
RenderView * RE_RenderViewGetById(RenderResult *rr, const int view_id)
void render_result_exr_file_end(Render *re, RenderEngine *engine)
static void * ml_addview_cb(void *base, const char *str)
void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath)
bool render_result_exr_file_cache_read(Render *re)
void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
void RE_create_render_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname)
void render_result_views_shallowdelete(RenderResult *rr)
void render_result_views_new(RenderResult *rr, const RenderData *rd)
static void * ml_addlayer_cb(void *base, const char *str)
void render_result_merge(RenderResult *rr, RenderResult *rrpart)
int render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, const char *filepath)
void render_result_view_new(RenderResult *rr, const char *viewname)
bool RE_RenderResult_is_stereo(RenderResult *rr)
RenderResult * render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
void render_result_free(RenderResult *rr)
Definition: render_result.c:85
void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rectx, int recty, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const int view_id)
RenderPass * render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id)
bool RE_HasFloatPixels(RenderResult *rr)
ImBuf * render_result_rect_to_ibuf(RenderResult *rr, const RenderData *rd, const int view_id)
static void templates_register_pass_cb(void *userdata, Scene *UNUSED(scene), ViewLayer *UNUSED(view_layer), const char *name, int channels, const char *chan_id, eNodeSocketDatatype UNUSED(type))
void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
static char * set_pass_name(char *outname, const char *name, int channel, const char *chan_id)
void render_result_exr_file_begin(Render *re, RenderEngine *engine)
RenderView * RE_RenderViewGetByName(RenderResult *rr, const char *viewname)
void render_result_free_list(ListBase *lb, RenderResult *rr)
static void save_render_result_tile(RenderResult *rr, RenderResult *rrpart, const char *viewname)
RenderResult * render_result_new(Render *re, rcti *partrct, int savebuffers, const char *layername, const char *viewname)
bool render_result_has_views(RenderResult *rr)
void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart, const char *viewname)
static int passtype_from_name(const char *name)
void render_result_single_layer_begin(Render *re)
static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view)
static RenderPass * duplicate_render_pass(RenderPass *rpass)
void render_result_save_empty_result_tiles(Render *re)
#define CHECK_PASS(NAME)
void RE_render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id)
static RenderLayer * duplicate_render_layer(RenderLayer *rl)
static RenderView * duplicate_render_view(RenderView *rview)
#define RENDER_LAYER_ADD_PASS_SAFE(rr, rl, channels, name, viewname, chan_id)
RenderResult * RE_DuplicateRenderResult(RenderResult *rr)
static void render_result_exr_file_cache_path(Scene *sce, const char *root, char *r_path)
static void do_merge_tile(RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
void render_result_views_shallowcopy(RenderResult *dst, RenderResult *src)
#define FOREACH_VIEW_LAYER_TO_RENDER_END
#define RR_USE_MEM
Definition: render_result.h:28
#define RR_ALL_VIEWS
Definition: render_result.h:32
#define RR_ALL_LAYERS
Definition: render_result.h:31
#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_)
@ PART_STATUS_MERGED
Definition: render_types.h:66
char name[66]
Definition: DNA_ID.h:283
float * zbuf_float
float dither
unsigned int * rect
float * rect_float
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
struct ImageFormatData im_format
float dither_intensity
ListBase views
void(* update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer)
Definition: RE_engine.h:107
RenderEngineType * type
Definition: RE_engine.h:126
ListBase passes
Definition: RE_pipeline.h:108
char name[RE_MAXNAME]
Definition: RE_pipeline.h:100
struct RenderLayer * next
Definition: RE_pipeline.h:97
void * exrhandle
Definition: RE_pipeline.h:106
struct RenderLayer * prev
Definition: RE_pipeline.h:97
short status
Definition: render_types.h:59
rcti disprect
Definition: render_types.h:56
char chan_id[8]
Definition: RE_pipeline.h:81
char name[64]
Definition: RE_pipeline.h:80
char fullname[64]
Definition: RE_pipeline.h:85
char view[64]
Definition: RE_pipeline.h:86
int channels
Definition: RE_pipeline.h:79
float * rect
Definition: RE_pipeline.h:82
struct RenderPass * prev
Definition: RE_pipeline.h:78
struct RenderPass * next
Definition: RE_pipeline.h:78
struct RenderResult * next
Definition: RE_pipeline.h:113
ListBase views
Definition: RE_pipeline.h:138
ListBase layers
Definition: RE_pipeline.h:135
float * rectz
Definition: RE_pipeline.h:127
volatile rcti renrect
Definition: RE_pipeline.h:141
struct RenderResult * prev
Definition: RE_pipeline.h:113
char * error
Definition: RE_pipeline.h:155
struct StampData * stamp_data
Definition: RE_pipeline.h:157
float * rectf
Definition: RE_pipeline.h:125
float * rectf
Definition: RE_pipeline.h:69
float * rectz
Definition: RE_pipeline.h:71
int * rect32
Definition: RE_pipeline.h:73
struct RenderView * next
Definition: RE_pipeline.h:65
char name[64]
Definition: RE_pipeline.h:66
RenderResult * result
Definition: render_types.h:79
RenderResult * pushedresult
Definition: render_types.h:81
RenderData r
Definition: render_types.h:113
int winy
Definition: render_types.h:92
int active_view_layer
Definition: render_types.h:115
Scene * scene
Definition: render_types.h:112
ListBase fullresult
Definition: render_types.h:83
int partx
Definition: render_types.h:101
int party
Definition: render_types.h:101
struct GHash * parts
Definition: render_types.h:119
ThreadRWMutex resultmutex
Definition: render_types.h:87
char viewname[MAX_NAME]
Definition: render_types.h:154
int winx
Definition: render_types.h:92
rcti disprect
Definition: render_types.h:93
ListBase view_layers
Definition: render_types.h:114
struct SceneRenderView * next
string name
Definition: scene.h:222
struct ViewLayer * next
char name[64]
int ymin
Definition: DNA_vec_types.h:80
int ymax
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
int xmax
Definition: DNA_vec_types.h:79
uint len