Blender V4.5
render_result.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cerrno>
10#include <cstdio>
11#include <cstdlib>
12#include <cstring>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_hash_md5.hh"
17#include "BLI_listbase.h"
18#include "BLI_path_utils.hh"
19#include "BLI_rect.h"
20#include "BLI_string.h"
21#include "BLI_string_utils.hh"
22#include "BLI_utildefines.h"
23
24#include "DNA_userdef_types.h"
25
26#include "BKE_appdir.hh"
27#include "BKE_image.hh"
28#include "BKE_image_format.hh"
29#include "BKE_image_save.hh"
30#include "BKE_main.hh"
31#include "BKE_report.hh"
32#include "BKE_scene.hh"
33
35#include "IMB_imbuf.hh"
36#include "IMB_imbuf_types.hh"
37#include "IMB_openexr.hh"
38
39#include "GPU_texture.hh"
40
41#include "render_result.h"
42#include "render_types.h"
43
44/* -------------------------------------------------------------------- */
47
49{
50 while (rr->views.first) {
51 RenderView *rv = static_cast<RenderView *>(rr->views.first);
52 BLI_remlink(&rr->views, rv);
53
55
56 MEM_freeN(rv);
57 }
58
59 rr->have_combined = false;
60}
61
63{
64 if (rr == nullptr) {
65 return;
66 }
67
68 /* Only actually free when RenderResult when the render result has zero users which is its
69 * default state.
70 * There is no need to lock as the user-counted render results are protected by mutex at the
71 * higher call stack level. */
72 if (rr->user_counter > 0) {
73 --rr->user_counter;
74 return;
75 }
76
77 while (rr->layers.first) {
78 RenderLayer *rl = static_cast<RenderLayer *>(rr->layers.first);
79
80 while (rl->passes.first) {
81 RenderPass *rpass = static_cast<RenderPass *>(rl->passes.first);
82
83 IMB_freeImBuf(rpass->ibuf);
84
85 BLI_freelinkN(&rl->passes, rpass);
86 }
87 BLI_remlink(&rr->layers, rl);
88 MEM_freeN(rl);
89 }
90
92
94
95 if (rr->text) {
96 MEM_freeN(rr->text);
97 }
98 if (rr->error) {
99 MEM_freeN(rr->error);
100 }
101
103
104 MEM_freeN(rr);
105}
106
108{
109 RenderResult *rrnext;
110
111 for (; rr; rr = rrnext) {
112 rrnext = rr->next;
113
114 if (lb && lb->first) {
115 BLI_remlink(lb, rr);
116 }
117
119 }
120}
121
123{
124 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
125 LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
126 IMB_free_gpu_textures(rpass->ibuf);
127 }
128 }
129}
130
132
133/* -------------------------------------------------------------------- */
136
138{
139 if (dst == nullptr || src == nullptr) {
140 return;
141 }
142
143 LISTBASE_FOREACH (RenderView *, rview, &src->views) {
144 RenderView *rv;
145
146 rv = MEM_callocN<RenderView>("new render view");
147 BLI_addtail(&dst->views, rv);
148
149 STRNCPY(rv->name, rview->name);
150
151 rv->ibuf = rview->ibuf;
152 }
153}
154
156{
157 if (rr == nullptr) {
158 return;
159 }
160
161 while (rr->views.first) {
162 RenderView *rv = static_cast<RenderView *>(rr->views.first);
163 BLI_remlink(&rr->views, rv);
164 MEM_freeN(rv);
165 }
166}
167
169
170/* -------------------------------------------------------------------- */
173
174static int get_num_planes_for_pass_ibuf(const RenderPass &render_pass)
175{
176 switch (render_pass.channels) {
177 case 1:
178 return R_IMF_PLANES_BW;
179 case 3:
180 return R_IMF_PLANES_RGB;
181 case 4:
182 return R_IMF_PLANES_RGBA;
183 }
184
185 /* Fall back to a commonly used default value of planes for odd-ball number of channel. */
186 return R_IMF_PLANES_RGBA;
187}
188
190{
191 if (RE_RenderPassIsColor(&render_pass)) {
192 return;
193 }
194
196 IMB_colormanagement_assign_float_colorspace(render_pass.ibuf, data_colorspace);
197}
198
200{
201 if (rp->ibuf && rp->ibuf->float_buffer.data) {
202 return;
203 }
204
205 /* NOTE: In-lined manual allocation to support floating point buffers of an arbitrary number of
206 * channels. */
207
208 const size_t rectsize = size_t(rr->rectx) * rr->recty * rp->channels;
209 float *buffer_data = MEM_calloc_arrayN<float>(rectsize, rp->name);
210
212 rp->ibuf->channels = rp->channels;
213 copy_v2_v2_db(rp->ibuf->ppm, rr->ppm);
216
217 if (STREQ(rp->name, RE_PASSNAME_VECTOR)) {
218 /* initialize to max speed */
219 for (int x = rectsize - 1; x >= 0; x--) {
220 buffer_data[x] = PASS_VECTOR_MAX;
221 }
222 }
223 else if (STREQ(rp->name, RE_PASSNAME_Z)) {
224 for (int x = rectsize - 1; x >= 0; x--) {
225 buffer_data[x] = 10e10;
226 }
227 }
228}
229
231 RenderLayer *rl,
232 int channels,
233 const char *name,
234 const char *viewname,
235 const char *chan_id,
236 const bool allocate)
237{
238 const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
239 RenderPass *rpass = MEM_callocN<RenderPass>(name);
240
241 rpass->channels = channels;
242 rpass->rectx = rl->rectx;
243 rpass->recty = rl->recty;
244 rpass->view_id = view_id;
245
246 STRNCPY(rpass->name, name);
247 STRNCPY(rpass->chan_id, chan_id);
248 STRNCPY(rpass->view, viewname);
250 rpass->fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, -1);
251
252 if (rl->exrhandle) {
253 int a;
254 for (a = 0; a < channels; a++) {
255 char passname[EXR_PASS_MAXNAME];
257 passname, nullptr, rpass->name, nullptr, rpass->chan_id, a);
258 IMB_exr_add_channel(rl->exrhandle, rl->name, passname, viewname, 0, 0, nullptr, false);
259 }
260 }
261
262 BLI_addtail(&rl->passes, rpass);
263
264 if (allocate) {
266 }
267 else {
268 /* The result contains non-allocated pass now, so tag it as such. */
269 rr->passes_allocated = false;
270 }
271
272 return rpass;
273}
274
276 const rcti *partrct,
277 const char *layername,
278 const char *viewname)
279{
280 RenderResult *rr;
281 RenderLayer *rl;
282 int rectx, recty;
283
284 rectx = BLI_rcti_size_x(partrct);
285 recty = BLI_rcti_size_y(partrct);
286
287 if (rectx <= 0 || recty <= 0) {
288 return nullptr;
289 }
290
291 rr = MEM_callocN<RenderResult>("new render result");
292 rr->rectx = rectx;
293 rr->recty = recty;
294
295 BKE_scene_ppm_get(&re->r, rr->ppm);
296
297 /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
298 rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
299 rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
300 rr->tilerect.ymin = partrct->ymin - re->disprect.ymin;
301 rr->tilerect.ymax = partrct->ymax - re->disprect.ymin;
302
303 rr->passes_allocated = false;
304
305 render_result_views_new(rr, &re->r);
306
307 /* Check render-data for amount of layers. */
308 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
309 if (layername && layername[0]) {
310 if (!STREQ(view_layer->name, layername)) {
311 continue;
312 }
313 }
314
315 rl = MEM_callocN<RenderLayer>("new render layer");
316 BLI_addtail(&rr->layers, rl);
317
318 STRNCPY(rl->name, view_layer->name);
319 rl->layflag = view_layer->layflag;
320
321 rl->passflag = view_layer->passflag;
322
323 rl->rectx = rectx;
324 rl->recty = recty;
325
326 LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
327 const char *view = rv->name;
328
329 if (viewname && viewname[0]) {
330 if (!STREQ(view, viewname)) {
331 continue;
332 }
333 }
334
335 /* A render-layer should always have a "Combined" pass. */
336 render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA", false);
337 }
338 }
340
341 /* Preview-render doesn't do layers, so we make a default one. */
342 if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
343 rl = MEM_callocN<RenderLayer>("new render layer");
344 BLI_addtail(&rr->layers, rl);
345
346 rl->rectx = rectx;
347 rl->recty = recty;
348
349 LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
350 const char *view = rv->name;
351
352 if (viewname && viewname[0]) {
353 if (!STREQ(view, viewname)) {
354 continue;
355 }
356 }
357
358 /* A render-layer should always have a "Combined" pass. */
359 render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA", false);
360 }
361
362 /* NOTE: this has to be in sync with `scene.cc`. */
365
366 re->single_view_layer[0] = '\0';
367 }
368
369 /* Border render; calculate offset for use in compositor. compo is centralized coords. */
370 /* XXX(ton): obsolete? I now use it for drawing border render offset. */
371 rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
372 rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
373
374 return rr;
375}
376
378{
379 if (rr == nullptr) {
380 /* Happens when the result was not yet allocated for the current scene or slot configuration.
381 */
382 return;
383 }
384
385 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
386 LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
387 if (rl->exrhandle != nullptr && !STREQ(rp->name, RE_PASSNAME_COMBINED)) {
388 continue;
389 }
390
392 }
393 }
394
395 rr->passes_allocated = true;
396}
397
398void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
399{
400 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
401 RenderLayer *main_rl = RE_GetRenderLayer(re->result, rl->name);
402 if (!main_rl) {
403 continue;
404 }
405
406 LISTBASE_FOREACH (RenderPass *, main_rp, &main_rl->passes) {
407 if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) {
408 continue;
409 }
410
411 /* Compare `fullname` to make sure that the view also is equal. */
412 const RenderPass *rp = static_cast<const RenderPass *>(
413 BLI_findstring(&rl->passes, main_rp->fullname, offsetof(RenderPass, fullname)));
414 if (!rp) {
416 rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id, false);
417 }
418 }
419 }
420}
421
423 const char *name,
424 int channels,
425 const char *chan_id,
426 const char *layername,
427 const char *viewname,
428 const bool allocate)
429{
430 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
431 if (layername && layername[0] && !STREQ(rl->name, layername)) {
432 continue;
433 }
434
435 LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
436 const char *view = rv->name;
437
438 if (viewname && viewname[0] && !STREQ(view, viewname)) {
439 continue;
440 }
441
442 /* Ensure that the pass doesn't exist yet. */
443 bool pass_exists = false;
444 LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
445 if (STREQ(rp->name, name) && STREQ(rp->view, view)) {
446 pass_exists = true;
447 break;
448 }
449 }
450
451 if (!pass_exists) {
452 render_layer_add_pass(rr, rl, channels, name, view, chan_id, allocate);
453 }
454 }
455 }
456}
457
464
466{
467 ImBuf *ibuf = rpass->ibuf;
468
469 if (!ibuf) {
470 /* No existing GPU texture, but also no CPU side data to create it from. */
471 return nullptr;
472 }
473
474 if (ibuf->gpu.texture) {
475 /* Return existing GPU texture, regardless whether it also exists on CPU or not. */
476 return ibuf->gpu.texture;
477 }
478
479 if (ibuf->float_buffer.data == nullptr) {
480 /* No CPU side data to create the texture from. */
481 return nullptr;
482 }
483
484 const eGPUTextureFormat format = (rpass->channels == 1) ? GPU_R32F :
485 (rpass->channels == 3) ? GPU_RGB32F :
487
488 /* TODO(sergey): Use utility to assign the texture. */
489 ibuf->gpu.texture = GPU_texture_create_2d("RenderBuffer.gpu_texture",
490 rpass->rectx,
491 rpass->recty,
492 1,
493 format,
495 nullptr);
496
497 if (ibuf->gpu.texture) {
500 }
501
502 return ibuf->gpu.texture;
503}
504
506 const char *layname,
507 const char *passname,
508 const char *viewname,
509 const char *chan_id,
510 const int channel)
511{
512 /* OpenEXR compatible full channel name. */
513 const char *strings[4];
514 int strings_len = 0;
515
516 if (layname && layname[0]) {
517 strings[strings_len++] = layname;
518 }
519 if (passname && passname[0]) {
520 strings[strings_len++] = passname;
521 }
522 if (viewname && viewname[0]) {
523 strings[strings_len++] = viewname;
524 }
525
526 char token[2];
527 if (channel >= 0) {
528 ARRAY_SET_ITEMS(token, chan_id[channel], '\0');
529 strings[strings_len++] = token;
530 }
531
532 BLI_string_join_array_by_sep_char(fullname, EXR_PASS_MAXNAME, '.', strings, strings_len);
533}
534
535static int passtype_from_name(const char *name)
536{
537 const char delim[] = {'.', '\0'};
538 const char *sep, *suf;
539 int len = BLI_str_partition(name, delim, &sep, &suf);
540
541#define CHECK_PASS(NAME) \
542 if (STREQLEN(name, RE_PASSNAME_##NAME, len)) { \
543 return SCE_PASS_##NAME; \
544 } \
545 ((void)0)
546
547 CHECK_PASS(COMBINED);
548 CHECK_PASS(Z);
550 CHECK_PASS(NORMAL);
551 CHECK_PASS(UV);
552 CHECK_PASS(EMIT);
553 CHECK_PASS(SHADOW);
554 CHECK_PASS(AO);
555 CHECK_PASS(ENVIRONMENT);
556 CHECK_PASS(INDEXOB);
557 CHECK_PASS(INDEXMA);
558 CHECK_PASS(MIST);
559 CHECK_PASS(DIFFUSE_DIRECT);
560 CHECK_PASS(DIFFUSE_INDIRECT);
561 CHECK_PASS(DIFFUSE_COLOR);
562 CHECK_PASS(GLOSSY_DIRECT);
563 CHECK_PASS(GLOSSY_INDIRECT);
564 CHECK_PASS(GLOSSY_COLOR);
565 CHECK_PASS(TRANSM_DIRECT);
566 CHECK_PASS(TRANSM_INDIRECT);
567 CHECK_PASS(TRANSM_COLOR);
568 CHECK_PASS(SUBSURFACE_DIRECT);
569 CHECK_PASS(SUBSURFACE_INDIRECT);
570 CHECK_PASS(SUBSURFACE_COLOR);
571
572#undef CHECK_PASS
573 return 0;
574}
575
576/* callbacks for render_result_new_from_exr */
577static void *ml_addlayer_cb(void *base, const char *str)
578{
579 RenderResult *rr = static_cast<RenderResult *>(base);
580
581 RenderLayer *rl = MEM_callocN<RenderLayer>("new render layer");
582 BLI_addtail(&rr->layers, rl);
583
585 return rl;
586}
587
588static void ml_addpass_cb(void *base,
589 void *lay,
590 const char *name,
591 float *rect,
592 int totchan,
593 const char *chan_id,
594 const char *view)
595{
596 RenderResult *rr = static_cast<RenderResult *>(base);
597 RenderLayer *rl = static_cast<RenderLayer *>(lay);
598 RenderPass *rpass = MEM_callocN<RenderPass>("loaded pass");
599
600 BLI_addtail(&rl->passes, rpass);
601 rpass->rectx = rr->rectx;
602 rpass->recty = rr->recty;
603 rpass->channels = totchan;
604 rl->passflag |= passtype_from_name(name);
605
606 /* channel id chars */
607 STRNCPY(rpass->chan_id, chan_id);
608
609 RE_pass_set_buffer_data(rpass, rect);
610
611 STRNCPY(rpass->name, name);
612 STRNCPY(rpass->view, view);
613 RE_render_result_full_channel_name(rpass->fullname, nullptr, name, view, rpass->chan_id, -1);
614
615 if (view[0] != '\0') {
617 }
618 else {
619 rpass->view_id = 0;
620 }
621}
622
623static void *ml_addview_cb(void *base, const char *str)
624{
625 RenderResult *rr = static_cast<RenderResult *>(base);
626
627 RenderView *rv = MEM_callocN<RenderView>("new render view");
628 STRNCPY(rv->name, str);
629
630 /* For stereo drawing we need to ensure:
631 * STEREO_LEFT_NAME == STEREO_LEFT_ID and
632 * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
633
634 if (STREQ(str, STEREO_LEFT_NAME)) {
635 BLI_addhead(&rr->views, rv);
636 }
637 else if (STREQ(str, STEREO_RIGHT_NAME)) {
638 RenderView *left_rv = static_cast<RenderView *>(
640
641 if (left_rv == nullptr) {
642 BLI_addhead(&rr->views, rv);
643 }
644 else {
645 BLI_insertlinkafter(&rr->views, left_rv, rv);
646 }
647 }
648 else {
649 BLI_addtail(&rr->views, rv);
650 }
651
652 return rv;
653}
654
655static int order_render_passes(const void *a, const void *b)
656{
657 /* 1 if `a` is after `b`. */
658 const RenderPass *rpa = (const RenderPass *)a;
659 const RenderPass *rpb = (const RenderPass *)b;
660 uint passtype_a = passtype_from_name(rpa->name);
661 uint passtype_b = passtype_from_name(rpb->name);
662
663 /* Render passes with default type always go first. */
664 if (passtype_b && !passtype_a) {
665 return 1;
666 }
667 if (passtype_a && !passtype_b) {
668 return 0;
669 }
670
671 if (passtype_a && passtype_b) {
672 if (passtype_a > passtype_b) {
673 return 1;
674 }
675 if (passtype_a < passtype_b) {
676 return 0;
677 }
678 }
679 else {
680 int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME);
681 if (cmp > 0) {
682 return 1;
683 }
684 if (cmp < 0) {
685 return 0;
686 }
687 }
688
689 /* they have the same type */
690 /* left first */
691 if (STREQ(rpa->view, STEREO_LEFT_NAME)) {
692 return 0;
693 }
694 if (STREQ(rpb->view, STEREO_LEFT_NAME)) {
695 return 1;
696 }
697
698 /* right second */
699 if (STREQ(rpa->view, STEREO_RIGHT_NAME)) {
700 return 0;
701 }
702 if (STREQ(rpb->view, STEREO_RIGHT_NAME)) {
703 return 1;
704 }
705
706 /* remaining in ascending id order */
707 return (rpa->view_id < rpb->view_id);
708}
709
711 void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
712{
714 const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(
717
718 rr->rectx = rectx;
719 rr->recty = recty;
720
721 IMB_exr_get_ppm(exrhandle, rr->ppm);
722
724
725 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
726 rl->rectx = rectx;
727 rl->recty = recty;
728
730
731 LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
732 rpass->rectx = rectx;
733 rpass->recty = recty;
734
735 copy_v2_v2_db(rpass->ibuf->ppm, rr->ppm);
736
737 if (RE_RenderPassIsColor(rpass)) {
738 IMB_colormanagement_transform_float(rpass->ibuf->float_buffer.data,
739 rpass->rectx,
740 rpass->recty,
741 rpass->channels,
742 colorspace,
743 to_colorspace,
744 predivide);
745 }
746 else {
747 IMB_colormanagement_assign_float_colorspace(rpass->ibuf, data_colorspace);
748 }
749 }
750 }
751
752 return rr;
753}
754
755void render_result_view_new(RenderResult *rr, const char *viewname)
756{
757 RenderView *rv = MEM_callocN<RenderView>("new render view");
758 BLI_addtail(&rr->views, rv);
759 STRNCPY(rv->name, viewname);
760}
761
763{
764 /* clear previously existing views - for sequencer */
766
767 /* check renderdata for amount of views */
768 if (rd->scemode & R_MULTIVIEW) {
769 LISTBASE_FOREACH (SceneRenderView *, srv, &rd->views) {
770 if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) {
771 continue;
772 }
773 render_result_view_new(rr, srv->name);
774 }
775 }
776
777 /* we always need at least one view */
778 if (BLI_listbase_is_empty(&rr->views)) {
780 }
781}
782
784
785/* -------------------------------------------------------------------- */
788
789static void do_merge_tile(
790 RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
791{
792 int y, tilex, tiley;
793 size_t ofs, copylen;
794
795 copylen = tilex = rrpart->rectx;
796 tiley = rrpart->recty;
797
798 ofs = (size_t(rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
799 target += pixsize * ofs;
800
801 copylen *= sizeof(float) * pixsize;
802 tilex *= pixsize;
803 ofs = pixsize * rr->rectx;
804
805 for (y = 0; y < tiley; y++) {
806 memcpy(target, tile, copylen);
807 target += ofs;
808 tile += tilex;
809 }
810}
811
813{
814 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
815 RenderLayer *rlp = RE_GetRenderLayer(rrpart, rl->name);
816
817 if (rlp) {
818 /* Passes are allocated in sync. */
819 for (RenderPass *rpass = static_cast<RenderPass *>(rl->passes.first),
820 *rpassp = static_cast<RenderPass *>(rlp->passes.first);
821 rpass && rpassp;
822 rpass = rpass->next)
823 {
824 /* For save buffers, skip any passes that are only saved to disk. */
825 if (rpass->ibuf == nullptr || rpassp->ibuf == nullptr) {
826 continue;
827 }
828 if (rpass->ibuf->float_buffer.data == nullptr ||
829 rpassp->ibuf->float_buffer.data == nullptr)
830 {
831 continue;
832 }
833 /* Render-result have all passes, render-part only the active view's passes. */
834 if (!STREQ(rpassp->fullname, rpass->fullname)) {
835 continue;
836 }
837
838 do_merge_tile(rr,
839 rrpart,
840 rpass->ibuf->float_buffer.data,
841 rpassp->ibuf->float_buffer.data,
842 rpass->channels);
843
844 /* manually get next render pass */
845 rpassp = rpassp->next;
846 }
847 }
848 }
849}
850
852
853/* -------------------------------------------------------------------- */
856
858{
859 /* all layers except the active one get temporally pushed away */
860
861 /* officially pushed result should be nullptr... error can happen with do_seq */
863
864 re->pushedresult = re->result;
865 re->result = nullptr;
866}
867
869{
870 if (re->result == nullptr) {
871 printf("pop render result error; no current result!\n");
872 return;
873 }
874
875 if (!re->pushedresult) {
876 return;
877 }
878
879 if (re->pushedresult->rectx == re->result->rectx && re->pushedresult->recty == re->result->recty)
880 {
881 /* find which layer in re->pushedresult should be replaced */
882 RenderLayer *rl = static_cast<RenderLayer *>(re->result->layers.first);
883
884 /* render result should be empty after this */
885 BLI_remlink(&re->result->layers, rl);
886
887 /* reconstruct render result layers */
888 LISTBASE_FOREACH (ViewLayer *, view_layer, &re->scene->view_layers) {
889 if (STREQ(view_layer->name, re->single_view_layer)) {
890 BLI_addtail(&re->result->layers, rl);
891 }
892 else {
893 RenderLayer *rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name);
894 if (rlpush) {
895 BLI_remlink(&re->pushedresult->layers, rlpush);
896 BLI_addtail(&re->result->layers, rlpush);
897 }
898 }
899 }
900 }
901
903 re->pushedresult = nullptr;
904}
905
907 RenderLayer *rl_single,
909 const char *filepath)
910{
911 void *exrhandle = IMB_exr_get_handle();
912 int rectx, recty;
913
914 if (!IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty, false)) {
915 IMB_exr_close(exrhandle);
916 return false;
917 }
918
919 ListBase layers = (rr) ? rr->layers : ListBase{rl_single, rl_single};
920 const int expected_rectx = (rr) ? rr->rectx : rl_single->rectx;
921 const int expected_recty = (rr) ? rr->recty : rl_single->recty;
922 bool found_channels = false;
923
924 if (rectx != expected_rectx || recty != expected_recty) {
926 RPT_ERROR,
927 "Reading render result: dimensions don't match, expected %dx%d",
928 expected_rectx,
929 expected_recty);
930 IMB_exr_close(exrhandle);
931 return true;
932 }
933
934 LISTBASE_FOREACH (RenderLayer *, rl, &layers) {
935 if (rl_single && rl_single != rl) {
936 continue;
937 }
938
939 /* passes are allocated in sync */
940 LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
941 const int xstride = rpass->channels;
942 const int ystride = xstride * rectx;
943 int a;
944 char fullname[EXR_PASS_MAXNAME];
945
946 for (a = 0; a < xstride; a++) {
948 fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, a);
949
950 if (IMB_exr_set_channel(exrhandle,
951 rl->name,
952 fullname,
953 xstride,
954 ystride,
955 rpass->ibuf->float_buffer.data + a))
956 {
957 found_channels = true;
958 }
959 else if (rl_single) {
960 if (IMB_exr_set_channel(exrhandle,
961 nullptr,
962 fullname,
963 xstride,
964 ystride,
965 rpass->ibuf->float_buffer.data + a))
966 {
967 found_channels = true;
968 }
969 else {
970 BKE_reportf(nullptr,
972 "Reading render result: expected channel \"%s.%s\" or \"%s\" not found",
973 rl->name,
974 fullname,
975 fullname);
976 }
977 }
978 else {
979 BKE_reportf(nullptr,
981 "Reading render result: expected channel \"%s.%s\" not found",
982 rl->name,
983 fullname);
984 }
985 }
986
988 rpass->fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, -1);
989 }
990 }
991
992 if (found_channels) {
993 IMB_exr_read_channels(exrhandle);
994 }
995
996 IMB_exr_close(exrhandle);
997
998 return true;
999}
1000
1001#define FILE_CACHE_MAX (FILE_MAXDIR + FILE_MAXFILE + MAX_ID_NAME + 100)
1002
1004 const char *root,
1005 char r_path[FILE_CACHE_MAX])
1006{
1007 char filename_full[FILE_MAXFILE + MAX_ID_NAME + 100];
1008 char filename[FILE_MAXFILE];
1009 char dirname[FILE_MAXDIR];
1010 char path_digest[16] = {0};
1011 char path_hexdigest[33];
1012
1013 /* If root is relative, use either current .blend file dir, or temp one if not saved. */
1014 const char *blendfile_path = BKE_main_blendfile_path_from_global();
1015 if (blendfile_path[0] != '\0') {
1016 BLI_path_split_dir_file(blendfile_path, dirname, sizeof(dirname), filename, sizeof(filename));
1017 BLI_path_extension_strip(filename); /* Strip `.blend`. */
1018 BLI_hash_md5_buffer(blendfile_path, strlen(blendfile_path), path_digest);
1019 }
1020 else {
1022 STRNCPY(filename, "UNSAVED");
1023 }
1024 BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
1025
1026 /* Default to *non-volatile* temp dir. */
1027 char root_buf[FILE_MAX];
1028 if (*root == '\0') {
1029 root = BKE_tempdir_base();
1030 }
1031 else if (BLI_path_is_rel(root)) {
1032 STRNCPY(root_buf, root);
1033 BLI_path_abs(root_buf, dirname);
1034 root = root_buf;
1035 }
1036
1037 SNPRINTF(filename_full, "cached_RR_%s_%s_%s.exr", filename, sce->id.name + 2, path_hexdigest);
1038
1039 BLI_path_join(r_path, FILE_CACHE_MAX, root, filename_full);
1040}
1041
1043{
1044 RenderResult *rr = re->result;
1045 char str[FILE_CACHE_MAX];
1046 const char *root = U.render_cachedir;
1047
1049
1051 printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
1052
1053 BKE_image_render_write_exr(nullptr, rr, str, nullptr, true, nullptr, -1);
1054}
1055
1057{
1058 /* File path to cache. */
1059 char filepath[FILE_CACHE_MAX] = "";
1060 const char *root = U.render_cachedir;
1061 render_result_exr_file_cache_path(re->scene, root, filepath);
1062
1063 printf("read exr cache file: %s\n", filepath);
1064
1065 /* Try opening the file. */
1066 void *exrhandle = IMB_exr_get_handle();
1067 int rectx, recty;
1068
1069 if (!IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty, true)) {
1070 printf("cannot read: %s\n", filepath);
1071 IMB_exr_close(exrhandle);
1072 return false;
1073 }
1074
1075 /* Read file contents into render result. */
1078
1079 IMB_exr_read_channels(exrhandle);
1080 re->result = render_result_new_from_exr(exrhandle, colorspace, false, rectx, recty);
1081
1082 IMB_exr_close(exrhandle);
1083
1084 return true;
1085}
1086
1088
1089/* -------------------------------------------------------------------- */
1092
1094 const ImageFormatData *imf,
1095 const float dither,
1096 const int view_id)
1097{
1098 ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, imf->planes, 0);
1099 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1100
1101 /* if not exists, BKE_imbuf_write makes one */
1102 if (rv->ibuf) {
1105 ibuf->channels = rv->ibuf->channels;
1106 }
1107
1110
1111 /* float factor for random dither, imbuf takes care of it */
1112 ibuf->dither = dither;
1113
1114 copy_v2_v2_db(ibuf->ppm, rr->ppm);
1115
1116 /* prepare to gamma correct to sRGB color space
1117 * note that sequence editor can generate 8bpc render buffers
1118 */
1119 if (ibuf->byte_buffer.data) {
1122 {
1123 if (imf->depth == R_IMF_CHAN_DEPTH_8) {
1124 /* Higher depth bits are supported but not needed for current file output. */
1126 }
1127 else {
1128 IMB_float_from_byte(ibuf);
1129 }
1130 }
1131 else {
1132 /* ensure no float buffer remained from previous frame */
1134 }
1135 }
1136
1137 /* Color -> gray-scale. */
1138 /* editing directly would alter the render view */
1139 if (imf->planes == R_IMF_PLANES_BW && imf->imtype != R_IMF_IMTYPE_MULTILAYER &&
1140 !(ibuf->float_buffer.data && !ibuf->byte_buffer.data && ibuf->channels == 1))
1141 {
1142 ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
1143 IMB_color_to_bw(ibuf_bw);
1144 IMB_freeImBuf(ibuf);
1145 ibuf = ibuf_bw;
1146 }
1147
1148 return ibuf;
1149}
1150
1151void RE_render_result_rect_from_ibuf(RenderResult *rr, const ImBuf *ibuf, const int view_id)
1152{
1153 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1154
1155 ImBuf *rv_ibuf = RE_RenderViewEnsureImBuf(rr, rv);
1156
1157 if (ibuf->float_buffer.data) {
1158 rr->have_combined = true;
1159
1160 if (!rv_ibuf->float_buffer.data) {
1161 float *data = MEM_malloc_arrayN<float>(4 * size_t(rr->rectx) * size_t(rr->recty),
1162 "render_seq float");
1164 }
1165
1166 memcpy(rv_ibuf->float_buffer.data,
1167 ibuf->float_buffer.data,
1168 sizeof(float[4]) * rr->rectx * rr->recty);
1169
1170 /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
1171 * can hang around when sequence render has rendered a 32 bits one before */
1172 IMB_free_byte_pixels(rv_ibuf);
1173 }
1174 else if (ibuf->byte_buffer.data) {
1175 rr->have_combined = true;
1176
1177 if (!rv_ibuf->byte_buffer.data) {
1178 uint8_t *data = MEM_malloc_arrayN<uint8_t>(4 * size_t(rr->rectx) * size_t(rr->recty),
1179 "render_seq byte");
1181 }
1182
1183 memcpy(rv_ibuf->byte_buffer.data, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
1184
1185 /* Same things as above, old rectf can hang around from previous render. */
1186 IMB_free_float_pixels(rv_ibuf);
1187 }
1188}
1189
1190void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
1191{
1192 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1193
1194 ImBuf *ibuf = RE_RenderViewEnsureImBuf(rr, rv);
1195
1196 if (!ibuf->float_buffer.data && !ibuf->byte_buffer.data) {
1197 uint8_t *data = MEM_calloc_arrayN<uint8_t>(4 * size_t(rr->rectx) * size_t(rr->recty),
1198 "render_seq rect");
1200 return;
1201 }
1202
1203 if (ibuf->float_buffer.data) {
1204 memset(ibuf->float_buffer.data, 0, sizeof(float[4]) * rr->rectx * rr->recty);
1205 }
1206
1207 if (ibuf->byte_buffer.data) {
1208 memset(ibuf->byte_buffer.data, 0, 4 * rr->rectx * rr->recty);
1209 }
1210}
1211
1213 uint *rect,
1214 int rectx,
1215 int recty,
1216 const ColorManagedViewSettings *view_settings,
1217 const ColorManagedDisplaySettings *display_settings,
1218 const int view_id)
1219{
1220 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1221 if (ImBuf *ibuf = rv ? rv->ibuf : nullptr) {
1222 if (ibuf->byte_buffer.data) {
1223 memcpy(rect, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
1224 return;
1225 }
1226 if (ibuf->float_buffer.data) {
1228 ibuf->float_buffer.data,
1229 rr->rectx,
1230 rr->recty,
1231 4,
1232 view_settings,
1233 display_settings,
1234 true);
1235 return;
1236 }
1237 }
1238
1239 /* Fill with black as a fallback. */
1240 memset(rect, 0, sizeof(int) * rectx * recty);
1241}
1242
1244
1245/* -------------------------------------------------------------------- */
1248
1250{
1251 if (result == nullptr) {
1252 return false;
1253 }
1254
1255 const RenderView *rv = static_cast<RenderView *>(result->views.first);
1256 if (rv == nullptr) {
1257 return false;
1258 }
1259
1260 return (rv->ibuf);
1261}
1262
1264{
1265 LISTBASE_FOREACH (const RenderView *, rview, &result->views) {
1266 ImBuf *ibuf = rview->ibuf;
1267 if (!ibuf) {
1268 continue;
1269 }
1270 if (ibuf->byte_buffer.data && !ibuf->float_buffer.data) {
1271 return false;
1272 }
1273 }
1274
1275 return true;
1276}
1277
1279{
1280 if (!BLI_findstring(&result->views, STEREO_LEFT_NAME, offsetof(RenderView, name))) {
1281 return false;
1282 }
1283
1285 return false;
1286 }
1287
1288 return true;
1289}
1290
1292{
1293 RenderView *rv = static_cast<RenderView *>(BLI_findlink(&rr->views, view_id));
1294 BLI_assert(rr->views.first);
1295 return rv ? rv : static_cast<RenderView *>(rr->views.first);
1296}
1297
1299{
1300 RenderView *rv = static_cast<RenderView *>(
1301 BLI_findstring(&rr->views, viewname, offsetof(RenderView, name)));
1302 BLI_assert(rr->views.first);
1303 return rv ? rv : static_cast<RenderView *>(rr->views.first);
1304}
1305
1307{
1308 RenderPass *new_rpass = MEM_dupallocN<RenderPass>("new render pass", *rpass);
1309 new_rpass->next = new_rpass->prev = nullptr;
1310
1311 new_rpass->ibuf = IMB_dupImBuf(rpass->ibuf);
1312
1313 return new_rpass;
1314}
1315
1317{
1318 RenderLayer *new_rl = MEM_dupallocN<RenderLayer>("new render layer", *rl);
1319 new_rl->next = new_rl->prev = nullptr;
1320 new_rl->passes.first = new_rl->passes.last = nullptr;
1321 new_rl->exrhandle = nullptr;
1322 LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
1323 RenderPass *new_rpass = duplicate_render_pass(rpass);
1324 BLI_addtail(&new_rl->passes, new_rpass);
1325 }
1326 return new_rl;
1327}
1328
1330{
1331 RenderView *new_rview = MEM_dupallocN<RenderView>("new render view", *rview);
1332
1333 new_rview->ibuf = IMB_dupImBuf(rview->ibuf);
1334
1335 return new_rview;
1336}
1337
1339{
1340 RenderResult *new_rr = MEM_dupallocN<RenderResult>("new duplicated render result", *rr);
1341 new_rr->next = new_rr->prev = nullptr;
1342 new_rr->layers.first = new_rr->layers.last = nullptr;
1343 new_rr->views.first = new_rr->views.last = nullptr;
1344 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
1345 RenderLayer *new_rl = duplicate_render_layer(rl);
1346 BLI_addtail(&new_rr->layers, new_rl);
1347 }
1348 LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
1349 RenderView *new_rview = duplicate_render_view(rview);
1350 BLI_addtail(&new_rr->views, new_rview);
1351 }
1352
1353 new_rr->ibuf = IMB_dupImBuf(rr->ibuf);
1354
1355 new_rr->stamp_data = BKE_stamp_data_copy(new_rr->stamp_data);
1356
1357 copy_v2_v2_db(new_rr->ppm, rr->ppm);
1358
1359 return new_rr;
1360}
1361
1363{
1364 if (!render_pass->ibuf) {
1365 render_pass->ibuf = IMB_allocImBuf(
1366 render_pass->rectx, render_pass->recty, get_num_planes_for_pass_ibuf(*render_pass), 0);
1367 render_pass->ibuf->channels = render_pass->channels;
1369 }
1370
1371 return render_pass->ibuf;
1372}
1373
1374ImBuf *RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *render_view)
1375{
1376 if (!render_view->ibuf) {
1377 render_view->ibuf = IMB_allocImBuf(render_result->rectx, render_result->recty, 32, 0);
1378 }
1379
1380 return render_view->ibuf;
1381}
1382
1383bool RE_RenderPassIsColor(const RenderPass *render_pass)
1384{
1385 return STR_ELEM(render_pass->chan_id, "RGB", "RGBA", "R", "G", "B", "A");
1386}
1387
const char * BKE_tempdir_base() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:1249
StampData * BKE_stamp_data_copy(const StampData *stamp_data)
void BKE_stamp_data_free(StampData *stamp_data)
char BKE_imtype_valid_depths(char imtype)
bool BKE_image_render_write_exr(ReportList *reports, const RenderResult *rr, const char *filepath, const ImageFormatData *imf, const bool save_as_render, const char *view, int layer)
const char * BKE_main_blendfile_path_from_global()
Definition main.cc:877
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv)
Definition scene.cc:3000
void BKE_scene_ppm_get(const RenderData *rd, double r_ppm[2])
Definition scene.cc:3245
#define BLI_assert(a)
Definition BLI_assert.h:46
char * BLI_hash_md5_to_hexdigest(const void *resblock, char r_hex_digest[33])
Definition hash_md5.cc:382
void * BLI_hash_md5_buffer(const char *buffer, size_t len, void *resblock)
Definition hash_md5.cc:346
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:332
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
int BLI_findstringindex(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:780
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
MINLINE void copy_v2_v2_db(double r[2], const double a[2])
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
bool bool BLI_path_extension_strip(char *path) ATTR_NONNULL(1)
#define FILE_MAXFILE
#define FILE_MAX
#define BLI_path_join(...)
void BLI_path_split_dir_file(const char *filepath, char *dir, size_t dir_maxncpy, char *file, size_t file_maxncpy) ATTR_NONNULL(1
bool BLI_path_is_rel(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAXDIR
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition BLI_rect.h:181
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition BLI_rect.h:177
#define STR_ELEM(...)
Definition BLI_string.h:656
int bool bool bool size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf) ATTR_NONNULL(1
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_string_join_array_by_sep_char(char *result, size_t result_maxncpy, char sep, const char *strings[], uint strings_num) ATTR_NONNULL()
unsigned char uchar
unsigned int uint
#define ARRAY_SET_ITEMS(...)
#define STREQ(a, b)
const char * dirname(char *path)
#define RE_PASSNAME_COMBINED
#define STEREO_LEFT_NAME
#define RE_PASSNAME_VECTOR
@ R_IMF_IMTYPE_MULTILAYER
@ R_IMF_PLANES_RGB
@ R_IMF_PLANES_RGBA
@ R_IMF_PLANES_BW
@ SCE_LAY_FLAG_DEFAULT
@ 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_Z
#define STEREO_RIGHT_NAME
@ R_MULTIVIEW
@ SCE_PASS_COMBINED
static AppView * view
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
@ GPU_DATA_FLOAT
@ GPU_TEXTURE_USAGE_GENERAL
eGPUTextureFormat
@ GPU_R32F
@ GPU_RGBA32F
@ GPU_RGB32F
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
#define Z
void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name)
void IMB_colormanagement_transform_float(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
@ COLOR_ROLE_DATA
@ COLOR_ROLE_SCENE_LINEAR
const char * IMB_colormanagement_role_colorspace_name_get(int role)
void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, int channels, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, bool predivide)
void IMB_free_gpu_textures(ImBuf *ibuf)
ImBuf * IMB_dupImBuf(const ImBuf *ibuf1)
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
void IMB_color_to_bw(ImBuf *ibuf)
void IMB_freeImBuf(ImBuf *ibuf)
ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
void IMB_free_float_pixels(ImBuf *ibuf)
void IMB_free_byte_pixels(ImBuf *ibuf)
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, ImBufOwnership ownership)
void IMB_float_from_byte(ImBuf *ibuf)
@ IB_DO_NOT_TAKE_OWNERSHIP
@ IB_TAKE_OWNERSHIP
#define EXR_LAY_MAXNAME
void IMB_exr_close(void *handle)
bool IMB_exr_begin_read(void *handle, const char *filepath, int *width, int *height, bool parse_channels)
bool IMB_exr_get_ppm(void *handle, double ppm[2])
#define EXR_PASS_MAXNAME
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_read_channels(void *handle)
bool IMB_exr_set_channel(void *handle, const char *layname, const char *passname, int xstride, int ystride, float *rect)
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))
void * IMB_exr_get_handle()
Read Guarded memory(de)allocation.
ReportList * reports
Definition WM_types.hh:1025
#define U
BMesh const char void * data
#define offsetof(t, d)
#define str(s)
#define printf(...)
#define MAX_ID_NAME
const ccl_global KernelWorkTile * tile
format
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static void render_result_exr_file_cache_path(Scene *sce, const char *root, char r_path[FILE_CACHE_MAX])
static int order_render_passes(const void *a, const void *b)
bool render_result_exr_file_read_path(RenderResult *rr, RenderLayer *rl_single, ReportList *reports, const char *filepath)
GPUTexture * RE_pass_ensure_gpu_texture_cache(Render *re, RenderPass *rpass)
static void render_result_views_free(RenderResult *rr)
ImBuf * RE_RenderPassEnsureImBuf(RenderPass *render_pass)
void RE_pass_set_buffer_data(RenderPass *pass, float *data)
RenderView * RE_RenderViewGetByName(RenderResult *rr, const char *viewname)
void render_result_single_layer_end(Render *re)
bool RE_HasCombinedLayer(const RenderResult *result)
void render_result_exr_file_cache_write(Render *re)
void render_result_free_gpu_texture_caches(RenderResult *rr)
ImBuf * RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *render_view)
bool RE_RenderPassIsColor(const RenderPass *render_pass)
bool render_result_exr_file_cache_read(Render *re)
void RE_render_result_rect_from_ibuf(RenderResult *rr, const ImBuf *ibuf, const int view_id)
void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
void render_result_views_shallowdelete(RenderResult *rr)
void render_result_views_new(RenderResult *rr, const RenderData *rd)
void render_result_merge(RenderResult *rr, RenderResult *rrpart)
bool RE_HasFloatPixels(const RenderResult *result)
void render_result_view_new(RenderResult *rr, const char *viewname)
RenderPass * render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id, const bool allocate)
ImBuf * RE_render_result_rect_to_ibuf(RenderResult *rr, const ImageFormatData *imf, const float dither, const int view_id)
void render_result_passes_allocated_ensure(RenderResult *rr)
static void render_layer_allocate_pass(RenderResult *rr, RenderPass *rp)
static void assign_render_pass_ibuf_colorspace(RenderPass &render_pass)
void render_result_free(RenderResult *rr)
RenderResult * render_result_new_from_exr(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
static RenderLayer * duplicate_render_layer(RenderLayer *rl)
static void * ml_addlayer_cb(void *base, const char *str)
void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
void render_result_free_list(ListBase *lb, RenderResult *rr)
void RE_render_result_full_channel_name(char *fullname, const char *layname, const char *passname, const char *viewname, const char *chan_id, const int channel)
RenderView * RE_RenderViewGetById(RenderResult *rr, const int view_id)
RenderResult * RE_DuplicateRenderResult(RenderResult *rr)
#define FILE_CACHE_MAX
static int passtype_from_name(const char *name)
static RenderView * duplicate_render_view(RenderView *rview)
void render_result_single_layer_begin(Render *re)
static void * ml_addview_cb(void *base, const char *str)
static void ml_addpass_cb(void *base, void *lay, const char *name, float *rect, int totchan, const char *chan_id, const char *view)
#define CHECK_PASS(NAME)
static RenderPass * duplicate_render_pass(RenderPass *rpass)
void render_result_rect_get_pixels(RenderResult *rr, uint *rect, int rectx, int recty, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const int view_id)
static int get_num_planes_for_pass_ibuf(const RenderPass &render_pass)
RenderResult * render_result_new(Render *re, const rcti *partrct, const char *layername, const char *viewname)
bool RE_RenderResult_is_stereo(const RenderResult *result)
void RE_create_render_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname, const bool allocate)
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 PASS_VECTOR_MAX
#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_)
void RE_FreeRenderResult(RenderResult *rr)
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
RenderResult * result
char name[66]
Definition DNA_ID.h:415
GPUTexture * texture
ImBufGPU gpu
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
double ppm[2]
void * last
void * first
ListBase passes
Definition RE_pipeline.h:89
char name[RE_MAXNAME]
Definition RE_pipeline.h:81
struct RenderLayer * next
Definition RE_pipeline.h:78
void * exrhandle
Definition RE_pipeline.h:87
struct RenderLayer * prev
Definition RE_pipeline.h:78
struct ImBuf * ibuf
Definition RE_pipeline.h:60
char chan_id[8]
Definition RE_pipeline.h:51
char name[64]
Definition RE_pipeline.h:50
char fullname[64]
Definition RE_pipeline.h:64
char view[64]
Definition RE_pipeline.h:65
struct RenderPass * prev
Definition RE_pipeline.h:48
struct RenderPass * next
Definition RE_pipeline.h:48
struct RenderResult * next
Definition RE_pipeline.h:93
ListBase views
ListBase layers
struct RenderResult * prev
Definition RE_pipeline.h:93
struct StampData * stamp_data
bool passes_allocated
double ppm[2]
struct ImBuf * ibuf
struct ImBuf * ibuf
Definition RE_pipeline.h:44
char name[64]
Definition RE_pipeline.h:39
bool result_has_gpu_texture_caches
RenderResult * pushedresult
RenderData r
Scene * scene
char single_view_layer[MAX_NAME]
rcti disprect
ListBase view_layers
int ymin
int ymax
int xmin
int xmax
uint len