c0a9d0ac453be0f08c74bf88fae998bb35f72edf
[blender.git] / source / blender / windowmanager / intern / wm_draw.c
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) 2007 Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup wm
22  *
23  * Handle OpenGL buffers for windowing, also paint cursor.
24  */
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "DNA_camera_types.h"
30 #include "DNA_listBase.h"
31 #include "DNA_object_types.h"
32 #include "DNA_screen_types.h"
33 #include "DNA_userdef_types.h"
34 #include "DNA_view3d_types.h"
35 #include "DNA_windowmanager_types.h"
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_blenlib.h"
40 #include "BLI_utildefines.h"
41
42 #include "BKE_context.h"
43 #include "BKE_image.h"
44 #include "BKE_main.h"
45 #include "BKE_scene.h"
46 #include "BKE_screen.h"
47
48 #include "GHOST_C-api.h"
49
50 #include "ED_node.h"
51 #include "ED_screen.h"
52 #include "ED_view3d.h"
53
54 #include "GPU_draw.h"
55 #include "GPU_framebuffer.h"
56 #include "GPU_immediate.h"
57 #include "GPU_state.h"
58 #include "GPU_texture.h"
59 #include "GPU_viewport.h"
60
61 #include "RE_engine.h"
62
63 #include "WM_api.h"
64 #include "WM_toolsystem.h"
65 #include "WM_types.h"
66 #include "wm.h"
67 #include "wm_draw.h"
68 #include "wm_event_system.h"
69 #include "wm_surface.h"
70 #include "wm_window.h"
71
72 #include "UI_resources.h"
73
74 #ifdef WITH_OPENSUBDIV
75 #  include "BKE_subsurf.h"
76 #endif
77
78 /* -------------------------------------------------------------------- */
79 /** \name Draw Paint Cursor
80  * \{ */
81
82 static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
83 {
84   wmWindowManager *wm = CTX_wm_manager(C);
85   wmWindow *win = CTX_wm_window(C);
86   bScreen *screen = WM_window_get_active_screen(win);
87   wmPaintCursor *pc;
88
89   /* Don't draw paint cursors with locked interface. Painting is not possible
90    * then, and cursor drawing can use scene data that another thread may be
91    * modifying. */
92   if (wm->is_interface_locked) {
93     return;
94   }
95
96   if (region->visible && region == screen->active_region) {
97     for (pc = wm->paintcursors.first; pc; pc = pc->next) {
98
99       if ((pc->space_type != SPACE_TYPE_ANY) && (area->spacetype != pc->space_type)) {
100         continue;
101       }
102
103       if ((pc->region_type != RGN_TYPE_ANY) && (region->regiontype != pc->region_type)) {
104         continue;
105       }
106
107       if (pc->poll == NULL || pc->poll(C)) {
108         /* Prevent drawing outside region. */
109         glEnable(GL_SCISSOR_TEST);
110         glScissor(region->winrct.xmin,
111                   region->winrct.ymin,
112                   BLI_rcti_size_x(&region->winrct) + 1,
113                   BLI_rcti_size_y(&region->winrct) + 1);
114
115         if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) {
116           int x = 0, y = 0;
117           wm_get_cursor_position(win, &x, &y);
118           pc->draw(C, x, y, pc->customdata);
119         }
120         else {
121           pc->draw(C, win->eventstate->x, win->eventstate->y, pc->customdata);
122         }
123
124         glDisable(GL_SCISSOR_TEST);
125       }
126     }
127   }
128 }
129
130 /** \} */
131
132 /* -------------------------------------------------------------------- */
133 /** \name Post Draw Region on display handlers
134  * \{ */
135
136 static void wm_region_draw_overlay(bContext *C, ScrArea *area, ARegion *region)
137 {
138   wmWindowManager *wm = CTX_wm_manager(C);
139   wmWindow *win = CTX_wm_window(C);
140
141   /* Don't draw overlay with locked interface. Drawing could access scene data that another thread
142    * may be modifying. */
143   if (wm->is_interface_locked) {
144     return;
145   }
146
147   wmViewport(&region->winrct);
148   UI_SetTheme(area->spacetype, region->regiontype);
149   region->type->draw_overlay(C, region);
150   wmWindowViewport(win);
151 }
152
153 /** \} */
154 /* -------------------------------------------------------------------- */
155 /** \name Internal Utilities
156  * \{ */
157
158 static bool wm_draw_region_stereo_set(Main *bmain,
159                                       ScrArea *area,
160                                       ARegion *region,
161                                       eStereoViews sview)
162 {
163   /* We could detect better when stereo is actually needed, by inspecting the
164    * image in the image editor and sequencer. */
165   if (!ELEM(region->regiontype, RGN_TYPE_WINDOW, RGN_TYPE_PREVIEW)) {
166     return false;
167   }
168
169   switch (area->spacetype) {
170     case SPACE_IMAGE: {
171       if (region->regiontype == RGN_TYPE_WINDOW) {
172         SpaceImage *sima = area->spacedata.first;
173         sima->iuser.multiview_eye = sview;
174         return true;
175       }
176       break;
177     }
178     case SPACE_VIEW3D: {
179       if (region->regiontype == RGN_TYPE_WINDOW) {
180         View3D *v3d = area->spacedata.first;
181         if (v3d->camera && v3d->camera->type == OB_CAMERA) {
182           RegionView3D *rv3d = region->regiondata;
183           RenderEngine *engine = rv3d->render_engine;
184           if (engine && !(engine->type->flag & RE_USE_STEREO_VIEWPORT)) {
185             return false;
186           }
187
188           Camera *cam = v3d->camera->data;
189           CameraBGImage *bgpic = cam->bg_images.first;
190           v3d->multiview_eye = sview;
191           if (bgpic) {
192             bgpic->iuser.multiview_eye = sview;
193           }
194           return true;
195         }
196       }
197       break;
198     }
199     case SPACE_NODE: {
200       if (region->regiontype == RGN_TYPE_WINDOW) {
201         SpaceNode *snode = area->spacedata.first;
202         if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
203           Image *ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
204           ima->eye = sview;
205           return true;
206         }
207       }
208       break;
209     }
210     case SPACE_SEQ: {
211       SpaceSeq *sseq = area->spacedata.first;
212       sseq->multiview_eye = sview;
213
214       if (region->regiontype == RGN_TYPE_PREVIEW) {
215         return true;
216       }
217       else if (region->regiontype == RGN_TYPE_WINDOW) {
218         return (sseq->draw_flag & SEQ_DRAW_BACKDROP) != 0;
219       }
220     }
221   }
222
223   return false;
224 }
225
226 static void wm_area_mark_invalid_backbuf(ScrArea *area)
227 {
228   if (area->spacetype == SPACE_VIEW3D) {
229     ((View3D *)area->spacedata.first)->flag |= V3D_INVALID_BACKBUF;
230   }
231 }
232
233 static void wm_region_test_gizmo_do_draw(bContext *C,
234                                          ScrArea *area,
235                                          ARegion *region,
236                                          bool tag_redraw)
237 {
238   if (region->gizmo_map == NULL) {
239     return;
240   }
241
242   wmGizmoMap *gzmap = region->gizmo_map;
243   LISTBASE_FOREACH (wmGizmoGroup *, gzgroup, WM_gizmomap_group_list(gzmap)) {
244     if (tag_redraw && (gzgroup->type->flag & WM_GIZMOGROUPTYPE_VR_REDRAWS)) {
245       ScrArea *ctx_area = CTX_wm_area(C);
246       ARegion *ctx_region = CTX_wm_region(C);
247
248       CTX_wm_area_set(C, area);
249       CTX_wm_region_set(C, region);
250
251       if (WM_gizmo_group_type_poll(C, gzgroup->type)) {
252         ED_region_tag_redraw_editor_overlays(region);
253       }
254
255       /* Reset. */
256       CTX_wm_area_set(C, ctx_area);
257       CTX_wm_region_set(C, ctx_region);
258     }
259
260     LISTBASE_FOREACH (wmGizmo *, gz, &gzgroup->gizmos) {
261       if (gz->do_draw) {
262         if (tag_redraw) {
263           ED_region_tag_redraw_editor_overlays(region);
264         }
265         gz->do_draw = false;
266       }
267     }
268   }
269 }
270
271 static void wm_region_test_render_do_draw(const Scene *scene,
272                                           struct Depsgraph *depsgraph,
273                                           ScrArea *area,
274                                           ARegion *region)
275 {
276   /* tag region for redraw from render engine preview running inside of it */
277   if (area->spacetype == SPACE_VIEW3D && region->regiontype == RGN_TYPE_WINDOW) {
278     RegionView3D *rv3d = region->regiondata;
279     RenderEngine *engine = rv3d->render_engine;
280     GPUViewport *viewport = WM_draw_region_get_viewport(region);
281
282     if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) {
283       View3D *v3d = area->spacedata.first;
284       rcti border_rect;
285
286       /* do partial redraw when possible */
287       if (ED_view3d_calc_render_border(scene, depsgraph, v3d, region, &border_rect)) {
288         ED_region_tag_redraw_partial(region, &border_rect, false);
289       }
290       else {
291         ED_region_tag_redraw_no_rebuild(region);
292       }
293
294       engine->flag &= ~RE_ENGINE_DO_DRAW;
295     }
296     else if (viewport && GPU_viewport_do_update(viewport)) {
297       ED_region_tag_redraw_no_rebuild(region);
298     }
299   }
300 }
301
302 #ifdef WITH_XR_OPENXR
303 static void wm_region_test_xr_do_draw(const wmWindowManager *wm,
304                                       const ScrArea *area,
305                                       ARegion *region)
306 {
307   if ((area->spacetype == SPACE_VIEW3D) && (region->regiontype == RGN_TYPE_WINDOW)) {
308     if (ED_view3d_is_region_xr_mirror_active(wm, area->spacedata.first, region)) {
309       ED_region_tag_redraw_no_rebuild(region);
310     }
311   }
312 }
313 #endif
314
315 static bool wm_region_use_viewport_by_type(short space_type, short region_type)
316 {
317   return (ELEM(space_type, SPACE_VIEW3D, SPACE_IMAGE) && region_type == RGN_TYPE_WINDOW);
318 }
319
320 bool WM_region_use_viewport(ScrArea *area, ARegion *region)
321 {
322   return wm_region_use_viewport_by_type(area->spacetype, region->regiontype);
323 }
324
325 /** \} */
326
327 /* -------------------------------------------------------------------- */
328 /** \name Window Drawing (Draw All)
329  *
330  * Reference method, draw all each time.
331  * \{ */
332
333 typedef struct WindowDrawCB {
334   struct WindowDrawCB *next, *prev;
335
336   void (*draw)(const struct wmWindow *, void *);
337   void *customdata;
338
339 } WindowDrawCB;
340
341 void *WM_draw_cb_activate(wmWindow *win,
342                           void (*draw)(const struct wmWindow *, void *),
343                           void *customdata)
344 {
345   WindowDrawCB *wdc = MEM_callocN(sizeof(*wdc), "WindowDrawCB");
346
347   BLI_addtail(&win->drawcalls, wdc);
348   wdc->draw = draw;
349   wdc->customdata = customdata;
350
351   return wdc;
352 }
353
354 void WM_draw_cb_exit(wmWindow *win, void *handle)
355 {
356   LISTBASE_FOREACH (WindowDrawCB *, wdc, &win->drawcalls) {
357     if (wdc == (WindowDrawCB *)handle) {
358       BLI_remlink(&win->drawcalls, wdc);
359       MEM_freeN(wdc);
360       return;
361     }
362   }
363 }
364
365 static void wm_draw_callbacks(wmWindow *win)
366 {
367   LISTBASE_FOREACH (WindowDrawCB *, wdc, &win->drawcalls) {
368     wdc->draw(win, wdc->customdata);
369   }
370 }
371
372 /** \} */
373
374 /* -------------------------------------------------------------------- */
375 /** \name Region Drawing
376  *
377  * Each region draws into its own frame-buffer, which is then blit on the
378  * window draw buffer. This helps with fast redrawing if only some regions
379  * change. It also means we can share a single context for multiple windows,
380  * so that for example VAOs can be shared between windows.
381  * \{ */
382
383 static void wm_draw_region_buffer_free(ARegion *region)
384 {
385   if (region->draw_buffer) {
386     if (region->draw_buffer->viewport) {
387       GPU_viewport_free(region->draw_buffer->viewport);
388     }
389     if (region->draw_buffer->offscreen) {
390       GPU_offscreen_free(region->draw_buffer->offscreen);
391     }
392
393     MEM_freeN(region->draw_buffer);
394     region->draw_buffer = NULL;
395   }
396 }
397
398 static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen)
399 {
400   /* Setup offscreen color texture for drawing. */
401   GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
402
403   /* We don't support multisample textures here. */
404   BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D);
405
406   glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
407
408   /* No mipmaps or filtering. */
409   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
410   /* GL_TEXTURE_BASE_LEVEL = 0 by default */
411   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
412   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
413   glBindTexture(GL_TEXTURE_2D, 0);
414 }
415
416 static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_viewport)
417 {
418   if (region->draw_buffer) {
419     if (region->draw_buffer->stereo != stereo) {
420       /* Free draw buffer on stereo changes. */
421       wm_draw_region_buffer_free(region);
422     }
423     else {
424       /* Free offscreen buffer on size changes. Viewport auto resizes. */
425       GPUOffScreen *offscreen = region->draw_buffer->offscreen;
426       if (offscreen && (GPU_offscreen_width(offscreen) != region->winx ||
427                         GPU_offscreen_height(offscreen) != region->winy)) {
428         wm_draw_region_buffer_free(region);
429       }
430     }
431   }
432
433   if (!region->draw_buffer) {
434     if (use_viewport) {
435       /* Allocate viewport which includes an offscreen buffer with depth
436        * multisample, etc. */
437       region->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer");
438       region->draw_buffer->viewport = stereo ? GPU_viewport_stereo_create() :
439                                                GPU_viewport_create();
440     }
441     else {
442       /* Allocate offscreen buffer if it does not exist. This one has no
443        * depth or multisample buffers. 3D view creates own buffers with
444        * the data it needs. */
445       GPUOffScreen *offscreen = GPU_offscreen_create(
446           region->winx, region->winy, 0, false, false, NULL);
447       if (!offscreen) {
448         return;
449       }
450
451       wm_draw_offscreen_texture_parameters(offscreen);
452
453       region->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer");
454       region->draw_buffer->offscreen = offscreen;
455     }
456
457     region->draw_buffer->bound_view = -1;
458     region->draw_buffer->stereo = stereo;
459   }
460 }
461
462 static void wm_draw_region_bind(ARegion *region, int view)
463 {
464   if (!region->draw_buffer) {
465     return;
466   }
467
468   if (region->draw_buffer->viewport) {
469     GPU_viewport_bind(region->draw_buffer->viewport, view, &region->winrct);
470   }
471   else {
472     GPU_offscreen_bind(region->draw_buffer->offscreen, false);
473
474     /* For now scissor is expected by region drawing, we could disable it
475      * and do the enable/disable in the specific cases that setup scissor. */
476     glEnable(GL_SCISSOR_TEST);
477     glScissor(0, 0, region->winx, region->winy);
478   }
479
480   region->draw_buffer->bound_view = view;
481 }
482
483 static void wm_draw_region_unbind(ARegion *region)
484 {
485   if (!region->draw_buffer) {
486     return;
487   }
488
489   region->draw_buffer->bound_view = -1;
490
491   if (region->draw_buffer->viewport) {
492     GPU_viewport_unbind(region->draw_buffer->viewport);
493   }
494   else {
495     glDisable(GL_SCISSOR_TEST);
496     GPU_offscreen_unbind(region->draw_buffer->offscreen, false);
497   }
498 }
499
500 static void wm_draw_region_blit(ARegion *region, int view)
501 {
502   if (!region->draw_buffer) {
503     return;
504   }
505
506   if (view == -1) {
507     /* Non-stereo drawing. */
508     view = 0;
509   }
510   else if (view > 0) {
511     if (region->draw_buffer->viewport == NULL) {
512       /* Region does not need stereo or failed to allocate stereo buffers. */
513       view = 0;
514     }
515   }
516
517   if (region->draw_buffer->viewport) {
518     GPU_viewport_draw_to_screen(region->draw_buffer->viewport, view, &region->winrct);
519   }
520   else {
521     GPU_offscreen_draw_to_screen(
522         region->draw_buffer->offscreen, region->winrct.xmin, region->winrct.ymin);
523   }
524 }
525
526 GPUTexture *wm_draw_region_texture(ARegion *region, int view)
527 {
528   if (!region->draw_buffer) {
529     return NULL;
530   }
531
532   GPUViewport *viewport = region->draw_buffer->viewport;
533   if (viewport) {
534     return GPU_viewport_color_texture(viewport, view);
535   }
536   else {
537     return GPU_offscreen_color_texture(region->draw_buffer->offscreen);
538   }
539 }
540
541 void wm_draw_region_blend(ARegion *region, int view, bool blend)
542 {
543   if (!region->draw_buffer) {
544     return;
545   }
546
547   /* Alpha is always 1, except when blend timer is running. */
548   float alpha = ED_region_blend_alpha(region);
549   if (alpha <= 0.0f) {
550     return;
551   }
552
553   if (!blend) {
554     alpha = 1.0f;
555   }
556
557   /* setup actual texture */
558   GPUTexture *texture = wm_draw_region_texture(region, view);
559   glActiveTexture(GL_TEXTURE0);
560   glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
561
562   /* wmOrtho for the screen has this same offset */
563   const float halfx = GLA_PIXEL_OFS / (BLI_rcti_size_x(&region->winrct) + 1);
564   const float halfy = GLA_PIXEL_OFS / (BLI_rcti_size_y(&region->winrct) + 1);
565
566   if (blend) {
567     /* GL_ONE because regions drawn offscreen have premultiplied alpha. */
568     GPU_blend(true);
569     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
570   }
571
572   GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
573   GPU_shader_bind(shader);
574
575   rcti rect_geo = region->winrct;
576   rect_geo.xmax += 1;
577   rect_geo.ymax += 1;
578
579   rctf rect_tex;
580   rect_tex.xmin = halfx;
581   rect_tex.ymin = halfy;
582   rect_tex.xmax = 1.0f + halfx;
583   rect_tex.ymax = 1.0f + halfy;
584
585   float alpha_easing = 1.0f - alpha;
586   alpha_easing = 1.0f - alpha_easing * alpha_easing;
587
588   /* Slide vertical panels */
589   float ofs_x = BLI_rcti_size_x(&region->winrct) * (1.0f - alpha_easing);
590   if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_RIGHT) {
591     rect_geo.xmin += ofs_x;
592     rect_tex.xmax *= alpha_easing;
593     alpha = 1.0f;
594   }
595   else if (RGN_ALIGN_ENUM_FROM_MASK(region->alignment) == RGN_ALIGN_LEFT) {
596     rect_geo.xmax -= ofs_x;
597     rect_tex.xmin += 1.0f - alpha_easing;
598     alpha = 1.0f;
599   }
600
601   glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
602   glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"),
603               rect_tex.xmin,
604               rect_tex.ymin,
605               rect_tex.xmax,
606               rect_tex.ymax);
607   glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"),
608               rect_geo.xmin,
609               rect_geo.ymin,
610               rect_geo.xmax,
611               rect_geo.ymax);
612   glUniform4f(
613       GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
614
615   GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
616
617   glBindTexture(GL_TEXTURE_2D, 0);
618
619   if (blend) {
620     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
621     GPU_blend(false);
622   }
623 }
624
625 GPUViewport *WM_draw_region_get_viewport(ARegion *region)
626 {
627   if (!region->draw_buffer) {
628     return NULL;
629   }
630
631   GPUViewport *viewport = region->draw_buffer->viewport;
632   return viewport;
633 }
634
635 GPUViewport *WM_draw_region_get_bound_viewport(ARegion *region)
636 {
637   if (!region->draw_buffer || region->draw_buffer->bound_view == -1) {
638     return NULL;
639   }
640
641   GPUViewport *viewport = region->draw_buffer->viewport;
642   return viewport;
643 }
644
645 static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
646 {
647   Main *bmain = CTX_data_main(C);
648   wmWindowManager *wm = CTX_wm_manager(C);
649   bScreen *screen = WM_window_get_active_screen(win);
650
651   /* Draw screen areas into own frame buffer. */
652   ED_screen_areas_iter (win, screen, area) {
653     CTX_wm_area_set(C, area);
654
655     /* Compute UI layouts for dynamically size regions. */
656     LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
657       /* Dynamic region may have been flagged as too small because their size on init is 0.
658        * ARegion.visible is false then, as expected. The layout should still be created then, so
659        * the region size can be updated (it may turn out to be not too small then). */
660       const bool ignore_visibility = (region->flag & RGN_FLAG_DYNAMIC_SIZE) &&
661                                      (region->flag & RGN_FLAG_TOO_SMALL) &&
662                                      !(region->flag & RGN_FLAG_HIDDEN);
663
664       if ((region->visible || ignore_visibility) && region->do_draw && region->type &&
665           region->type->layout) {
666         CTX_wm_region_set(C, region);
667         ED_region_do_layout(C, region);
668         CTX_wm_region_set(C, NULL);
669       }
670     }
671
672     ED_area_update_region_sizes(wm, win, area);
673
674     if (area->flag & AREA_FLAG_ACTIVE_TOOL_UPDATE) {
675       if ((1 << area->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
676         WM_toolsystem_update_from_context(C, CTX_wm_workspace(C), CTX_data_view_layer(C), area);
677       }
678       area->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE;
679     }
680
681     /* Then do actual drawing of regions. */
682     LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
683       if (region->visible && region->do_draw) {
684         CTX_wm_region_set(C, region);
685         bool use_viewport = WM_region_use_viewport(area, region);
686
687         if (stereo && wm_draw_region_stereo_set(bmain, area, region, STEREO_LEFT_ID)) {
688           wm_draw_region_buffer_create(region, true, use_viewport);
689
690           for (int view = 0; view < 2; view++) {
691             eStereoViews sview;
692             if (view == 0) {
693               sview = STEREO_LEFT_ID;
694             }
695             else {
696               sview = STEREO_RIGHT_ID;
697               wm_draw_region_stereo_set(bmain, area, region, sview);
698             }
699
700             wm_draw_region_bind(region, view);
701             ED_region_do_draw(C, region);
702             wm_draw_region_unbind(region);
703           }
704           if (use_viewport) {
705             GPUViewport *viewport = region->draw_buffer->viewport;
706             GPU_viewport_stereo_composite(viewport, win->stereo3d_format);
707           }
708         }
709         else {
710           wm_draw_region_buffer_create(region, false, use_viewport);
711           wm_draw_region_bind(region, 0);
712           ED_region_do_draw(C, region);
713           wm_draw_region_unbind(region);
714         }
715
716         region->do_draw = false;
717         CTX_wm_region_set(C, NULL);
718       }
719     }
720
721     wm_area_mark_invalid_backbuf(area);
722     CTX_wm_area_set(C, NULL);
723   }
724
725   /* Draw menus into their own framebuffer. */
726   LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
727     if (region->visible) {
728       CTX_wm_menu_set(C, region);
729
730       if (region->type && region->type->layout) {
731         /* UI code reads the OpenGL state, but we have to refresh
732          * the UI layout beforehand in case the menu size changes. */
733         wmViewport(&region->winrct);
734         region->type->layout(C, region);
735       }
736
737       wm_draw_region_buffer_create(region, false, false);
738       wm_draw_region_bind(region, 0);
739       glClearColor(0, 0, 0, 0);
740       glClear(GL_COLOR_BUFFER_BIT);
741       ED_region_do_draw(C, region);
742       wm_draw_region_unbind(region);
743
744       region->do_draw = false;
745       CTX_wm_menu_set(C, NULL);
746     }
747   }
748 }
749
750 static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
751 {
752   wmWindowManager *wm = CTX_wm_manager(C);
753   bScreen *screen = WM_window_get_active_screen(win);
754
755   /* Draw into the window framebuffer, in full window coordinates. */
756   wmWindowViewport(win);
757
758   /* We draw on all pixels of the windows so we don't need to clear them before.
759    * Actually this is only a problem when resizing the window.
760    * If it becomes a problem we should clear only when window size changes. */
761 #if 0
762   glClearColor(0, 0, 0, 0);
763   glClear(GL_COLOR_BUFFER_BIT);
764 #endif
765
766   /* Blit non-overlapping area regions. */
767   ED_screen_areas_iter (win, screen, area) {
768     LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
769       if (region->visible && region->overlap == false) {
770         /* Blit from offscreen buffer. */
771         wm_draw_region_blit(region, view);
772       }
773     }
774   }
775
776   /* Draw overlays and paint cursors. */
777   ED_screen_areas_iter (win, screen, area) {
778     LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
779       if (region->visible) {
780         const bool do_paint_cursor = (wm->paintcursors.first && region == screen->active_region);
781         const bool do_draw_overlay = (region->type && region->type->draw_overlay);
782         if (!(do_paint_cursor || do_draw_overlay)) {
783           continue;
784         }
785
786         CTX_wm_area_set(C, area);
787         CTX_wm_region_set(C, region);
788         if (do_draw_overlay) {
789           wm_region_draw_overlay(C, area, region);
790         }
791         if (do_paint_cursor) {
792           wm_paintcursor_draw(C, area, region);
793         }
794         CTX_wm_region_set(C, NULL);
795         CTX_wm_area_set(C, NULL);
796       }
797     }
798   }
799   wmWindowViewport(win);
800
801   /* Blend in overlapping area regions */
802   ED_screen_areas_iter (win, screen, area) {
803     LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
804       if (region->visible && region->overlap) {
805         wm_draw_region_blend(region, 0, true);
806       }
807     }
808   }
809
810   /* After area regions so we can do area 'overlay' drawing. */
811   ED_screen_draw_edges(win);
812   wm_draw_callbacks(win);
813
814   /* Blend in floating regions (menus). */
815   LISTBASE_FOREACH (ARegion *, region, &screen->regionbase) {
816     if (region->visible) {
817       wm_draw_region_blend(region, 0, true);
818     }
819   }
820
821   /* always draw, not only when screen tagged */
822   if (win->gesture.first) {
823     wm_gesture_draw(win);
824   }
825
826   /* needs pixel coords in screen */
827   if (wm->drags.first) {
828     wm_drags_draw(C, win, NULL);
829   }
830 }
831
832 static void wm_draw_window(bContext *C, wmWindow *win)
833 {
834   bScreen *screen = WM_window_get_active_screen(win);
835   bool stereo = WM_stereo3d_enabled(win, false);
836   /* Draw area regions into their own framebuffer. This way we can redraw
837    * the areas that need it, and blit the rest from existing framebuffers. */
838   wm_draw_window_offscreen(C, win, stereo);
839
840   /* Now we draw into the window framebuffer, in full window coordinates. */
841   if (!stereo) {
842     /* Regular mono drawing. */
843     wm_draw_window_onscreen(C, win, -1);
844   }
845   else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
846     /* For pageflip we simply draw to both back buffers. */
847     glDrawBuffer(GL_BACK_LEFT);
848     wm_draw_window_onscreen(C, win, 0);
849     glDrawBuffer(GL_BACK_RIGHT);
850     wm_draw_window_onscreen(C, win, 1);
851     glDrawBuffer(GL_BACK);
852   }
853   else if (ELEM(win->stereo3d_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) {
854     /* For anaglyph and interlace, we draw individual regions with
855      * stereo framebuffers using different shaders. */
856     wm_draw_window_onscreen(C, win, -1);
857   }
858   else {
859     /* For side-by-side and top-bottom, we need to render each view to an
860      * an offscreen texture and then draw it. This used to happen for all
861      * stereo methods, but it's less efficient than drawing directly. */
862     const int width = WM_window_pixels_x(win);
863     const int height = WM_window_pixels_y(win);
864     GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL);
865
866     if (offscreen) {
867       GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
868       wm_draw_offscreen_texture_parameters(offscreen);
869
870       for (int view = 0; view < 2; view++) {
871         /* Draw view into offscreen buffer. */
872         GPU_offscreen_bind(offscreen, false);
873         wm_draw_window_onscreen(C, win, view);
874         GPU_offscreen_unbind(offscreen, false);
875
876         /* Draw offscreen buffer to screen. */
877         glActiveTexture(GL_TEXTURE0);
878         glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
879
880         wmWindowViewport(win);
881         if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) {
882           wm_stereo3d_draw_sidebyside(win, view);
883         }
884         else {
885           wm_stereo3d_draw_topbottom(win, view);
886         }
887
888         glBindTexture(GL_TEXTURE_2D, 0);
889       }
890
891       GPU_offscreen_free(offscreen);
892     }
893     else {
894       /* Still draw something in case of allocation failure. */
895       wm_draw_window_onscreen(C, win, 0);
896     }
897   }
898
899   screen->do_draw = false;
900 }
901
902 /**
903  * Draw offscreen contexts not bound to a specific window.
904  */
905 static void wm_draw_surface(bContext *C, wmSurface *surface)
906 {
907   wm_window_clear_drawable(CTX_wm_manager(C));
908   wm_surface_make_drawable(surface);
909
910   surface->draw(C);
911
912   /* Avoid interference with window drawable */
913   wm_surface_clear_drawable();
914 }
915
916 /** \} */
917
918 /* -------------------------------------------------------------------- */
919 /** \name Main Update Call
920  * \{ */
921
922 /* quick test to prevent changing window drawable */
923 static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win)
924 {
925   const wmWindowManager *wm = CTX_wm_manager(C);
926   Scene *scene = WM_window_get_active_scene(win);
927   ViewLayer *view_layer = WM_window_get_active_view_layer(win);
928   struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true);
929   bScreen *screen = WM_window_get_active_screen(win);
930   ARegion *region;
931   bool do_draw = false;
932
933   for (region = screen->regionbase.first; region; region = region->next) {
934     if (region->do_draw_overlay) {
935       screen->do_draw_paintcursor = true;
936       region->do_draw_overlay = false;
937     }
938     if (region->visible && region->do_draw) {
939       do_draw = true;
940     }
941   }
942
943   ED_screen_areas_iter (win, screen, area) {
944     for (region = area->regionbase.first; region; region = region->next) {
945       wm_region_test_gizmo_do_draw(C, area, region, true);
946       wm_region_test_render_do_draw(scene, depsgraph, area, region);
947 #ifdef WITH_XR_OPENXR
948       wm_region_test_xr_do_draw(wm, area, region);
949 #endif
950
951       if (region->visible && region->do_draw) {
952         do_draw = true;
953       }
954     }
955   }
956
957   if (do_draw) {
958     return true;
959   }
960
961   if (screen->do_refresh) {
962     return true;
963   }
964   if (screen->do_draw) {
965     return true;
966   }
967   if (screen->do_draw_gesture) {
968     return true;
969   }
970   if (screen->do_draw_paintcursor) {
971     return true;
972   }
973   if (screen->do_draw_drag) {
974     return true;
975   }
976
977 #ifndef WITH_XR_OPENXR
978   UNUSED_VARS(wm);
979 #endif
980
981   return false;
982 }
983
984 /* Clear drawing flags, after drawing is complete so any draw flags set during
985  * drawing don't cause any additional redraws. */
986 static void wm_draw_update_clear_window(bContext *C, wmWindow *win)
987 {
988   bScreen *screen = WM_window_get_active_screen(win);
989
990   ED_screen_areas_iter (win, screen, area) {
991     LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
992       wm_region_test_gizmo_do_draw(C, area, region, false);
993     }
994   }
995
996   screen->do_draw_gesture = false;
997   screen->do_draw_paintcursor = false;
998   screen->do_draw_drag = false;
999 }
1000
1001 void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *UNUSED(region))
1002 {
1003   if (win) {
1004     bScreen *screen = WM_window_get_active_screen(win);
1005     screen->do_draw_paintcursor = true;
1006   }
1007 }
1008
1009 void wm_draw_update(bContext *C)
1010 {
1011   Main *bmain = CTX_data_main(C);
1012   wmWindowManager *wm = CTX_wm_manager(C);
1013   wmWindow *win;
1014
1015   GPU_free_unused_buffers(bmain);
1016
1017   for (win = wm->windows.first; win; win = win->next) {
1018 #ifdef WIN32
1019     GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
1020
1021     if (state == GHOST_kWindowStateMinimized) {
1022       /* do not update minimized windows, gives issues on Intel (see T33223)
1023        * and AMD (see T50856). it seems logical to skip update for invisible
1024        * window anyway.
1025        */
1026       continue;
1027     }
1028 #endif
1029
1030     CTX_wm_window_set(C, win);
1031
1032     if (wm_draw_update_test_window(bmain, C, win)) {
1033       bScreen *screen = WM_window_get_active_screen(win);
1034
1035       /* sets context window+screen */
1036       wm_window_make_drawable(wm, win);
1037
1038       /* notifiers for screen redraw */
1039       ED_screen_ensure_updated(wm, win, screen);
1040
1041       wm_draw_window(C, win);
1042       wm_draw_update_clear_window(C, win);
1043
1044       wm_window_swap_buffers(win);
1045     }
1046   }
1047
1048   CTX_wm_window_set(C, NULL);
1049
1050   /* Draw non-windows (surfaces) */
1051   wm_surfaces_iter(C, wm_draw_surface);
1052 }
1053
1054 void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(region))
1055 {
1056   bScreen *screen = WM_window_get_active_screen(win);
1057   screen->do_draw = true;
1058 }
1059
1060 void WM_draw_region_free(ARegion *region, bool hide)
1061 {
1062   wm_draw_region_buffer_free(region);
1063   if (hide) {
1064     region->visible = 0;
1065   }
1066 }
1067
1068 void wm_draw_region_test(bContext *C, ScrArea *area, ARegion *region)
1069 {
1070   /* Function for redraw timer benchmark. */
1071   bool use_viewport = WM_region_use_viewport(area, region);
1072   wm_draw_region_buffer_create(region, false, use_viewport);
1073   wm_draw_region_bind(region, 0);
1074   ED_region_do_draw(C, region);
1075   wm_draw_region_unbind(region);
1076   region->do_draw = false;
1077 }
1078
1079 void WM_redraw_windows(bContext *C)
1080 {
1081   wmWindow *win_prev = CTX_wm_window(C);
1082   ScrArea *area_prev = CTX_wm_area(C);
1083   ARegion *region_prev = CTX_wm_region(C);
1084
1085   wm_draw_update(C);
1086
1087   CTX_wm_window_set(C, win_prev);
1088   CTX_wm_area_set(C, area_prev);
1089   CTX_wm_region_set(C, region_prev);
1090 }
1091
1092 /** \} */
1093
1094 /* -------------------------------------------------------------------- */
1095 /** \name Region Viewport Drawing
1096  *
1097  * This is needed for viewport drawing for operator use
1098  * (where the viewport may not have drawn yet).
1099  *
1100  * Otherwise avoid using these sine they're exposing low level logic externally.
1101  *
1102  * \{ */
1103
1104 void WM_draw_region_viewport_ensure(ARegion *region, short space_type)
1105 {
1106   bool use_viewport = wm_region_use_viewport_by_type(space_type, region->regiontype);
1107   wm_draw_region_buffer_create(region, false, use_viewport);
1108 }
1109
1110 void WM_draw_region_viewport_bind(ARegion *region)
1111 {
1112   wm_draw_region_bind(region, 0);
1113 }
1114
1115 void WM_draw_region_viewport_unbind(ARegion *region)
1116 {
1117   wm_draw_region_unbind(region);
1118 }
1119
1120 /** \} */