Blender  V2.93
render_opengl.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) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <math.h>
25 #include <stddef.h>
26 #include <string.h>
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "BLI_bitmap.h"
31 #include "BLI_blenlib.h"
32 #include "BLI_math.h"
33 #include "BLI_math_color_blend.h"
34 #include "BLI_task.h"
35 #include "BLI_threads.h"
36 #include "BLI_utildefines.h"
37 #include "DNA_camera_types.h"
38 
39 #include "DNA_action_types.h"
40 #include "DNA_anim_types.h"
41 #include "DNA_curve_types.h"
42 #include "DNA_gpencil_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 
46 #include "BKE_anim_data.h"
47 #include "BKE_camera.h"
48 #include "BKE_context.h"
49 #include "BKE_customdata.h"
50 #include "BKE_fcurve.h"
51 #include "BKE_global.h"
52 #include "BKE_image.h"
53 #include "BKE_lib_query.h"
54 #include "BKE_main.h"
55 #include "BKE_report.h"
56 #include "BKE_scene.h"
57 #include "BKE_writeavi.h"
58 
59 #include "DEG_depsgraph.h"
60 #include "DEG_depsgraph_query.h"
61 
62 #include "DRW_engine.h"
63 
64 #include "WM_api.h"
65 #include "WM_types.h"
66 
67 #include "ED_gpencil.h"
68 #include "ED_screen.h"
69 #include "ED_view3d.h"
70 #include "ED_view3d_offscreen.h"
71 
72 #include "IMB_colormanagement.h"
73 #include "IMB_imbuf.h"
74 #include "IMB_imbuf_types.h"
75 #include "RE_pipeline.h"
76 
77 #include "RNA_access.h"
78 #include "RNA_define.h"
79 
80 #include "SEQ_render.h"
81 
82 #include "GPU_framebuffer.h"
83 #include "GPU_matrix.h"
84 
85 #include "render_intern.h"
86 
87 /* Define this to get timing information. */
88 // #define DEBUG_TIME
89 
90 #ifdef DEBUG_TIME
91 # include "PIL_time.h"
92 #endif
93 
94 /* TODO(sergey): Find better approximation of the scheduled frames.
95  * For really highres renders it might fail still. */
96 #define MAX_SCHEDULED_FRAMES 8
97 
98 typedef struct OGLRender {
105 
109 
112 
113  int views_len; /* multi-view views */
114 
117  struct {
120 
123 
125  int sizex, sizey;
127 
130  int cfrao, nfra;
131 
133 
134  /* For only rendering frames that have a key in animation data. */
136 
137  /* quick lookup */
138  int view_id;
139 
140  /* wm vars for timer and progress cursor */
143 
144  wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/
146 
148  bool pool_ok;
150 
156 
157 #ifdef DEBUG_TIME
158  double time_start;
159 #endif
161 
162 static bool screen_opengl_is_multiview(OGLRender *oglrender)
163 {
164  View3D *v3d = oglrender->v3d;
165  RegionView3D *rv3d = oglrender->rv3d;
166  RenderData *rd = &oglrender->scene->r;
167 
168  if ((rd == NULL) || ((v3d != NULL) && (rv3d == NULL))) {
169  return false;
170  }
171 
172  return (rd->scemode & R_MULTIVIEW) &&
173  ((v3d == NULL) || (rv3d->persp == RV3D_CAMOB && v3d->camera));
174 }
175 
176 static void screen_opengl_views_setup(OGLRender *oglrender)
177 {
178  RenderResult *rr;
179  RenderView *rv;
180  SceneRenderView *srv;
181  bool is_multiview;
182  Object *camera;
183  View3D *v3d = oglrender->v3d;
184 
185  RenderData *rd = &oglrender->scene->r;
186 
187  rr = RE_AcquireResultWrite(oglrender->re);
188 
189  is_multiview = screen_opengl_is_multiview(oglrender);
190 
191  if (!is_multiview) {
192  /* we only have one view when multiview is off */
193  rv = rr->views.first;
194 
195  if (rv == NULL) {
196  rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
197  BLI_addtail(&rr->views, rv);
198  }
199 
200  while (rv->next) {
201  RenderView *rv_del = rv->next;
202  BLI_remlink(&rr->views, rv_del);
203 
204  if (rv_del->rectf) {
205  MEM_freeN(rv_del->rectf);
206  }
207 
208  if (rv_del->rectz) {
209  MEM_freeN(rv_del->rectz);
210  }
211 
212  if (rv_del->rect32) {
213  MEM_freeN(rv_del->rect32);
214  }
215 
216  MEM_freeN(rv_del);
217  }
218  }
219  else {
220  if (v3d) {
221  RE_SetOverrideCamera(oglrender->re, V3D_CAMERA_SCENE(oglrender->scene, v3d));
222  }
223 
224  /* remove all the views that are not needed */
225  rv = rr->views.last;
226  while (rv) {
227  srv = BLI_findstring(&rd->views, rv->name, offsetof(SceneRenderView, name));
229  rv = rv->prev;
230  }
231  else {
232  RenderView *rv_del = rv;
233  rv = rv_del->prev;
234 
235  BLI_remlink(&rr->views, rv_del);
236 
237  if (rv_del->rectf) {
238  MEM_freeN(rv_del->rectf);
239  }
240 
241  if (rv_del->rectz) {
242  MEM_freeN(rv_del->rectz);
243  }
244 
245  if (rv_del->rect32) {
246  MEM_freeN(rv_del->rect32);
247  }
248 
249  MEM_freeN(rv_del);
250  }
251  }
252 
253  /* create all the views that are needed */
254  for (srv = rd->views.first; srv; srv = srv->next) {
255  if (BKE_scene_multiview_is_render_view_active(rd, srv) == false) {
256  continue;
257  }
258 
259  rv = BLI_findstring(&rr->views, srv->name, offsetof(SceneRenderView, name));
260 
261  if (rv == NULL) {
262  rv = MEM_callocN(sizeof(RenderView), "new opengl render view");
263  BLI_strncpy(rv->name, srv->name, sizeof(rv->name));
264  BLI_addtail(&rr->views, rv);
265  }
266  }
267  }
268 
269  if (!(is_multiview && BKE_scene_multiview_is_stereo3d(rd))) {
270  oglrender->iuser.flag &= ~IMA_SHOW_STEREO;
271  }
272 
273  /* will only work for non multiview correctly */
274  if (v3d) {
275  camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, "new opengl render view");
276  BKE_render_result_stamp_info(oglrender->scene, camera, rr, false);
277  }
278  else {
279  BKE_render_result_stamp_info(oglrender->scene, oglrender->scene->camera, rr, false);
280  }
281 
282  RE_ReleaseResult(oglrender->re);
283 }
284 
285 static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, RenderResult *rr)
286 {
288  Scene *scene = oglrender->scene;
289  ARegion *region = oglrender->region;
290  View3D *v3d = oglrender->v3d;
291  RegionView3D *rv3d = oglrender->rv3d;
292  Object *camera = NULL;
293  int sizex = oglrender->sizex;
294  int sizey = oglrender->sizey;
295  const short view_context = (v3d != NULL);
296  bool draw_sky = (scene->r.alphamode == R_ADDSKY);
297  float *rectf = NULL;
298  uchar *rect = NULL;
299  const char *viewname = RE_GetActiveRenderView(oglrender->re);
300  ImBuf *ibuf_result = NULL;
301 
302  if (oglrender->is_sequencer) {
303  SpaceSeq *sseq = oglrender->sseq;
304  struct bGPdata *gpd = (sseq && (sseq->flag & SEQ_SHOW_GPENCIL)) ? sseq->gpd : NULL;
305 
306  /* use pre-calculated ImBuf (avoids deadlock), see: */
307  ImBuf *ibuf = oglrender->seq_data.ibufs_arr[oglrender->view_id];
308 
309  if (ibuf) {
310  ImBuf *out = IMB_dupImBuf(ibuf);
311  IMB_freeImBuf(ibuf);
312  /* OpenGL render is considered to be preview and should be
313  * as fast as possible. So currently we're making sure sequencer
314  * result is always byte to simplify color management pipeline.
315  *
316  * TODO(sergey): In the case of output to float container (EXR)
317  * it actually makes sense to keep float buffer instead.
318  */
319  if (out->rect_float != NULL) {
320  IMB_rect_from_float(out);
322  }
323  BLI_assert((oglrender->sizex == ibuf->x) && (oglrender->sizey == ibuf->y));
324  RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
325  IMB_freeImBuf(out);
326  }
327  else if (gpd) {
328  /* If there are no strips, Grease Pencil still needs a buffer to draw on */
329  ImBuf *out = IMB_allocImBuf(oglrender->sizex, oglrender->sizey, 32, IB_rect);
330  RE_render_result_rect_from_ibuf(rr, &scene->r, out, oglrender->view_id);
331  IMB_freeImBuf(out);
332  }
333 
334  if (gpd) {
335  int i;
336  uchar *gp_rect;
337  uchar *render_rect = (uchar *)RE_RenderViewGetById(rr, oglrender->view_id)->rect32;
338 
340  GPU_offscreen_bind(oglrender->ofs, true);
341 
342  GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
343  GPU_clear_depth(1.0f);
344 
346  wmOrtho2(0, scene->r.xsch, 0, scene->r.ysch);
348 
350  ED_annotation_draw_ex(scene, gpd, sizex, sizey, scene->r.cfra, SPACE_SEQ);
352 
353  gp_rect = MEM_mallocN(sizeof(uchar[4]) * sizex * sizey, "offscreen rect");
354  GPU_offscreen_read_pixels(oglrender->ofs, GPU_DATA_UBYTE, gp_rect);
355 
356  for (i = 0; i < sizex * sizey * 4; i += 4) {
357  blend_color_mix_byte(&render_rect[i], &render_rect[i], &gp_rect[i]);
358  }
359  GPU_offscreen_unbind(oglrender->ofs, true);
361 
362  MEM_freeN(gp_rect);
363  }
364  }
365  else {
366  /* shouldn't suddenly give errors mid-render but possible */
367  char err_out[256] = "unknown";
368  ImBuf *ibuf_view;
369  const int alpha_mode = (draw_sky) ? R_ADDSKY : R_ALPHAPREMUL;
370  if (view_context) {
372  scene,
373  v3d->shading.type,
374  v3d,
375  region,
376  sizex,
377  sizey,
378  IB_rectfloat,
379  alpha_mode,
380  viewname,
381  true,
382  oglrender->ofs,
383  err_out);
384 
385  /* for stamp only */
386  if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
387  camera = BKE_camera_multiview_render(oglrender->scene, v3d->camera, viewname);
388  }
389  }
390  else {
392  scene,
393  NULL,
394  OB_SOLID,
395  scene->camera,
396  oglrender->sizex,
397  oglrender->sizey,
398  IB_rectfloat,
400  alpha_mode,
401  viewname,
402  oglrender->ofs,
403  err_out);
404  camera = scene->camera;
405  }
406 
407  if (ibuf_view) {
408  ibuf_result = ibuf_view;
409  if (ibuf_view->rect_float) {
410  rectf = ibuf_view->rect_float;
411  }
412  else {
413  rect = (uchar *)ibuf_view->rect;
414  }
415  }
416  else {
417  fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
418  }
419  }
420 
421  if (ibuf_result != NULL) {
422  if ((scene->r.stamp & R_STAMP_ALL) && (scene->r.stamp & R_STAMP_DRAW)) {
423  BKE_image_stamp_buf(scene, camera, NULL, rect, rectf, rr->rectx, rr->recty, 4);
424  }
425  RE_render_result_rect_from_ibuf(rr, &scene->r, ibuf_result, oglrender->view_id);
426  IMB_freeImBuf(ibuf_result);
427  }
428 }
429 
430 static void screen_opengl_render_write(OGLRender *oglrender)
431 {
432  Scene *scene = oglrender->scene;
433  RenderResult *rr;
434  bool ok;
435  char name[FILE_MAX];
436 
437  rr = RE_AcquireResultRead(oglrender->re);
438 
440  scene->r.pic,
441  BKE_main_blendfile_path(oglrender->bmain),
442  scene->r.cfra,
443  &scene->r.im_format,
444  (scene->r.scemode & R_EXTENSION) != 0,
445  false,
446  NULL);
447 
448  /* write images as individual images or stereo */
450  ok = RE_WriteRenderViewsImage(oglrender->reports, rr, scene, false, name);
451 
452  RE_ReleaseResultImage(oglrender->re);
453 
454  if (ok) {
455  printf("OpenGL Render written to '%s'\n", name);
456  }
457  else {
458  printf("OpenGL Render failed to write '%s'\n", name);
459  }
460 }
461 
462 static void UNUSED_FUNCTION(addAlphaOverFloat)(float dest[4], const float source[4])
463 {
464  /* d = s + (1-alpha_s)d*/
465  float mul;
466 
467  mul = 1.0f - source[3];
468 
469  dest[0] = (mul * dest[0]) + source[0];
470  dest[1] = (mul * dest[1]) + source[1];
471  dest[2] = (mul * dest[2]) + source[2];
472  dest[3] = (mul * dest[3]) + source[3];
473 }
474 
475 static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
476 {
477  RenderResult *rr;
478  RenderView *rv;
479  int view_id;
480  ImBuf *ibuf;
481  void *lock;
482 
483  if (oglrender->is_sequencer) {
484  Scene *scene = oglrender->scene;
485 
487  SpaceSeq *sseq = oglrender->sseq;
488  int chanshown = sseq ? sseq->chanshown : 0;
489 
491  oglrender->depsgraph,
492  scene,
493  oglrender->sizex,
494  oglrender->sizey,
496  false,
497  &context);
498 
499  for (view_id = 0; view_id < oglrender->views_len; view_id++) {
500  context.view_id = view_id;
501  context.gpu_offscreen = oglrender->ofs;
502  oglrender->seq_data.ibufs_arr[view_id] = SEQ_render_give_ibuf(&context, CFRA, chanshown);
503  }
504  }
505 
506  rr = RE_AcquireResultRead(oglrender->re);
507  for (rv = rr->views.first, view_id = 0; rv; rv = rv->next, view_id++) {
508  BLI_assert(view_id < oglrender->views_len);
509  RE_SetActiveRenderView(oglrender->re, rv->name);
510  oglrender->view_id = view_id;
511  /* render composite */
512  screen_opengl_render_doit(C, oglrender, rr);
513  }
514 
515  RE_ReleaseResult(oglrender->re);
516 
517  ibuf = BKE_image_acquire_ibuf(oglrender->ima, &oglrender->iuser, &lock);
518  if (ibuf) {
520  }
521  BKE_image_release_ibuf(oglrender->ima, ibuf, lock);
522  oglrender->ima->gpuflag |= IMA_GPU_REFRESH;
523 
524  if (oglrender->write_still) {
525  screen_opengl_render_write(oglrender);
526  }
527 }
528 
529 static void gather_frames_to_render_for_adt(const OGLRender *oglrender, const AnimData *adt)
530 {
531  if (adt == NULL || adt->action == NULL) {
532  return;
533  }
534 
535  Scene *scene = oglrender->scene;
536  int frame_start = PSFRA;
537  int frame_end = PEFRA;
538 
539  LISTBASE_FOREACH (FCurve *, fcu, &adt->action->curves) {
540  if (fcu->driver != NULL || fcu->fpt != NULL) {
541  /* Drivers have values for any point in time, so to get "the keyed frames" they are
542  * useless. Same for baked FCurves, they also have keys for every frame, which is not
543  * useful for rendering the keyed subset of the frames. */
544  continue;
545  }
546 
547  bool found = false; /* Not interesting, we just want a starting point for the for-loop.*/
548  int key_index = BKE_fcurve_bezt_binarysearch_index(
549  fcu->bezt, frame_start, fcu->totvert, &found);
550  for (; key_index < fcu->totvert; key_index++) {
551  BezTriple *bezt = &fcu->bezt[key_index];
552  /* The frame range to render uses integer frame numbers, and the frame
553  * step is also an integer, so we always render on the frame. */
554  int frame_nr = round_fl_to_int(bezt->vec[1][0]);
555 
556  /* (frame_nr < frame_start) cannot happen because of the binary search above. */
557  BLI_assert(frame_nr >= frame_start);
558  if (frame_nr > frame_end) {
559  break;
560  }
561  BLI_BITMAP_ENABLE(oglrender->render_frames, frame_nr - frame_start);
562  }
563  }
564 }
565 
567  const bGPdata *gp)
568 {
569  if (gp == NULL) {
570  return;
571  }
572 
573  Scene *scene = oglrender->scene;
574  int frame_start = PSFRA;
575  int frame_end = PEFRA;
576 
577  LISTBASE_FOREACH (const bGPDlayer *, gp_layer, &gp->layers) {
578  LISTBASE_FOREACH (const bGPDframe *, gp_frame, &gp_layer->frames) {
579  if (gp_frame->framenum < frame_start || gp_frame->framenum > frame_end) {
580  continue;
581  }
582  BLI_BITMAP_ENABLE(oglrender->render_frames, gp_frame->framenum - frame_start);
583  }
584  }
585 }
586 
588 {
589  ID **id_p = cb_data->id_pointer;
590  if (*id_p == NULL) {
591  return IDWALK_RET_NOP;
592  }
593  ID *id = *id_p;
594 
595  ID *id_self = cb_data->id_self;
596  const int cb_flag = cb_data->cb_flag;
597  if (cb_flag == IDWALK_CB_LOOPBACK || id == id_self) {
598  /* IDs may end up referencing themselves one way or the other, and those
599  * (the id_self ones) have always already been processed. */
601  }
602 
603  OGLRender *oglrender = cb_data->user_data;
604 
605  /* Whitelist of datablocks to follow pointers into. */
606  const ID_Type id_type = GS(id->name);
607  switch (id_type) {
608  /* Whitelist: */
609  case ID_ME: /* Mesh */
610  case ID_CU: /* Curve */
611  case ID_MB: /* MetaBall */
612  case ID_MA: /* Material */
613  case ID_TE: /* Tex (Texture) */
614  case ID_IM: /* Image */
615  case ID_LT: /* Lattice */
616  case ID_LA: /* Light */
617  case ID_CA: /* Camera */
618  case ID_KE: /* Key (shape key) */
619  case ID_VF: /* VFont (Vector Font) */
620  case ID_TXT: /* Text */
621  case ID_SPK: /* Speaker */
622  case ID_SO: /* Sound */
623  case ID_AR: /* bArmature */
624  case ID_NT: /* bNodeTree */
625  case ID_PA: /* ParticleSettings */
626  case ID_MC: /* MovieClip */
627  case ID_MSK: /* Mask */
628  case ID_LP: /* LightProbe */
629  case ID_HA: /* Hair */
630  case ID_PT: /* PointCloud */
631  case ID_VO: /* Volume */
632  case ID_SIM: /* Simulation */
633  break;
634 
635  /* Blacklist: */
636  case ID_SCE: /* Scene */
637  case ID_LI: /* Library */
638  case ID_OB: /* Object */
639  case ID_IP: /* Ipo (depreciated, replaced by FCurves) */
640  case ID_WO: /* World */
641  case ID_SCR: /* Screen */
642  case ID_GR: /* Group */
643  case ID_AC: /* bAction */
644  case ID_BR: /* Brush */
645  case ID_WM: /* WindowManager */
646  case ID_LS: /* FreestyleLineStyle */
647  case ID_PAL: /* Palette */
648  case ID_PC: /* PaintCurve */
649  case ID_CF: /* CacheFile */
650  case ID_WS: /* WorkSpace */
651  /* Only follow pointers to specific datablocks, to avoid ending up in
652  * unrelated datablocks and exploding the number of blocks we follow. If the
653  * frames of the animation of certain objects should be taken into account,
654  * they should have been selected by the user. */
656 
657  /* Special cases: */
658  case ID_GD: /* bGPdata, (Grease Pencil) */
659  /* In addition to regular ID's animdata, GreasePencil uses a specific frame-based animation
660  * system that requires specific handling here. */
662  break;
663  }
664 
667 
668  return IDWALK_RET_NOP;
669 }
670 
678 static void gather_frames_to_render(bContext *C, OGLRender *oglrender)
679 {
680  Scene *scene = oglrender->scene;
681  int frame_start = PSFRA;
682  int frame_end = PEFRA;
683 
684  /* Will be freed in screen_opengl_render_end(). */
685  oglrender->render_frames = BLI_BITMAP_NEW(frame_end - frame_start + 1,
686  "OGLRender::render_frames");
687 
688  /* The first frame should always be rendered, otherwise there is nothing to write to file. */
689  BLI_BITMAP_ENABLE(oglrender->render_frames, 0);
690 
691  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
692  ID *id = &ob->id;
693 
694  /* Gather the frames from the object animation data. */
697 
698  /* Gather the frames from linked datablocks (materials, shapkeys, etc.). */
701  }
702  CTX_DATA_END;
703 }
704 
706 {
707  /* new render clears all callbacks */
709  wmWindow *win = CTX_wm_window(C);
710  WorkSpace *workspace = CTX_wm_workspace(C);
711 
713  ScrArea *prevsa = CTX_wm_area(C);
714  ARegion *prevar = CTX_wm_region(C);
715  GPUOffScreen *ofs;
716  OGLRender *oglrender;
717  int sizex, sizey;
718  bool is_view_context = RNA_boolean_get(op->ptr, "view_context");
719  const bool is_animation = RNA_boolean_get(op->ptr, "animation");
720  const bool is_render_keyed_only = RNA_boolean_get(op->ptr, "render_keyed_only");
721  const bool is_sequencer = RNA_boolean_get(op->ptr, "sequencer");
722  const bool is_write_still = RNA_boolean_get(op->ptr, "write_still");
723  const eImageFormatDepth color_depth = (is_animation) ? scene->r.im_format.depth :
725  char err_out[256] = "unknown";
726 
727  if (G.background) {
728  BKE_report(
729  op->reports, RPT_ERROR, "Cannot use OpenGL render in background mode (no opengl context)");
730  return false;
731  }
732 
733  /* only one render job at a time */
735  return false;
736  }
737 
738  if (is_sequencer) {
739  is_view_context = false;
740  }
741  else {
742  /* ensure we have a 3d view */
744  RNA_boolean_set(op->ptr, "view_context", false);
745  is_view_context = false;
746  }
747 
748  if (!is_view_context && scene->camera == NULL) {
749  BKE_report(op->reports, RPT_ERROR, "Scene has no camera");
750  return false;
751  }
752  }
753 
754  if (!is_animation && is_write_still && BKE_imtype_is_movie(scene->r.im_format.imtype)) {
755  BKE_report(
756  op->reports, RPT_ERROR, "Cannot write a single file with an animation format selected");
757  return false;
758  }
759 
760  /* stop all running jobs, except screen one. currently previews frustrate Render */
762 
763  /* create offscreen buffer */
764  sizex = (scene->r.size * scene->r.xsch) / 100;
765  sizey = (scene->r.size * scene->r.ysch) / 100;
766 
767  /* corrects render size with actual size, not every card supports non-power-of-two dimensions */
768  DRW_opengl_context_enable(); /* Offscreen creation needs to be done in DRW context. */
769  ofs = GPU_offscreen_create(sizex, sizey, true, true, err_out);
771 
772  if (!ofs) {
773  BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer, %s", err_out);
774  return false;
775  }
776 
777  /* allocate opengl render */
778  oglrender = MEM_callocN(sizeof(OGLRender), "OGLRender");
779  op->customdata = oglrender;
780 
781  oglrender->ofs = ofs;
782  oglrender->sizex = sizex;
783  oglrender->sizey = sizey;
784  oglrender->bmain = CTX_data_main(C);
785  oglrender->scene = scene;
786  oglrender->workspace = workspace;
787  oglrender->view_layer = CTX_data_view_layer(C);
788  /* NOTE: The depsgraph is not only used to update scene for a new frames, but also to initialize
789  * output video handles, which does need evaluated scene. */
791  oglrender->cfrao = scene->r.cfra;
792 
793  oglrender->write_still = is_write_still && !is_animation;
794  oglrender->is_animation = is_animation;
795  oglrender->color_depth = color_depth;
796 
798 
799  oglrender->is_sequencer = is_sequencer;
800  if (is_sequencer) {
801  oglrender->sseq = CTX_wm_space_seq(C);
802  ImBuf **ibufs_arr = MEM_callocN(sizeof(*ibufs_arr) * oglrender->views_len, __func__);
803  oglrender->seq_data.ibufs_arr = ibufs_arr;
804  }
805 
806  oglrender->prevsa = prevsa;
807  oglrender->prevar = prevar;
808 
809  if (is_view_context) {
810  /* so quad view renders camera */
811  ED_view3d_context_user_region(C, &oglrender->v3d, &oglrender->region);
812 
813  oglrender->rv3d = oglrender->region->regiondata;
814 
815  /* MUST be cleared on exit */
816  memset(&oglrender->scene->customdata_mask_modal,
817  0,
818  sizeof(oglrender->scene->customdata_mask_modal));
820  C, oglrender->scene, oglrender->v3d, &oglrender->scene->customdata_mask_modal);
821 
822  /* apply immediately in case we're rendering from a script,
823  * running notifiers again will overwrite */
825  &oglrender->scene->customdata_mask_modal);
826  }
827 
828  /* create render */
829  oglrender->re = RE_NewSceneRender(scene);
830 
831  /* create image and image user */
832  oglrender->ima = BKE_image_ensure_viewer(oglrender->bmain, IMA_TYPE_R_RESULT, "Render Result");
833  BKE_image_signal(oglrender->bmain, oglrender->ima, NULL, IMA_SIGNAL_FREE);
834  BKE_image_backup_render(oglrender->scene, oglrender->ima, true);
835 
836  oglrender->iuser.scene = scene;
837  oglrender->iuser.ok = 1;
838 
839  /* create render result */
840  RE_InitState(oglrender->re, NULL, &scene->r, &scene->view_layers, NULL, sizex, sizey, NULL);
841 
842  /* create render views */
843  screen_opengl_views_setup(oglrender);
844 
845  /* wm vars */
846  oglrender->wm = wm;
847  oglrender->win = win;
848 
849  oglrender->totvideos = 0;
850  oglrender->mh = NULL;
851  oglrender->movie_ctx_arr = NULL;
852 
853  if (is_animation) {
854  if (is_render_keyed_only) {
855  gather_frames_to_render(C, oglrender);
856  }
857 
860  }
861  else {
862  oglrender->task_pool = BLI_task_pool_create(oglrender, TASK_PRIORITY_LOW);
863  }
864  oglrender->pool_ok = true;
865  BLI_spin_init(&oglrender->reports_lock);
866  }
867  else {
868  oglrender->task_pool = NULL;
869  }
870  oglrender->num_scheduled_frames = 0;
871  BLI_mutex_init(&oglrender->task_mutex);
872  BLI_condition_init(&oglrender->task_condition);
873 
874 #ifdef DEBUG_TIME
875  oglrender->time_start = PIL_check_seconds_timer();
876 #endif
877 
878  return true;
879 }
880 
881 static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
882 {
883  Scene *scene = oglrender->scene;
884  int i;
885 
886  if (oglrender->is_animation) {
887  /* Trickery part for movie output:
888  *
889  * We MUST write frames in an exact order, so we only let background
890  * thread to work on that, and main thread is simply waits for that
891  * thread to do all the dirty work.
892  *
893  * After this loop is done work_and_wait() will have nothing to do,
894  * so we don't run into wrong order of frames written to the stream.
895  */
897  BLI_mutex_lock(&oglrender->task_mutex);
898  while (oglrender->num_scheduled_frames > 0) {
899  BLI_condition_wait(&oglrender->task_condition, &oglrender->task_mutex);
900  }
901  BLI_mutex_unlock(&oglrender->task_mutex);
902  }
904  BLI_task_pool_free(oglrender->task_pool);
905  BLI_spin_end(&oglrender->reports_lock);
906  }
907  BLI_mutex_end(&oglrender->task_mutex);
908  BLI_condition_end(&oglrender->task_condition);
909 
910 #ifdef DEBUG_TIME
911  printf("Total render time: %f\n", PIL_check_seconds_timer() - oglrender->time_start);
912 #endif
913 
914  MEM_SAFE_FREE(oglrender->render_frames);
915 
916  if (oglrender->mh) {
918  for (i = 0; i < oglrender->totvideos; i++) {
919  oglrender->mh->end_movie(oglrender->movie_ctx_arr[i]);
920  oglrender->mh->context_free(oglrender->movie_ctx_arr[i]);
921  }
922  }
923 
924  if (oglrender->movie_ctx_arr) {
925  MEM_freeN(oglrender->movie_ctx_arr);
926  }
927  }
928 
929  if (oglrender->timer) { /* exec will not have a timer */
930  Depsgraph *depsgraph = oglrender->depsgraph;
931  scene->r.cfra = oglrender->cfrao;
933 
934  WM_event_remove_timer(oglrender->wm, oglrender->win, oglrender->timer);
935  }
936 
937  WM_cursor_modal_restore(oglrender->win);
938 
940 
942  GPU_offscreen_free(oglrender->ofs);
944 
945  if (oglrender->is_sequencer) {
946  MEM_freeN(oglrender->seq_data.ibufs_arr);
947  }
948 
949  memset(&oglrender->scene->customdata_mask_modal,
950  0,
951  sizeof(oglrender->scene->customdata_mask_modal));
952 
953  CTX_wm_area_set(C, oglrender->prevsa);
954  CTX_wm_region_set(C, oglrender->prevar);
955 
956  MEM_freeN(oglrender);
957 }
958 
960 {
962 }
963 
964 /* share between invoke and exec */
966 {
967  /* initialize animation */
968  OGLRender *oglrender;
969  Scene *scene;
970 
971  oglrender = op->customdata;
972  scene = oglrender->scene;
974 
975  oglrender->reports = op->reports;
976 
978  size_t width, height;
979  int i;
980 
982  &scene->r, oglrender->sizex, oglrender->sizey, &width, &height);
984 
985  if (oglrender->mh == NULL) {
986  BKE_report(oglrender->reports, RPT_ERROR, "Movie format unsupported");
987  screen_opengl_render_end(C, oglrender);
988  return false;
989  }
990 
991  oglrender->movie_ctx_arr = MEM_mallocN(sizeof(void *) * oglrender->totvideos, "Movies");
992 
993  for (i = 0; i < oglrender->totvideos; i++) {
994  Scene *scene_eval = DEG_get_evaluated_scene(oglrender->depsgraph);
995  const char *suffix = BKE_scene_multiview_view_id_suffix_get(&scene->r, i);
996 
997  oglrender->movie_ctx_arr[i] = oglrender->mh->context_create();
998  if (!oglrender->mh->start_movie(oglrender->movie_ctx_arr[i],
999  scene_eval,
1000  &scene->r,
1001  oglrender->sizex,
1002  oglrender->sizey,
1003  oglrender->reports,
1004  PRVRANGEON != 0,
1005  suffix)) {
1006  screen_opengl_render_end(C, oglrender);
1007  return false;
1008  }
1009  }
1010  }
1011 
1012  oglrender->cfrao = scene->r.cfra;
1013  oglrender->nfra = PSFRA;
1014  scene->r.cfra = PSFRA;
1015 
1016  return true;
1017 }
1018 
1019 typedef struct WriteTaskData {
1023 
1024 static void write_result_func(TaskPool *__restrict pool, void *task_data_v)
1025 {
1027  WriteTaskData *task_data = (WriteTaskData *)task_data_v;
1028  Scene *scene = &task_data->tmp_scene;
1029  RenderResult *rr = task_data->rr;
1030  const bool is_movie = BKE_imtype_is_movie(scene->r.im_format.imtype);
1031  const int cfra = scene->r.cfra;
1032  bool ok;
1033  /* Don't attempt to write if we've got an error. */
1034  if (!oglrender->pool_ok) {
1035  RE_FreeRenderResult(rr);
1036  BLI_mutex_lock(&oglrender->task_mutex);
1037  oglrender->num_scheduled_frames--;
1039  BLI_mutex_unlock(&oglrender->task_mutex);
1040  return;
1041  }
1042  /* Construct local thread0safe copy of reports structure which we can
1043  * safely pass to the underlying functions.
1044  */
1045  ReportList reports;
1046  BKE_reports_init(&reports, oglrender->reports->flag & ~RPT_PRINT);
1047  /* Do actual save logic here, depending on the file format.
1048  *
1049  * NOTE: We have to construct temporary scene with proper scene->r.cfra.
1050  * This is because underlying calls do not use r.cfra but use scene
1051  * for that.
1052  */
1053  if (is_movie) {
1054  ok = RE_WriteRenderViewsMovie(&reports,
1055  rr,
1056  scene,
1057  &scene->r,
1058  oglrender->mh,
1059  oglrender->movie_ctx_arr,
1060  oglrender->totvideos,
1061  PRVRANGEON != 0);
1062  }
1063  else {
1064  /* TODO(sergey): We can in theory save some CPU ticks here because we
1065  * calculate file name again here.
1066  */
1067  char name[FILE_MAX];
1069  scene->r.pic,
1070  BKE_main_blendfile_path(oglrender->bmain),
1071  cfra,
1072  &scene->r.im_format,
1073  (scene->r.scemode & R_EXTENSION) != 0,
1074  true,
1075  NULL);
1076 
1078  ok = RE_WriteRenderViewsImage(NULL, rr, scene, true, name);
1079  if (!ok) {
1080  BKE_reportf(&reports, RPT_ERROR, "Write error: cannot save %s", name);
1081  }
1082  }
1083  if (reports.list.first != NULL) {
1084  BLI_spin_lock(&oglrender->reports_lock);
1085  for (Report *report = reports.list.first; report != NULL; report = report->next) {
1086  BKE_report(oglrender->reports, report->type, report->message);
1087  }
1088  BLI_spin_unlock(&oglrender->reports_lock);
1089  }
1090  if (!ok) {
1091  oglrender->pool_ok = false;
1092  }
1093  RE_FreeRenderResult(rr);
1094  BLI_mutex_lock(&oglrender->task_mutex);
1095  oglrender->num_scheduled_frames--;
1097  BLI_mutex_unlock(&oglrender->task_mutex);
1098 }
1099 
1100 static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
1101 {
1102  if (!oglrender->pool_ok) {
1103  RE_FreeRenderResult(rr);
1104  return false;
1105  }
1106  Scene *scene = oglrender->scene;
1107  WriteTaskData *task_data = MEM_mallocN(sizeof(WriteTaskData), "write task data");
1108  task_data->rr = rr;
1109  task_data->tmp_scene = *scene;
1110  BLI_mutex_lock(&oglrender->task_mutex);
1111  oglrender->num_scheduled_frames++;
1112  if (oglrender->num_scheduled_frames > MAX_SCHEDULED_FRAMES) {
1113  BLI_condition_wait(&oglrender->task_condition, &oglrender->task_mutex);
1114  }
1115  BLI_mutex_unlock(&oglrender->task_mutex);
1116  BLI_task_pool_push(oglrender->task_pool, write_result_func, task_data, true, NULL);
1117  return true;
1118 }
1119 
1121 {
1122  OGLRender *oglrender = op->customdata;
1123  Scene *scene = oglrender->scene;
1124  Depsgraph *depsgraph = oglrender->depsgraph;
1125  char name[FILE_MAX];
1126  bool ok = false;
1127  const bool view_context = (oglrender->v3d != NULL);
1128  bool is_movie;
1129  RenderResult *rr;
1130 
1131  /* go to next frame */
1132  if (CFRA < oglrender->nfra) {
1133  CFRA++;
1134  }
1135  while (CFRA < oglrender->nfra) {
1137  CFRA++;
1138  }
1139 
1141 
1142  if (!is_movie) {
1144  scene->r.pic,
1145  BKE_main_blendfile_path(oglrender->bmain),
1146  scene->r.cfra,
1147  &scene->r.im_format,
1148  (scene->r.scemode & R_EXTENSION) != 0,
1149  true,
1150  NULL);
1151 
1152  if ((scene->r.mode & R_NO_OVERWRITE) && BLI_exists(name)) {
1153  BLI_spin_lock(&oglrender->reports_lock);
1154  BKE_reportf(op->reports, RPT_INFO, "Skipping existing frame \"%s\"", name);
1155  BLI_spin_unlock(&oglrender->reports_lock);
1156  ok = true;
1157  goto finally;
1158  }
1159  }
1160 
1161  WM_cursor_time(oglrender->win, scene->r.cfra);
1162 
1164 
1165  if (view_context) {
1166  if (oglrender->rv3d->persp == RV3D_CAMOB && oglrender->v3d->camera &&
1167  oglrender->v3d->scenelock) {
1168  /* since BKE_scene_graph_update_for_newframe() is used rather
1169  * then ED_update_for_newframe() the camera needs to be set */
1171  oglrender->v3d->camera = scene->camera;
1172  }
1173  }
1174  }
1175  else {
1177  }
1178 
1179  if (oglrender->render_frames == NULL ||
1180  BLI_BITMAP_TEST_BOOL(oglrender->render_frames, CFRA - PSFRA)) {
1181  /* render into offscreen buffer */
1182  screen_opengl_render_apply(C, oglrender);
1183  }
1184 
1185  /* save to disk */
1186  rr = RE_AcquireResultRead(oglrender->re);
1187  RenderResult *new_rr = RE_DuplicateRenderResult(rr);
1188  RE_ReleaseResult(oglrender->re);
1189 
1190  ok = schedule_write_result(oglrender, new_rr);
1191 
1192 finally: /* Step the frame and bail early if needed */
1193 
1194  /* go to next frame */
1195  oglrender->nfra += scene->r.frame_step;
1196 
1197  /* stop at the end or on error */
1198  if (CFRA >= PEFRA || !ok) {
1200  return 0;
1201  }
1202 
1203  return 1;
1204 }
1205 
1206 static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
1207 {
1208  OGLRender *oglrender = op->customdata;
1209  const bool anim = RNA_boolean_get(op->ptr, "animation");
1210  bool ret;
1211 
1212  switch (event->type) {
1213  case EVT_ESCKEY:
1214  /* cancel */
1215  oglrender->pool_ok = false; /* Flag pool for cancel. */
1217  return OPERATOR_FINISHED;
1218  case TIMER:
1219  /* render frame? */
1220  if (oglrender->timer == event->customdata) {
1221  break;
1222  }
1224  default:
1225  /* nothing to do */
1226  return OPERATOR_RUNNING_MODAL;
1227  }
1228 
1229  /* run first because screen_opengl_render_anim_step can free oglrender */
1231 
1232  if (anim == 0) {
1235  return OPERATOR_FINISHED;
1236  }
1237 
1239 
1240  /* stop at the end or on error */
1241  if (ret == false) {
1242  return OPERATOR_FINISHED;
1243  }
1244 
1245  return OPERATOR_RUNNING_MODAL;
1246 }
1247 
1249 {
1250  OGLRender *oglrender;
1251  const bool anim = RNA_boolean_get(op->ptr, "animation");
1252 
1253  if (!screen_opengl_render_init(C, op)) {
1254  return OPERATOR_CANCELLED;
1255  }
1256 
1257  if (anim) {
1258  if (!screen_opengl_render_anim_init(C, op)) {
1259  return OPERATOR_CANCELLED;
1260  }
1261  }
1262 
1263  oglrender = op->customdata;
1264  render_view_open(C, event->x, event->y, op->reports);
1265 
1266  /* View may be changed above #USER_RENDER_DISPLAY_WINDOW. */
1267  oglrender->win = CTX_wm_window(C);
1268 
1270  oglrender->timer = WM_event_add_timer(oglrender->wm, oglrender->win, TIMER, 0.01f);
1271 
1272  return OPERATOR_RUNNING_MODAL;
1273 }
1274 
1275 /* executes blocking render */
1277 {
1278  const bool is_animation = RNA_boolean_get(op->ptr, "animation");
1279 
1280  if (!screen_opengl_render_init(C, op)) {
1281  return OPERATOR_CANCELLED;
1282  }
1283 
1284  if (!is_animation) { /* same as invoke */
1285  /* render image */
1288 
1289  return OPERATOR_FINISHED;
1290  }
1291 
1292  bool ret = true;
1293 
1294  if (!screen_opengl_render_anim_init(C, op)) {
1295  return OPERATOR_CANCELLED;
1296  }
1297 
1298  while (ret) {
1300  }
1301 
1302  /* no redraw needed, we leave state as we entered it */
1303  // ED_update_for_newframe(C);
1305 
1306  return OPERATOR_FINISHED;
1307 }
1308 
1310  struct wmOperatorType *UNUSED(ot),
1311  struct PointerRNA *ptr)
1312 {
1313  if (!RNA_boolean_get(ptr, "animation")) {
1314  return NULL;
1315  }
1316 
1317  if (RNA_boolean_get(ptr, "render_keyed_only")) {
1318  return BLI_strdup(
1319  "Render the viewport for the animation range of this scene, but only render keyframes of "
1320  "selected objects");
1321  }
1322 
1323  return BLI_strdup("Render the viewport for the animation range of this scene");
1324 }
1325 
1327 {
1328  PropertyRNA *prop;
1329 
1330  /* identifiers */
1331  ot->name = "Viewport Render";
1332  ot->description = "Take a snapshot of the active viewport";
1333  ot->idname = "RENDER_OT_opengl";
1334 
1335  /* api callbacks */
1338  ot->exec = screen_opengl_render_exec; /* blocking */
1341 
1343 
1344  prop = RNA_def_boolean(ot->srna,
1345  "animation",
1346  0,
1347  "Animation",
1348  "Render files from the animation range of this scene");
1350 
1351  prop = RNA_def_boolean(ot->srna,
1352  "render_keyed_only",
1353  0,
1354  "Render Keyframes Only",
1355  "Render only those frames where selected objects have a key in their "
1356  "animation data. Only used when rendering animation");
1358 
1359  prop = RNA_def_boolean(
1360  ot->srna, "sequencer", 0, "Sequencer", "Render using the sequencer's OpenGL display");
1362  prop = RNA_def_boolean(
1363  ot->srna,
1364  "write_still",
1365  0,
1366  "Write Image",
1367  "Save rendered the image to the output path (used only when animation is disabled)");
1369  prop = RNA_def_boolean(ot->srna,
1370  "view_context",
1371  1,
1372  "View Context",
1373  "Use the current 3D view for rendering, else use scene settings");
1375 }
struct AnimData * BKE_animdata_from_id(struct ID *id)
Definition: anim_data.c:96
Camera data-block and utility functions.
struct Object * BKE_camera_multiview_render(const struct Scene *scene, struct Object *camera, const char *viewname)
struct WorkSpace * CTX_wm_workspace(const bContext *C)
Definition: context.c:704
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
void CTX_wm_region_set(bContext *C, struct ARegion *region)
Definition: context.c:985
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct SpaceSeq * CTX_wm_space_seq(const bContext *C)
Definition: context.c:827
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:709
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
void CTX_wm_area_set(bContext *C, struct ScrArea *area)
Definition: context.c:973
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
#define CTX_DATA_END
Definition: BKE_context.h:260
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
CustomData interface, see also DNA_customdata_types.h.
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst, const CustomData_MeshMasks *mask_src)
Definition: customdata.c:76
int BKE_fcurve_bezt_binarysearch_index(struct BezTriple array[], float frame, int arraylen, bool *r_replace)
Definition: fcurve.c:600
@ G_FLAG_RENDER_VIEWPORT
Definition: BKE_global.h:110
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
Definition: image.c:5113
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
Definition: image.c:5100
void BKE_image_backup_render(struct Scene *scene, struct Image *ima, bool free_current_slot)
Definition: image.c:3971
void BKE_image_path_from_imformat(char *string, const char *base, const char *relbase, int frame, const struct ImageFormatData *im_format, const bool use_ext, const bool use_frames, const char *suffix)
struct Image * BKE_image_ensure_viewer(struct Main *bmain, int type, const char *name)
Definition: image.c:3162
#define IMA_SIGNAL_FREE
Definition: BKE_image.h:163
bool BKE_imtype_is_movie(const char imtype)
Definition: image.c:1443
void BKE_image_signal(struct Main *bmain, struct Image *ima, struct ImageUser *iuser, int signal)
Definition: image.c:3499
void BKE_render_result_stamp_info(struct Scene *scene, struct Object *camera, struct RenderResult *rr, bool allocate_only)
Definition: image.c:2611
void BKE_image_stamp_buf(struct Scene *scene, struct Object *camera, const struct StampData *stamp_data_template, unsigned char *rect, float *rectf, int width, int height, int channels)
@ IDWALK_RECURSE
void BKE_library_foreach_ID_link(struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
Definition: lib_query.c:322
@ IDWALK_RET_STOP_RECURSION
@ IDWALK_RET_NOP
Definition: BKE_lib_query.h:97
@ IDWALK_CB_LOOPBACK
Definition: BKE_lib_query.h:68
const char * BKE_main_blendfile_path(const struct Main *bmain) ATTR_NONNULL()
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_reportf(ReportList *reports, ReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_reports_init(ReportList *reports, int flag)
Definition: report.c:66
bool BKE_scene_multiview_is_stereo3d(const struct RenderData *rd)
const char * BKE_scene_multiview_view_id_suffix_get(const struct RenderData *rd, const int view_id)
int BKE_scene_multiview_num_videos_get(const struct RenderData *rd)
bool BKE_scene_multiview_is_render_view_active(const struct RenderData *rd, const struct SceneRenderView *srv)
bool BKE_scene_camera_switch_update(struct Scene *scene)
Definition: scene.c:2349
void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph)
Definition: scene.c:2794
int BKE_scene_multiview_num_views_get(const struct RenderData *rd)
void BKE_scene_multiview_videos_dimensions_get(const struct RenderData *rd, const size_t width, const size_t height, size_t *r_width, size_t *r_height)
bMovieHandle * BKE_movie_handle_get(const char imtype)
Definition: writeavi.c:114
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
Definition: BLI_bitmap.h:73
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
#define ATTR_FALLTHROUGH
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition: storage.c:349
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
void * BLI_findstring(const struct ListBase *listbase, const char *id, const int offset) ATTR_WARN_UNUSED_RESULT 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
MINLINE int round_fl_to_int(float a)
MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
#define FILE_MAX
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:70
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
unsigned char uchar
Definition: BLI_sys_types.h:86
unsigned int uint
Definition: BLI_sys_types.h:83
void * BLI_task_pool_user_data(TaskPool *pool)
Definition: task_pool.cc:541
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition: task_pool.cc:496
TaskPool * BLI_task_pool_create_background_serial(void *userdata, TaskPriority priority)
Definition: task_pool.cc:451
TaskPool * BLI_task_pool_create(void *userdata, TaskPriority priority)
Definition: task_pool.cc:406
void BLI_task_pool_free(TaskPool *pool)
Definition: task_pool.cc:456
@ TASK_PRIORITY_LOW
Definition: BLI_task.h:66
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition: task_pool.cc:475
void BLI_condition_notify_all(ThreadCondition *cond)
Definition: threads.cc:622
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:111
void BLI_mutex_end(ThreadMutex *mutex)
Definition: threads.cc:416
void BLI_condition_wait(ThreadCondition *cond, ThreadMutex *mutex)
Definition: threads.cc:607
void BLI_mutex_init(ThreadMutex *mutex)
Definition: threads.cc:396
pthread_cond_t ThreadCondition
Definition: BLI_threads.h:151
void BLI_condition_end(ThreadCondition *cond)
Definition: threads.cc:627
void BLI_condition_init(ThreadCondition *cond)
Definition: threads.cc:602
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:401
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:406
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:447
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:480
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:461
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:83
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:495
#define UNUSED_FUNCTION(x)
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
ID_Type
Definition: DNA_ID_enums.h:56
@ ID_WM
Definition: DNA_ID_enums.h:84
@ ID_CA
Definition: DNA_ID_enums.h:68
@ ID_AR
Definition: DNA_ID_enums.h:78
@ ID_MC
Definition: DNA_ID_enums.h:85
@ ID_CF
Definition: DNA_ID_enums.h:90
@ ID_LI
Definition: DNA_ID_enums.h:58
@ ID_TE
Definition: DNA_ID_enums.h:64
@ ID_IM
Definition: DNA_ID_enums.h:65
@ ID_VO
Definition: DNA_ID_enums.h:95
@ ID_WS
Definition: DNA_ID_enums.h:91
@ ID_NT
Definition: DNA_ID_enums.h:80
@ ID_LA
Definition: DNA_ID_enums.h:67
@ ID_KE
Definition: DNA_ID_enums.h:70
@ ID_TXT
Definition: DNA_ID_enums.h:74
@ ID_SO
Definition: DNA_ID_enums.h:76
@ ID_SCE
Definition: DNA_ID_enums.h:57
@ ID_LS
Definition: DNA_ID_enums.h:87
@ ID_MSK
Definition: DNA_ID_enums.h:86
@ ID_GD
Definition: DNA_ID_enums.h:83
@ ID_PAL
Definition: DNA_ID_enums.h:88
@ ID_BR
Definition: DNA_ID_enums.h:81
@ ID_LP
Definition: DNA_ID_enums.h:92
@ ID_HA
Definition: DNA_ID_enums.h:93
@ ID_WO
Definition: DNA_ID_enums.h:71
@ ID_SIM
Definition: DNA_ID_enums.h:96
@ ID_MA
Definition: DNA_ID_enums.h:63
@ ID_AC
Definition: DNA_ID_enums.h:79
@ ID_SCR
Definition: DNA_ID_enums.h:72
@ ID_VF
Definition: DNA_ID_enums.h:73
@ ID_ME
Definition: DNA_ID_enums.h:60
@ ID_IP
Definition: DNA_ID_enums.h:69
@ ID_GR
Definition: DNA_ID_enums.h:77
@ ID_SPK
Definition: DNA_ID_enums.h:75
@ ID_MB
Definition: DNA_ID_enums.h:62
@ ID_LT
Definition: DNA_ID_enums.h:66
@ ID_OB
Definition: DNA_ID_enums.h:59
@ ID_PA
Definition: DNA_ID_enums.h:82
@ ID_PT
Definition: DNA_ID_enums.h:94
@ ID_CU
Definition: DNA_ID_enums.h:61
@ ID_PC
Definition: DNA_ID_enums.h:89
@ IMA_GPU_REFRESH
@ IMA_TYPE_R_RESULT
#define IMA_SHOW_STEREO
@ OB_SOLID
Object is a sort of wrapper for general info.
#define R_STAMP_ALL
#define R_EXTENSION
@ R_ADDSKY
@ R_ALPHAPREMUL
#define R_MULTIVIEW
#define CFRA
#define PSFRA
#define R_NO_OVERWRITE
#define V3D_CAMERA_SCENE(scene, v3d)
#define R_STAMP_DRAW
eImageFormatDepth
@ R_IMF_CHAN_DEPTH_32
#define PRVRANGEON
#define PEFRA
@ SEQ_RENDER_SIZE_SCENE
@ SPACE_SEQ
@ SEQ_SHOW_GPENCIL
@ V3D_OFSDRAW_SHOW_ANNOTATION
#define RV3D_CAMOB
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void DRW_opengl_context_enable(void)
void DRW_opengl_context_disable(void)
bool ED_operator_screenactive(struct bContext *C)
Definition: screen_ops.c:133
bool ED_view3d_context_activate(struct bContext *C)
Definition: view3d_utils.c:244
bool ED_view3d_context_user_region(struct bContext *C, struct View3D **r_v3d, struct ARegion **r_region)
Definition: space_view3d.c:107
void ED_view3d_datamask(const struct bContext *C, const struct Scene *scene, const struct View3D *v3d, struct CustomData_MeshMasks *r_cddata_masks)
struct ImBuf * ED_view3d_draw_offscreen_imbuf(struct Depsgraph *depsgraph, struct Scene *scene, eDrawType drawtype, struct View3D *v3d, struct ARegion *region, int sizex, int sizey, eImBufFlags imbuf_flag, int alpha_mode, const char *viewname, const bool restore_rv3d_mats, struct GPUOffScreen *ofs, char err_out[256])
Definition: view3d_draw.c:1834
struct ImBuf * ED_view3d_draw_offscreen_imbuf_simple(struct Depsgraph *depsgraph, struct Scene *scene, struct View3DShading *shading_override, eDrawType drawtype, struct Object *camera, int width, int height, eImBufFlags imbuf_flags, eV3DOffscreenDrawFlag draw_flags, int alpha_mode, const char *viewname, struct GPUOffScreen *ofs, char err_out[256])
Definition: view3d_draw.c:1991
_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 GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
void GPU_matrix_reset(void)
Definition: gpu_matrix.cc:102
void GPU_matrix_translate_2f(float x, float y)
Definition: gpu_matrix.cc:190
@ GPU_DATA_UBYTE
Definition: GPU_texture.h:175
void imb_freerectfloatImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:97
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_rect_from_float(struct ImBuf *ibuf)
Definition: divers.c:720
void IMB_freeImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:211
Contains defines and structs used throughout the imbuf module.
@ IB_DISPLAY_BUFFER_INVALID
@ IB_rectfloat
@ IB_rect
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Platform independent time functions.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:204
#define C
Definition: RandGen.cpp:39
@ WM_JOB_TYPE_RENDER
Definition: WM_api.h:736
#define ND_RENDER_RESULT
Definition: WM_types.h:346
#define NC_SCENE
Definition: WM_types.h:279
void ED_annotation_draw_ex(Scene *scene, bGPdata *gpd, int winx, int winy, const int cfra, const char spacetype)
static void mul(btAlignedObjectArray< T > &items, const Q &value)
short gpuflag
Scene scene
const Depsgraph * depsgraph
void GPU_offscreen_free(GPUOffScreen *ofs)
void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, eGPUDataFormat format, void *pixels)
void GPU_clear_color(float red, float green, float blue, float alpha)
GPUOffScreen * GPU_offscreen_create(int width, int height, bool depth, bool high_bitdepth, char err_out[256])
void GPU_clear_depth(float depth)
void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
void RE_SetOverrideCamera(Render *re, Object *cam_ob)
Definition: initrender.c:175
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
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
RenderResult * RE_AcquireResultRead(Render *re)
Definition: pipeline.c:343
void RE_ReleaseResultImage(Render *re)
Definition: pipeline.c:512
bool RE_WriteRenderViewsMovie(ReportList *reports, RenderResult *rr, Scene *scene, RenderData *rd, bMovieHandle *mh, void **movie_ctx_arr, const int totvideos, bool preview)
Definition: pipeline.c:2133
bool RE_WriteRenderViewsImage(ReportList *reports, RenderResult *rr, Scene *scene, const bool stamp, char *name)
Definition: pipeline.c:2010
void RE_FreeRenderResult(RenderResult *rr)
Definition: pipeline.c:265
Render * RE_NewSceneRender(const Scene *scene)
Definition: pipeline.c:598
void RE_InitState(Render *re, Render *source, RenderData *rd, ListBase *render_layers, ViewLayer *single_layer, int winx, int winy, rcti *disprect)
Definition: pipeline.c:788
void RE_ReleaseResult(Render *re)
Definition: pipeline.c:379
const char * RE_GetActiveRenderView(Render *re)
Definition: pipeline.c:1746
RenderResult * RE_AcquireResultWrite(Render *re)
Definition: pipeline.c:353
void RE_SetActiveRenderView(Render *re, const char *viewname)
Definition: pipeline.c:1741
return ret
ImBuf * SEQ_render_give_ibuf(const SeqRenderData *context, float timeline_frame, int chanshown)
Definition: render.c:1964
void SEQ_render_new_render_data(Main *bmain, struct Depsgraph *depsgraph, Scene *scene, int rectx, int recty, int preview_render_size, int for_render, SeqRenderData *r_context)
Definition: render.c:211
struct ScrArea * render_view_open(struct bContext *C, int mx, int my, struct ReportList *reports)
Definition: render_view.c:134
static void screen_opengl_render_doit(const bContext *C, OGLRender *oglrender, RenderResult *rr)
static bool schedule_write_result(OGLRender *oglrender, RenderResult *rr)
static bool screen_opengl_render_anim_init(bContext *C, wmOperator *op)
static void screen_opengl_render_end(bContext *C, OGLRender *oglrender)
static void UNUSED_FUNCTION() addAlphaOverFloat(float dest[4], const float source[4])
static int screen_opengl_render_exec(bContext *C, wmOperator *op)
static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEvent *event)
#define MAX_SCHEDULED_FRAMES
Definition: render_opengl.c:96
static char * screen_opengl_render_description(struct bContext *UNUSED(C), struct wmOperatorType *UNUSED(ot), struct PointerRNA *ptr)
static void screen_opengl_views_setup(OGLRender *oglrender)
static void gather_frames_to_render(bContext *C, OGLRender *oglrender)
static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data)
static void gather_frames_to_render_for_adt(const OGLRender *oglrender, const AnimData *adt)
static void write_result_func(TaskPool *__restrict pool, void *task_data_v)
static void screen_opengl_render_apply(const bContext *C, OGLRender *oglrender)
static void screen_opengl_render_write(OGLRender *oglrender)
struct WriteTaskData WriteTaskData
static bool screen_opengl_render_anim_step(bContext *C, wmOperator *op)
void RENDER_OT_opengl(wmOperatorType *ot)
static bool screen_opengl_is_multiview(OGLRender *oglrender)
static bool screen_opengl_render_init(bContext *C, wmOperator *op)
static void gather_frames_to_render_for_grease_pencil(const OGLRender *oglrender, const bGPdata *gp)
struct OGLRender OGLRender
static void screen_opengl_render_cancel(bContext *C, wmOperator *op)
RenderView * RE_RenderViewGetById(RenderResult *rr, const int view_id)
void RE_render_result_rect_from_ibuf(RenderResult *rr, RenderData *UNUSED(rd), ImBuf *ibuf, const int view_id)
RenderResult * RE_DuplicateRenderResult(RenderResult *rr)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
Definition: rna_access.c:6272
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
struct SELECTID_Context context
Definition: select_engine.c:47
void * regiondata
bAction * action
float vec[3][3]
Definition: DNA_ID.h:273
char name[66]
Definition: DNA_ID.h:283
int userflags
unsigned int * rect
float * rect_float
struct Scene * scene
void * last
Definition: DNA_listBase.h:47
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
Main * bmain
Definition: render_opengl.c:99
TaskPool * task_pool
wmTimer * timer
BLI_bitmap * render_frames
ViewLayer * view_layer
SpinLock reports_lock
Render * re
ImBuf ** ibufs_arr
uint num_scheduled_frames
ThreadMutex task_mutex
ARegion * prevar
Depsgraph * depsgraph
RegionView3D * rv3d
Scene * scene
ThreadCondition task_condition
WorkSpace * workspace
wmWindowManager * wm
bool is_animation
void ** movie_ctx_arr
ScrArea * prevsa
ARegion * region
ReportList * reports
bMovieHandle * mh
ImageUser iuser
eImageFormatDepth color_depth
Image * ima
GPUOffScreen * ofs
SpaceSeq * sseq
View3D * v3d
wmWindow * win
struct OGLRender::@480 seq_data
bool is_sequencer
struct ImageFormatData im_format
char pic[1024]
ListBase views
ListBase views
Definition: RE_pipeline.h:138
struct RenderView * prev
Definition: RE_pipeline.h:65
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
struct SceneRenderView * next
struct CustomData_MeshMasks customdata_mask
struct RenderData r
ListBase view_layers
struct CustomData_MeshMasks customdata_mask_modal
struct Object * camera
short chanshown
struct bGPdata * gpd
struct Object * camera
short scenelock
View3DShading shading
RenderResult * rr
Definition: IMB_anim.h:87
ListBase curves
ListBase layers
struct AnimData * adt
void(* end_movie)(void *context_v)
Definition: BKE_writeavi.h:54
int(* start_movie)(void *context_v, const struct Scene *scene, struct RenderData *rd, int rectx, int recty, struct ReportList *reports, bool preview, const char *suffix)
Definition: BKE_writeavi.h:37
void(* context_free)(void *context_v)
Definition: BKE_writeavi.h:63
void *(* context_create)(void)
Definition: BKE_writeavi.h:62
int y
Definition: WM_types.h:581
int x
Definition: WM_types.h:581
short type
Definition: WM_types.h:577
void * customdata
Definition: WM_types.h:631
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
char *(* get_description)(struct bContext *C, struct wmOperatorType *, struct PointerRNA *)
Definition: WM_types.h:799
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct ReportList * reports
struct PointerRNA * ptr
double PIL_check_seconds_timer(void)
Definition: time.c:80
#define G(x, y, z)
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:216
void WM_cursor_time(wmWindow *win, int nr)
Definition: wm_cursors.c:338
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ TIMER
@ EVT_ESCKEY
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
void WM_jobs_kill_all_except(wmWindowManager *wm, void *owner)
Definition: wm_jobs.c:563
bool WM_jobs_test(wmWindowManager *wm, void *owner, int job_type)
Definition: wm_jobs.c:223
void wmOrtho2(float x1, float x2, float y1, float y2)
Definition: wm_subwindow.c:100
void WM_event_remove_timer(wmWindowManager *wm, wmWindow *UNUSED(win), wmTimer *timer)
Definition: wm_window.c:1669
wmTimer * WM_event_add_timer(wmWindowManager *wm, wmWindow *win, int event_type, double timestep)
Definition: wm_window.c:1632