Blender V4.3
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
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_threads.h"
23#include "BLI_utildefines.h"
24
25#include "BKE_appdir.hh"
26#include "BKE_global.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/* -------------------------------------------------------------------- */
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
133/* -------------------------------------------------------------------- */
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_cnew<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
170/* -------------------------------------------------------------------- */
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 /* Fallback 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_cnew_array<float>(rectsize, rp->name);
210
212 rp->ibuf->channels = rp->channels;
215
216 if (STREQ(rp->name, RE_PASSNAME_VECTOR)) {
217 /* initialize to max speed */
218 for (int x = rectsize - 1; x >= 0; x--) {
219 buffer_data[x] = PASS_VECTOR_MAX;
220 }
221 }
222 else if (STREQ(rp->name, RE_PASSNAME_Z)) {
223 for (int x = rectsize - 1; x >= 0; x--) {
224 buffer_data[x] = 10e10;
225 }
226 }
227}
228
230 RenderLayer *rl,
231 int channels,
232 const char *name,
233 const char *viewname,
234 const char *chan_id,
235 const bool allocate)
236{
237 const int view_id = BLI_findstringindex(&rr->views, viewname, offsetof(RenderView, name));
238 RenderPass *rpass = MEM_cnew<RenderPass>(name);
239
240 rpass->channels = channels;
241 rpass->rectx = rl->rectx;
242 rpass->recty = rl->recty;
243 rpass->view_id = view_id;
244
245 STRNCPY(rpass->name, name);
246 STRNCPY(rpass->chan_id, chan_id);
247 STRNCPY(rpass->view, viewname);
249 rpass->fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, -1);
250
251 if (rl->exrhandle) {
252 int a;
253 for (a = 0; a < channels; a++) {
254 char passname[EXR_PASS_MAXNAME];
256 passname, nullptr, rpass->name, nullptr, rpass->chan_id, a);
257 IMB_exr_add_channel(rl->exrhandle, rl->name, passname, viewname, 0, 0, nullptr, false);
258 }
259 }
260
261 BLI_addtail(&rl->passes, rpass);
262
263 if (allocate) {
265 }
266 else {
267 /* The result contains non-allocated pass now, so tag it as such. */
268 rr->passes_allocated = false;
269 }
270
271 return rpass;
272}
273
275 const rcti *partrct,
276 const char *layername,
277 const char *viewname)
278{
279 RenderResult *rr;
280 RenderLayer *rl;
281 int rectx, recty;
282
283 rectx = BLI_rcti_size_x(partrct);
284 recty = BLI_rcti_size_y(partrct);
285
286 if (rectx <= 0 || recty <= 0) {
287 return nullptr;
288 }
289
290 rr = MEM_cnew<RenderResult>("new render result");
291 rr->rectx = rectx;
292 rr->recty = recty;
293
294 /* tilerect is relative coordinates within render disprect. do not subtract crop yet */
295 rr->tilerect.xmin = partrct->xmin - re->disprect.xmin;
296 rr->tilerect.xmax = partrct->xmax - re->disprect.xmin;
297 rr->tilerect.ymin = partrct->ymin - re->disprect.ymin;
298 rr->tilerect.ymax = partrct->ymax - re->disprect.ymin;
299
300 rr->passes_allocated = false;
301
302 render_result_views_new(rr, &re->r);
303
304 /* Check render-data for amount of layers. */
305 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
306 if (layername && layername[0]) {
307 if (!STREQ(view_layer->name, layername)) {
308 continue;
309 }
310 }
311
312 rl = MEM_cnew<RenderLayer>("new render layer");
313 BLI_addtail(&rr->layers, rl);
314
315 STRNCPY(rl->name, view_layer->name);
316 rl->layflag = view_layer->layflag;
317
318 rl->passflag = view_layer->passflag;
319
320 rl->rectx = rectx;
321 rl->recty = recty;
322
323 LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
324 const char *view = rv->name;
325
326 if (viewname && viewname[0]) {
327 if (!STREQ(view, viewname)) {
328 continue;
329 }
330 }
331
332 /* A render-layer should always have a "Combined" pass. */
333 render_layer_add_pass(rr, rl, 4, "Combined", view, "RGBA", false);
334 }
335 }
337
338 /* Preview-render doesn't do layers, so we make a default one. */
339 if (BLI_listbase_is_empty(&rr->layers) && !(layername && layername[0])) {
340 rl = MEM_cnew<RenderLayer>("new render layer");
341 BLI_addtail(&rr->layers, rl);
342
343 rl->rectx = rectx;
344 rl->recty = recty;
345
346 LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
347 const char *view = rv->name;
348
349 if (viewname && viewname[0]) {
350 if (!STREQ(view, viewname)) {
351 continue;
352 }
353 }
354
355 /* A render-layer should always have a "Combined" pass. */
356 render_layer_add_pass(rr, rl, 4, RE_PASSNAME_COMBINED, view, "RGBA", false);
357 }
358
359 /* NOTE: this has to be in sync with `scene.cc`. */
362
363 re->single_view_layer[0] = '\0';
364 }
365
366 /* Border render; calculate offset for use in compositor. compo is centralized coords. */
367 /* XXX(ton): obsolete? I now use it for drawing border render offset. */
368 rr->xof = re->disprect.xmin + BLI_rcti_cent_x(&re->disprect) - (re->winx / 2);
369 rr->yof = re->disprect.ymin + BLI_rcti_cent_y(&re->disprect) - (re->winy / 2);
370
371 return rr;
372}
373
375{
376 if (rr == nullptr) {
377 /* Happens when the result was not yet allocated for the current scene or slot configuration.
378 */
379 return;
380 }
381
382 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
383 LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
384 if (rl->exrhandle != nullptr && !STREQ(rp->name, RE_PASSNAME_COMBINED)) {
385 continue;
386 }
387
389 }
390 }
391
392 rr->passes_allocated = true;
393}
394
395void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
396{
397 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
398 RenderLayer *main_rl = RE_GetRenderLayer(re->result, rl->name);
399 if (!main_rl) {
400 continue;
401 }
402
403 LISTBASE_FOREACH (RenderPass *, main_rp, &main_rl->passes) {
404 if (viewname && viewname[0] && !STREQ(main_rp->view, viewname)) {
405 continue;
406 }
407
408 /* Compare `fullname` to make sure that the view also is equal. */
409 const RenderPass *rp = static_cast<const RenderPass *>(
410 BLI_findstring(&rl->passes, main_rp->fullname, offsetof(RenderPass, fullname)));
411 if (!rp) {
413 rr, rl, main_rp->channels, main_rp->name, main_rp->view, main_rp->chan_id, false);
414 }
415 }
416 }
417}
418
420 const char *name,
421 int channels,
422 const char *chan_id,
423 const char *layername,
424 const char *viewname,
425 const bool allocate)
426{
427 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
428 if (layername && layername[0] && !STREQ(rl->name, layername)) {
429 continue;
430 }
431
432 LISTBASE_FOREACH (RenderView *, rv, &rr->views) {
433 const char *view = rv->name;
434
435 if (viewname && viewname[0] && !STREQ(view, viewname)) {
436 continue;
437 }
438
439 /* Ensure that the pass doesn't exist yet. */
440 bool pass_exists = false;
441 LISTBASE_FOREACH (RenderPass *, rp, &rl->passes) {
442 if (STREQ(rp->name, name) && STREQ(rp->view, view)) {
443 pass_exists = true;
444 break;
445 }
446 }
447
448 if (!pass_exists) {
449 render_layer_add_pass(rr, rl, channels, name, view, chan_id, allocate);
450 }
451 }
452 }
453}
454
455void RE_pass_set_buffer_data(RenderPass *pass, float *data)
456{
457 ImBuf *ibuf = RE_RenderPassEnsureImBuf(pass);
458
460}
461
463{
464 ImBuf *ibuf = rpass->ibuf;
465
466 if (!ibuf) {
467 /* No existing GPU texture, but also no CPU side data to create it from. */
468 return nullptr;
469 }
470
471 if (ibuf->gpu.texture) {
472 /* Return existing GPU texture, regardless whether it also exists on CPU or not. */
473 return ibuf->gpu.texture;
474 }
475
476 if (ibuf->float_buffer.data == nullptr) {
477 /* No CPU side data to create the texture from. */
478 return nullptr;
479 }
480
481 const eGPUTextureFormat format = (rpass->channels == 1) ? GPU_R32F :
482 (rpass->channels == 3) ? GPU_RGB32F :
484
485 /* TODO(sergey): Use utility to assign the texture. */
486 ibuf->gpu.texture = GPU_texture_create_2d("RenderBuffer.gpu_texture",
487 rpass->rectx,
488 rpass->recty,
489 1,
490 format,
492 nullptr);
493
494 if (ibuf->gpu.texture) {
497 }
498
499 return ibuf->gpu.texture;
500}
501
503 const char *layname,
504 const char *passname,
505 const char *viewname,
506 const char *chan_id,
507 const int channel)
508{
509 /* OpenEXR compatible full channel name. */
510 const char *strings[4];
511 int strings_len = 0;
512
513 if (layname && layname[0]) {
514 strings[strings_len++] = layname;
515 }
516 if (passname && passname[0]) {
517 strings[strings_len++] = passname;
518 }
519 if (viewname && viewname[0]) {
520 strings[strings_len++] = viewname;
521 }
522
523 char token[2];
524 if (channel >= 0) {
525 ARRAY_SET_ITEMS(token, chan_id[channel], '\0');
526 strings[strings_len++] = token;
527 }
528
529 BLI_string_join_array_by_sep_char(fullname, EXR_PASS_MAXNAME, '.', strings, strings_len);
530}
531
532static int passtype_from_name(const char *name)
533{
534 const char delim[] = {'.', '\0'};
535 const char *sep, *suf;
536 int len = BLI_str_partition(name, delim, &sep, &suf);
537
538#define CHECK_PASS(NAME) \
539 if (STREQLEN(name, RE_PASSNAME_##NAME, len)) { \
540 return SCE_PASS_##NAME; \
541 } \
542 ((void)0)
543
544 CHECK_PASS(COMBINED);
545 CHECK_PASS(Z);
546 CHECK_PASS(VECTOR);
547 CHECK_PASS(NORMAL);
548 CHECK_PASS(UV);
549 CHECK_PASS(EMIT);
550 CHECK_PASS(SHADOW);
551 CHECK_PASS(AO);
552 CHECK_PASS(ENVIRONMENT);
553 CHECK_PASS(INDEXOB);
554 CHECK_PASS(INDEXMA);
555 CHECK_PASS(MIST);
556 CHECK_PASS(DIFFUSE_DIRECT);
557 CHECK_PASS(DIFFUSE_INDIRECT);
558 CHECK_PASS(DIFFUSE_COLOR);
559 CHECK_PASS(GLOSSY_DIRECT);
560 CHECK_PASS(GLOSSY_INDIRECT);
561 CHECK_PASS(GLOSSY_COLOR);
562 CHECK_PASS(TRANSM_DIRECT);
563 CHECK_PASS(TRANSM_INDIRECT);
564 CHECK_PASS(TRANSM_COLOR);
565 CHECK_PASS(SUBSURFACE_DIRECT);
566 CHECK_PASS(SUBSURFACE_INDIRECT);
567 CHECK_PASS(SUBSURFACE_COLOR);
568
569#undef CHECK_PASS
570 return 0;
571}
572
573/* callbacks for render_result_new_from_exr */
574static void *ml_addlayer_cb(void *base, const char *str)
575{
576 RenderResult *rr = static_cast<RenderResult *>(base);
577
578 RenderLayer *rl = MEM_cnew<RenderLayer>("new render layer");
579 BLI_addtail(&rr->layers, rl);
580
582 return rl;
583}
584
585static void ml_addpass_cb(void *base,
586 void *lay,
587 const char *name,
588 float *rect,
589 int totchan,
590 const char *chan_id,
591 const char *view)
592{
593 RenderResult *rr = static_cast<RenderResult *>(base);
594 RenderLayer *rl = static_cast<RenderLayer *>(lay);
595 RenderPass *rpass = MEM_cnew<RenderPass>("loaded pass");
596
597 BLI_addtail(&rl->passes, rpass);
598 rpass->rectx = rr->rectx;
599 rpass->recty = rr->recty;
600 rpass->channels = totchan;
601 rl->passflag |= passtype_from_name(name);
602
603 /* channel id chars */
604 STRNCPY(rpass->chan_id, chan_id);
605
606 RE_pass_set_buffer_data(rpass, rect);
607
608 STRNCPY(rpass->name, name);
609 STRNCPY(rpass->view, view);
610 RE_render_result_full_channel_name(rpass->fullname, nullptr, name, view, rpass->chan_id, -1);
611
612 if (view[0] != '\0') {
613 rpass->view_id = BLI_findstringindex(&rr->views, view, offsetof(RenderView, name));
614 }
615 else {
616 rpass->view_id = 0;
617 }
618}
619
620static void *ml_addview_cb(void *base, const char *str)
621{
622 RenderResult *rr = static_cast<RenderResult *>(base);
623
624 RenderView *rv = MEM_cnew<RenderView>("new render view");
625 STRNCPY(rv->name, str);
626
627 /* For stereo drawing we need to ensure:
628 * STEREO_LEFT_NAME == STEREO_LEFT_ID and
629 * STEREO_RIGHT_NAME == STEREO_RIGHT_ID */
630
631 if (STREQ(str, STEREO_LEFT_NAME)) {
632 BLI_addhead(&rr->views, rv);
633 }
634 else if (STREQ(str, STEREO_RIGHT_NAME)) {
635 RenderView *left_rv = static_cast<RenderView *>(
637
638 if (left_rv == nullptr) {
639 BLI_addhead(&rr->views, rv);
640 }
641 else {
642 BLI_insertlinkafter(&rr->views, left_rv, rv);
643 }
644 }
645 else {
646 BLI_addtail(&rr->views, rv);
647 }
648
649 return rv;
650}
651
652static int order_render_passes(const void *a, const void *b)
653{
654 /* 1 if `a` is after `b`. */
655 const RenderPass *rpa = (const RenderPass *)a;
656 const RenderPass *rpb = (const RenderPass *)b;
657 uint passtype_a = passtype_from_name(rpa->name);
658 uint passtype_b = passtype_from_name(rpb->name);
659
660 /* Render passes with default type always go first. */
661 if (passtype_b && !passtype_a) {
662 return 1;
663 }
664 if (passtype_a && !passtype_b) {
665 return 0;
666 }
667
668 if (passtype_a && passtype_b) {
669 if (passtype_a > passtype_b) {
670 return 1;
671 }
672 if (passtype_a < passtype_b) {
673 return 0;
674 }
675 }
676 else {
677 int cmp = strncmp(rpa->name, rpb->name, EXR_PASS_MAXNAME);
678 if (cmp > 0) {
679 return 1;
680 }
681 if (cmp < 0) {
682 return 0;
683 }
684 }
685
686 /* they have the same type */
687 /* left first */
688 if (STREQ(rpa->view, STEREO_LEFT_NAME)) {
689 return 0;
690 }
691 if (STREQ(rpb->view, STEREO_LEFT_NAME)) {
692 return 1;
693 }
694
695 /* right second */
696 if (STREQ(rpa->view, STEREO_RIGHT_NAME)) {
697 return 0;
698 }
699 if (STREQ(rpb->view, STEREO_RIGHT_NAME)) {
700 return 1;
701 }
702
703 /* remaining in ascending id order */
704 return (rpa->view_id < rpb->view_id);
705}
706
708 void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty)
709{
710 RenderResult *rr = MEM_cnew<RenderResult>(__func__);
711 const char *to_colorspace = IMB_colormanagement_role_colorspace_name_get(
714
715 rr->rectx = rectx;
716 rr->recty = recty;
717
719
720 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
721 rl->rectx = rectx;
722 rl->recty = recty;
723
725
726 LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
727 rpass->rectx = rectx;
728 rpass->recty = recty;
729
730 if (RE_RenderPassIsColor(rpass)) {
731 IMB_colormanagement_transform(rpass->ibuf->float_buffer.data,
732 rpass->rectx,
733 rpass->recty,
734 rpass->channels,
735 colorspace,
736 to_colorspace,
737 predivide);
738 }
739 else {
740 IMB_colormanagement_assign_float_colorspace(rpass->ibuf, data_colorspace);
741 }
742 }
743 }
744
745 return rr;
746}
747
748void render_result_view_new(RenderResult *rr, const char *viewname)
749{
750 RenderView *rv = MEM_cnew<RenderView>("new render view");
751 BLI_addtail(&rr->views, rv);
752 STRNCPY(rv->name, viewname);
753}
754
756{
757 /* clear previously existing views - for sequencer */
759
760 /* check renderdata for amount of views */
761 if (rd->scemode & R_MULTIVIEW) {
762 LISTBASE_FOREACH (SceneRenderView *, srv, &rd->views) {
763 if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) {
764 continue;
765 }
766 render_result_view_new(rr, srv->name);
767 }
768 }
769
770 /* we always need at least one view */
771 if (BLI_listbase_is_empty(&rr->views)) {
773 }
774}
775
778/* -------------------------------------------------------------------- */
782static void do_merge_tile(
783 RenderResult *rr, RenderResult *rrpart, float *target, float *tile, int pixsize)
784{
785 int y, tilex, tiley;
786 size_t ofs, copylen;
787
788 copylen = tilex = rrpart->rectx;
789 tiley = rrpart->recty;
790
791 ofs = (size_t(rrpart->tilerect.ymin) * rr->rectx + rrpart->tilerect.xmin);
792 target += pixsize * ofs;
793
794 copylen *= sizeof(float) * pixsize;
795 tilex *= pixsize;
796 ofs = pixsize * rr->rectx;
797
798 for (y = 0; y < tiley; y++) {
799 memcpy(target, tile, copylen);
800 target += ofs;
801 tile += tilex;
802 }
803}
804
806{
807 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
808 RenderLayer *rlp = RE_GetRenderLayer(rrpart, rl->name);
809
810 if (rlp) {
811 /* Passes are allocated in sync. */
812 for (RenderPass *rpass = static_cast<RenderPass *>(rl->passes.first),
813 *rpassp = static_cast<RenderPass *>(rlp->passes.first);
814 rpass && rpassp;
815 rpass = rpass->next)
816 {
817 /* For save buffers, skip any passes that are only saved to disk. */
818 if (rpass->ibuf == nullptr || rpassp->ibuf == nullptr) {
819 continue;
820 }
821 if (rpass->ibuf->float_buffer.data == nullptr ||
822 rpassp->ibuf->float_buffer.data == nullptr)
823 {
824 continue;
825 }
826 /* Render-result have all passes, render-part only the active view's passes. */
827 if (!STREQ(rpassp->fullname, rpass->fullname)) {
828 continue;
829 }
830
831 do_merge_tile(rr,
832 rrpart,
833 rpass->ibuf->float_buffer.data,
834 rpassp->ibuf->float_buffer.data,
835 rpass->channels);
836
837 /* manually get next render pass */
838 rpassp = rpassp->next;
839 }
840 }
841 }
842}
843
846/* -------------------------------------------------------------------- */
851{
852 /* all layers except the active one get temporally pushed away */
853
854 /* officially pushed result should be nullptr... error can happen with do_seq */
856
857 re->pushedresult = re->result;
858 re->result = nullptr;
859}
860
862{
863 if (re->result == nullptr) {
864 printf("pop render result error; no current result!\n");
865 return;
866 }
867
868 if (!re->pushedresult) {
869 return;
870 }
871
872 if (re->pushedresult->rectx == re->result->rectx && re->pushedresult->recty == re->result->recty)
873 {
874 /* find which layer in re->pushedresult should be replaced */
875 RenderLayer *rl = static_cast<RenderLayer *>(re->result->layers.first);
876
877 /* render result should be empty after this */
878 BLI_remlink(&re->result->layers, rl);
879
880 /* reconstruct render result layers */
881 LISTBASE_FOREACH (ViewLayer *, view_layer, &re->scene->view_layers) {
882 if (STREQ(view_layer->name, re->single_view_layer)) {
883 BLI_addtail(&re->result->layers, rl);
884 }
885 else {
886 RenderLayer *rlpush = RE_GetRenderLayer(re->pushedresult, view_layer->name);
887 if (rlpush) {
888 BLI_remlink(&re->pushedresult->layers, rlpush);
889 BLI_addtail(&re->result->layers, rlpush);
890 }
891 }
892 }
893 }
894
896 re->pushedresult = nullptr;
897}
898
900 RenderLayer *rl_single,
901 ReportList *reports,
902 const char *filepath)
903{
904 void *exrhandle = IMB_exr_get_handle();
905 int rectx, recty;
906
907 if (!IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty, false)) {
908 IMB_exr_close(exrhandle);
909 return false;
910 }
911
912 ListBase layers = (rr) ? rr->layers : ListBase{rl_single, rl_single};
913 const int expected_rectx = (rr) ? rr->rectx : rl_single->rectx;
914 const int expected_recty = (rr) ? rr->recty : rl_single->recty;
915 bool found_channels = false;
916
917 if (rectx != expected_rectx || recty != expected_recty) {
918 BKE_reportf(reports,
919 RPT_ERROR,
920 "Reading render result: dimensions don't match, expected %dx%d",
921 expected_rectx,
922 expected_recty);
923 IMB_exr_close(exrhandle);
924 return true;
925 }
926
927 LISTBASE_FOREACH (RenderLayer *, rl, &layers) {
928 if (rl_single && rl_single != rl) {
929 continue;
930 }
931
932 /* passes are allocated in sync */
933 LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
934 const int xstride = rpass->channels;
935 const int ystride = xstride * rectx;
936 int a;
937 char fullname[EXR_PASS_MAXNAME];
938
939 for (a = 0; a < xstride; a++) {
941 fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, a);
942
943 if (IMB_exr_set_channel(exrhandle,
944 rl->name,
945 fullname,
946 xstride,
947 ystride,
948 rpass->ibuf->float_buffer.data + a))
949 {
950 found_channels = true;
951 }
952 else if (rl_single) {
953 if (IMB_exr_set_channel(exrhandle,
954 nullptr,
955 fullname,
956 xstride,
957 ystride,
958 rpass->ibuf->float_buffer.data + a))
959 {
960 found_channels = true;
961 }
962 else {
963 BKE_reportf(nullptr,
965 "Reading render result: expected channel \"%s.%s\" or \"%s\" not found",
966 rl->name,
967 fullname,
968 fullname);
969 }
970 }
971 else {
972 BKE_reportf(nullptr,
974 "Reading render result: expected channel \"%s.%s\" not found",
975 rl->name,
976 fullname);
977 }
978 }
979
981 rpass->fullname, nullptr, rpass->name, rpass->view, rpass->chan_id, -1);
982 }
983 }
984
985 if (found_channels) {
986 IMB_exr_read_channels(exrhandle);
987 }
988
989 IMB_exr_close(exrhandle);
990
991 return true;
992}
993
994#define FILE_CACHE_MAX (FILE_MAXDIR + FILE_MAXFILE + MAX_ID_NAME + 100)
995
997 const char *root,
998 char r_path[FILE_CACHE_MAX])
999{
1000 char filename_full[FILE_MAXFILE + MAX_ID_NAME + 100];
1001 char filename[FILE_MAXFILE];
1002 char dirname[FILE_MAXDIR];
1003 char path_digest[16] = {0};
1004 char path_hexdigest[33];
1005
1006 /* If root is relative, use either current .blend file dir, or temp one if not saved. */
1007 const char *blendfile_path = BKE_main_blendfile_path_from_global();
1008 if (blendfile_path[0] != '\0') {
1009 BLI_path_split_dir_file(blendfile_path, dirname, sizeof(dirname), filename, sizeof(filename));
1010 BLI_path_extension_strip(filename); /* Strip `.blend`. */
1011 BLI_hash_md5_buffer(blendfile_path, strlen(blendfile_path), path_digest);
1012 }
1013 else {
1015 STRNCPY(filename, "UNSAVED");
1016 }
1017 BLI_hash_md5_to_hexdigest(path_digest, path_hexdigest);
1018
1019 /* Default to *non-volatile* temp dir. */
1020 char root_buf[FILE_MAX];
1021 if (*root == '\0') {
1022 root = BKE_tempdir_base();
1023 }
1024 else if (BLI_path_is_rel(root)) {
1025 STRNCPY(root_buf, root);
1026 BLI_path_abs(root_buf, dirname);
1027 root = root_buf;
1028 }
1029
1030 SNPRINTF(filename_full, "cached_RR_%s_%s_%s.exr", filename, sce->id.name + 2, path_hexdigest);
1031
1032 BLI_path_join(r_path, FILE_CACHE_MAX, root, filename_full);
1033}
1034
1036{
1037 RenderResult *rr = re->result;
1038 char str[FILE_CACHE_MAX];
1039 const char *root = U.render_cachedir;
1040
1042
1044 printf("Caching exr file, %dx%d, %s\n", rr->rectx, rr->recty, str);
1045
1046 BKE_image_render_write_exr(nullptr, rr, str, nullptr, true, nullptr, -1);
1047}
1048
1050{
1051 /* File path to cache. */
1052 char filepath[FILE_CACHE_MAX] = "";
1053 const char *root = U.render_cachedir;
1054 render_result_exr_file_cache_path(re->scene, root, filepath);
1055
1056 printf("read exr cache file: %s\n", filepath);
1057
1058 /* Try opening the file. */
1059 void *exrhandle = IMB_exr_get_handle();
1060 int rectx, recty;
1061
1062 if (!IMB_exr_begin_read(exrhandle, filepath, &rectx, &recty, true)) {
1063 printf("cannot read: %s\n", filepath);
1064 IMB_exr_close(exrhandle);
1065 return false;
1066 }
1067
1068 /* Read file contents into render result. */
1071
1072 IMB_exr_read_channels(exrhandle);
1073 re->result = render_result_new_from_exr(exrhandle, colorspace, false, rectx, recty);
1074
1075 IMB_exr_close(exrhandle);
1076
1077 return true;
1078}
1079
1082/* -------------------------------------------------------------------- */
1087 const ImageFormatData *imf,
1088 const float dither,
1089 const int view_id)
1090{
1091 ImBuf *ibuf = IMB_allocImBuf(rr->rectx, rr->recty, imf->planes, 0);
1092 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1093
1094 /* if not exists, BKE_imbuf_write makes one */
1095 if (rv->ibuf) {
1098 ibuf->channels = rv->ibuf->channels;
1099 }
1100
1103
1104 /* float factor for random dither, imbuf takes care of it */
1105 ibuf->dither = dither;
1106
1107 /* prepare to gamma correct to sRGB color space
1108 * note that sequence editor can generate 8bpc render buffers
1109 */
1110 if (ibuf->byte_buffer.data) {
1113 {
1114 if (imf->depth == R_IMF_CHAN_DEPTH_8) {
1115 /* Higher depth bits are supported but not needed for current file output. */
1117 }
1118 else {
1119 IMB_float_from_rect(ibuf);
1120 }
1121 }
1122 else {
1123 /* ensure no float buffer remained from previous frame */
1125 }
1126 }
1127
1128 /* Color -> gray-scale. */
1129 /* editing directly would alter the render view */
1130 if (imf->planes == R_IMF_PLANES_BW && imf->imtype != R_IMF_IMTYPE_MULTILAYER &&
1131 !(ibuf->float_buffer.data && !ibuf->byte_buffer.data && ibuf->channels == 1))
1132 {
1133 ImBuf *ibuf_bw = IMB_dupImBuf(ibuf);
1134 IMB_color_to_bw(ibuf_bw);
1135 IMB_freeImBuf(ibuf);
1136 ibuf = ibuf_bw;
1137 }
1138
1139 return ibuf;
1140}
1141
1142void RE_render_result_rect_from_ibuf(RenderResult *rr, const ImBuf *ibuf, const int view_id)
1143{
1144 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1145
1146 ImBuf *rv_ibuf = RE_RenderViewEnsureImBuf(rr, rv);
1147
1148 if (ibuf->float_buffer.data) {
1149 rr->have_combined = true;
1150
1151 if (!rv_ibuf->float_buffer.data) {
1152 float *data = MEM_cnew_array<float>(4 * rr->rectx * rr->recty, "render_seq rectf");
1154 }
1155
1156 memcpy(rv_ibuf->float_buffer.data,
1157 ibuf->float_buffer.data,
1158 sizeof(float[4]) * rr->rectx * rr->recty);
1159
1160 /* TSK! Since sequence render doesn't free the *rr render result, the old rect32
1161 * can hang around when sequence render has rendered a 32 bits one before */
1162 imb_freerectImBuf(rv_ibuf);
1163 }
1164 else if (ibuf->byte_buffer.data) {
1165 rr->have_combined = true;
1166
1167 if (!rv_ibuf->byte_buffer.data) {
1168 uint8_t *data = MEM_cnew_array<uint8_t>(4 * rr->rectx * rr->recty, "render_seq rect");
1170 }
1171
1172 memcpy(rv_ibuf->byte_buffer.data, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
1173
1174 /* Same things as above, old rectf can hang around from previous render. */
1175 imb_freerectfloatImBuf(rv_ibuf);
1176 }
1177}
1178
1179void render_result_rect_fill_zero(RenderResult *rr, const int view_id)
1180{
1181 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1182
1183 ImBuf *ibuf = RE_RenderViewEnsureImBuf(rr, rv);
1184
1185 if (!ibuf->float_buffer.data && !ibuf->byte_buffer.data) {
1186 uint8_t *data = MEM_cnew_array<uint8_t>(4 * rr->rectx * rr->recty, "render_seq rect");
1188 return;
1189 }
1190
1191 if (ibuf->float_buffer.data) {
1192 memset(ibuf->float_buffer.data, 0, sizeof(float[4]) * rr->rectx * rr->recty);
1193 }
1194
1195 if (ibuf->byte_buffer.data) {
1196 memset(ibuf->byte_buffer.data, 0, 4 * rr->rectx * rr->recty);
1197 }
1198}
1199
1201 uint *rect,
1202 int rectx,
1203 int recty,
1204 const ColorManagedViewSettings *view_settings,
1205 const ColorManagedDisplaySettings *display_settings,
1206 const int view_id)
1207{
1208 RenderView *rv = RE_RenderViewGetById(rr, view_id);
1209 if (ImBuf *ibuf = rv ? rv->ibuf : nullptr) {
1210 if (ibuf->byte_buffer.data) {
1211 memcpy(rect, ibuf->byte_buffer.data, sizeof(int) * rr->rectx * rr->recty);
1212 return;
1213 }
1214 if (ibuf->float_buffer.data) {
1216 ibuf->float_buffer.data,
1217 rr->rectx,
1218 rr->recty,
1219 4,
1220 view_settings,
1221 display_settings,
1222 true);
1223 return;
1224 }
1225 }
1226
1227 /* Fill with black as a fallback. */
1228 memset(rect, 0, sizeof(int) * rectx * recty);
1229}
1230
1233/* -------------------------------------------------------------------- */
1238{
1239 if (result == nullptr) {
1240 return false;
1241 }
1242
1243 const RenderView *rv = static_cast<RenderView *>(result->views.first);
1244 if (rv == nullptr) {
1245 return false;
1246 }
1247
1248 return (rv->ibuf);
1249}
1250
1252{
1253 LISTBASE_FOREACH (const RenderView *, rview, &result->views) {
1254 ImBuf *ibuf = rview->ibuf;
1255 if (!ibuf) {
1256 continue;
1257 }
1258 if (ibuf->byte_buffer.data && !ibuf->float_buffer.data) {
1259 return false;
1260 }
1261 }
1262
1263 return true;
1264}
1265
1267{
1268 if (!BLI_findstring(&result->views, STEREO_LEFT_NAME, offsetof(RenderView, name))) {
1269 return false;
1270 }
1271
1272 if (!BLI_findstring(&result->views, STEREO_RIGHT_NAME, offsetof(RenderView, name))) {
1273 return false;
1274 }
1275
1276 return true;
1277}
1278
1280{
1281 RenderView *rv = static_cast<RenderView *>(BLI_findlink(&rr->views, view_id));
1282 BLI_assert(rr->views.first);
1283 return rv ? rv : static_cast<RenderView *>(rr->views.first);
1284}
1285
1287{
1288 RenderView *rv = static_cast<RenderView *>(
1289 BLI_findstring(&rr->views, viewname, offsetof(RenderView, name)));
1290 BLI_assert(rr->views.first);
1291 return rv ? rv : static_cast<RenderView *>(rr->views.first);
1292}
1293
1295{
1296 RenderPass *new_rpass = MEM_cnew<RenderPass>("new render pass", *rpass);
1297 new_rpass->next = new_rpass->prev = nullptr;
1298
1299 new_rpass->ibuf = IMB_dupImBuf(rpass->ibuf);
1300
1301 return new_rpass;
1302}
1303
1305{
1306 RenderLayer *new_rl = MEM_cnew<RenderLayer>("new render layer", *rl);
1307 new_rl->next = new_rl->prev = nullptr;
1308 new_rl->passes.first = new_rl->passes.last = nullptr;
1309 new_rl->exrhandle = nullptr;
1310 LISTBASE_FOREACH (RenderPass *, rpass, &rl->passes) {
1311 RenderPass *new_rpass = duplicate_render_pass(rpass);
1312 BLI_addtail(&new_rl->passes, new_rpass);
1313 }
1314 return new_rl;
1315}
1316
1318{
1319 RenderView *new_rview = MEM_cnew<RenderView>("new render view", *rview);
1320
1321 new_rview->ibuf = IMB_dupImBuf(rview->ibuf);
1322
1323 return new_rview;
1324}
1325
1327{
1328 RenderResult *new_rr = MEM_cnew<RenderResult>("new duplicated render result", *rr);
1329 new_rr->next = new_rr->prev = nullptr;
1330 new_rr->layers.first = new_rr->layers.last = nullptr;
1331 new_rr->views.first = new_rr->views.last = nullptr;
1332 LISTBASE_FOREACH (RenderLayer *, rl, &rr->layers) {
1333 RenderLayer *new_rl = duplicate_render_layer(rl);
1334 BLI_addtail(&new_rr->layers, new_rl);
1335 }
1336 LISTBASE_FOREACH (RenderView *, rview, &rr->views) {
1337 RenderView *new_rview = duplicate_render_view(rview);
1338 BLI_addtail(&new_rr->views, new_rview);
1339 }
1340
1341 new_rr->ibuf = IMB_dupImBuf(rr->ibuf);
1342
1343 new_rr->stamp_data = BKE_stamp_data_copy(new_rr->stamp_data);
1344 return new_rr;
1345}
1346
1348{
1349 if (!render_pass->ibuf) {
1350 render_pass->ibuf = IMB_allocImBuf(
1351 render_pass->rectx, render_pass->recty, get_num_planes_for_pass_ibuf(*render_pass), 0);
1352 render_pass->ibuf->channels = render_pass->channels;
1354 }
1355
1356 return render_pass->ibuf;
1357}
1358
1359ImBuf *RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *render_view)
1360{
1361 if (!render_view->ibuf) {
1362 render_view->ibuf = IMB_allocImBuf(render_result->rectx, render_result->recty, 32, 0);
1363 }
1364
1365 return render_view->ibuf;
1366}
1367
1368bool RE_RenderPassIsColor(const RenderPass *render_pass)
1369{
1370 return STR_ELEM(render_pass->chan_id, "RGB", "RGBA", "R", "G", "B", "A");
1371}
1372
const char * BKE_tempdir_base() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:1211
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:837
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:2976
#define BLI_assert(a)
Definition BLI_assert.h:50
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
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addhead(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:90
#define LISTBASE_FOREACH(type, var, list)
void BLI_freelinkN(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:269
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:331
void * BLI_findlink(const struct ListBase *listbase, int number) 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.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
int BLI_findstringindex(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
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:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
BLI_INLINE int BLI_rcti_cent_y(const struct rcti *rct)
Definition BLI_rect.h:176
BLI_INLINE int BLI_rcti_cent_x(const struct rcti *rct)
Definition BLI_rect.h:172
#define STR_ELEM(...)
Definition BLI_string.h:653
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 STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
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 MAX_ID_NAME
Definition DNA_ID.h:377
#define RE_PASSNAME_COMBINED
#define STEREO_LEFT_NAME
@ R_MULTIVIEW
#define RE_PASSNAME_VECTOR
@ 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
@ R_IMF_IMTYPE_MULTILAYER
@ SCE_LAY_FLAG_DEFAULT
#define RE_PASSNAME_Z
#define STEREO_RIGHT_NAME
@ R_IMF_PLANES_RGB
@ R_IMF_PLANES_RGBA
@ R_IMF_PLANES_BW
@ SCE_PASS_COMBINED
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_RGB32F
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name)
const char * IMB_colormanagement_role_colorspace_name_get(int role)
@ COLOR_ROLE_DATA
@ COLOR_ROLE_SCENE_LINEAR
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_colormanagement_transform(float *buffer, int width, int height, int channels, const char *from_colorspace, const char *to_colorspace, bool predivide)
void imb_freerectImBuf(ImBuf *ibuf)
void IMB_free_gpu_textures(ImBuf *ibuf)
void imb_freerectfloatImBuf(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)
Definition divers.cc:838
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, ImBufOwnership ownership)
void IMB_float_from_rect(ImBuf *ibuf)
Definition divers.cc:802
Contains defines and structs used throughout the imbuf module.
@ 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)
#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.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
unsigned int U
Definition btGjkEpa3.h:78
local_group_size(16, 16) .push_constant(Type b
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
#define printf
#define offsetof(t, d)
int len
draw_view in_light_buf[] float
#define str(s)
struct ImBuf * IMB_allocImBuf(unsigned int, unsigned int, unsigned char, unsigned int)
void IMB_freeImBuf(ImBuf *)
ccl_global const KernelWorkTile * tile
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
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)
unsigned char uint8_t
Definition stdint.h:78
RenderResult * result
char name[66]
Definition DNA_ID.h:425
GPUTexture * texture
ImBufGPU gpu
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
void * last
void * first
ListBase passes
Definition RE_pipeline.h:97
char name[RE_MAXNAME]
Definition RE_pipeline.h:89
struct RenderLayer * next
Definition RE_pipeline.h:86
void * exrhandle
Definition RE_pipeline.h:95
struct RenderLayer * prev
Definition RE_pipeline.h:86
struct ImBuf * ibuf
Definition RE_pipeline.h:68
char chan_id[8]
Definition RE_pipeline.h:59
char name[64]
Definition RE_pipeline.h:58
char fullname[64]
Definition RE_pipeline.h:72
char view[64]
Definition RE_pipeline.h:73
struct RenderPass * prev
Definition RE_pipeline.h:56
struct RenderPass * next
Definition RE_pipeline.h:56
struct RenderResult * next
ListBase views
ListBase layers
struct RenderResult * prev
struct StampData * stamp_data
bool passes_allocated
struct ImBuf * ibuf
struct ImBuf * ibuf
Definition RE_pipeline.h:52
char name[64]
Definition RE_pipeline.h:47
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