GPU: Rename GPU_shader_get_uniform to GPU_shader_get_uniform_ensure
[blender.git] / source / blender / windowmanager / intern / wm_draw.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2007 Blender Foundation.
19  * All rights reserved.
20  *
21  *
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/windowmanager/intern/wm_draw.c
28  *  \ingroup wm
29  *
30  * Handle OpenGL buffers for windowing, also paint cursor.
31  */
32
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "DNA_listBase.h"
37 #include "DNA_object_types.h"
38 #include "DNA_camera_types.h"
39 #include "DNA_screen_types.h"
40 #include "DNA_windowmanager_types.h"
41 #include "DNA_userdef_types.h"
42 #include "DNA_view3d_types.h"
43
44 #include "MEM_guardedalloc.h"
45
46 #include "BLI_blenlib.h"
47 #include "BLI_utildefines.h"
48
49 #include "BIF_gl.h"
50
51 #include "BKE_context.h"
52 #include "BKE_image.h"
53 #include "BKE_main.h"
54 #include "BKE_screen.h"
55 #include "BKE_scene.h"
56 #include "BKE_workspace.h"
57
58 #include "GHOST_C-api.h"
59
60 #include "ED_node.h"
61 #include "ED_view3d.h"
62 #include "ED_screen.h"
63
64 #include "GPU_draw.h"
65 #include "GPU_extensions.h"
66 #include "GPU_framebuffer.h"
67 #include "GPU_immediate.h"
68 #include "GPU_matrix.h"
69 #include "GPU_texture.h"
70 #include "GPU_viewport.h"
71
72 #include "RE_engine.h"
73
74 #include "WM_api.h"
75 #include "WM_types.h"
76 #include "WM_toolsystem.h"
77 #include "wm.h"
78 #include "wm_draw.h"
79 #include "wm_window.h"
80 #include "wm_event_system.h"
81
82 #ifdef WITH_OPENSUBDIV
83 #  include "BKE_subsurf.h"
84 #endif
85
86
87 /* ******************* paint cursor *************** */
88
89 static void wm_paintcursor_draw(bContext *C, ScrArea *sa, ARegion *ar)
90 {
91         wmWindowManager *wm = CTX_wm_manager(C);
92         wmWindow *win = CTX_wm_window(C);
93         bScreen *screen = WM_window_get_active_screen(win);
94         wmPaintCursor *pc;
95
96         if (ar->visible && ar == screen->active_region) {
97                 for (pc = wm->paintcursors.first; pc; pc = pc->next) {
98
99                         if ((pc->space_type != SPACE_TYPE_ANY) && (sa->spacetype != pc->space_type)) {
100                                 continue;
101                         }
102
103                         if ((pc->region_type != RGN_TYPE_ANY) && (ar->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(ar->winrct.xmin,
111                                           ar->winrct.ymin,
112                                           BLI_rcti_size_x(&ar->winrct) + 1,
113                                           BLI_rcti_size_y(&ar->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 static bool wm_draw_region_stereo_set(Main *bmain, ScrArea *sa, ARegion *ar, eStereoViews sview)
132 {
133         /* We could detect better when stereo is actually needed, by inspecting the
134          * image in the image editor and sequencer. */
135         if (ar->regiontype != RGN_TYPE_WINDOW) {
136                 return false;
137         }
138
139         switch (sa->spacetype) {
140                 case SPACE_IMAGE:
141                 {
142                         SpaceImage *sima = sa->spacedata.first;
143                         sima->iuser.multiview_eye = sview;
144                         return true;
145                 }
146                 case SPACE_VIEW3D:
147                 {
148                         View3D *v3d = sa->spacedata.first;
149                         if (v3d->camera && v3d->camera->type == OB_CAMERA) {
150                                 Camera *cam = v3d->camera->data;
151                                 CameraBGImage *bgpic = cam->bg_images.first;
152                                 v3d->multiview_eye = sview;
153                                 if (bgpic) bgpic->iuser.multiview_eye = sview;
154                                 return true;
155                         }
156                         return false;
157                 }
158                 case SPACE_NODE:
159                 {
160                         SpaceNode *snode = sa->spacedata.first;
161                         if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
162                                 Image *ima = BKE_image_verify_viewer(bmain, IMA_TYPE_COMPOSITE, "Viewer Node");
163                                 ima->eye = sview;
164                                 return true;
165                         }
166                         return false;
167                 }
168                 case SPACE_SEQ:
169                 {
170                         SpaceSeq *sseq = sa->spacedata.first;
171                         sseq->multiview_eye = sview;
172                         return true;
173                 }
174         }
175
176         return false;
177 }
178
179 /* ********************* drawing ****************** */
180
181 static void wm_area_mark_invalid_backbuf(ScrArea *sa)
182 {
183         if (sa->spacetype == SPACE_VIEW3D)
184                 ((View3D *)sa->spacedata.first)->flag |= V3D_INVALID_BACKBUF;
185 }
186
187 static void wm_region_test_render_do_draw(const Scene *scene, struct Depsgraph *depsgraph,
188                                           ScrArea *sa, ARegion *ar)
189 {
190         /* tag region for redraw from render engine preview running inside of it */
191         if (sa->spacetype == SPACE_VIEW3D && ar->regiontype == RGN_TYPE_WINDOW) {
192                 RegionView3D *rv3d = ar->regiondata;
193                 RenderEngine *engine = rv3d->render_engine;
194                 GPUViewport *viewport = WM_draw_region_get_viewport(ar, 0);
195
196                 if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) {
197                         View3D *v3d = sa->spacedata.first;
198                         rcti border_rect;
199
200                         /* do partial redraw when possible */
201                         if (ED_view3d_calc_render_border(scene, depsgraph, v3d, ar, &border_rect))
202                                 ED_region_tag_redraw_partial(ar, &border_rect);
203                         else
204                                 ED_region_tag_redraw(ar);
205
206                         engine->flag &= ~RE_ENGINE_DO_DRAW;
207                 }
208                 else if (viewport && GPU_viewport_do_update(viewport)) {
209                         ED_region_tag_redraw(ar);
210                 }
211         }
212 }
213
214 static bool wm_region_use_viewport(ScrArea *sa, ARegion *ar)
215 {
216         return (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_IMAGE) && ar->regiontype == RGN_TYPE_WINDOW);
217 }
218
219 /********************** draw all **************************/
220 /* - reference method, draw all each time                 */
221
222 typedef struct WindowDrawCB {
223         struct WindowDrawCB *next, *prev;
224
225         void(*draw)(const struct wmWindow *, void *);
226         void *customdata;
227
228 } WindowDrawCB;
229
230 void *WM_draw_cb_activate(
231         wmWindow *win,
232         void(*draw)(const struct wmWindow *, void *),
233         void *customdata)
234 {
235         WindowDrawCB *wdc = MEM_callocN(sizeof(*wdc), "WindowDrawCB");
236
237         BLI_addtail(&win->drawcalls, wdc);
238         wdc->draw = draw;
239         wdc->customdata = customdata;
240
241         return wdc;
242 }
243
244 void WM_draw_cb_exit(wmWindow *win, void *handle)
245 {
246         for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) {
247                 if (wdc == (WindowDrawCB *)handle) {
248                         BLI_remlink(&win->drawcalls, wdc);
249                         MEM_freeN(wdc);
250                         return;
251                 }
252         }
253 }
254
255 static void wm_draw_callbacks(wmWindow *win)
256 {
257         for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) {
258                 wdc->draw(win, wdc->customdata);
259         }
260 }
261
262
263 /************************* Region drawing. ********************************
264  *
265  * Each region draws into its own framebuffer, which is then blit on the
266  * window draw buffer. This helps with fast redrawing if only some regions
267  * change. It also means we can share a single context for multiple windows,
268  * so that for example VAOs can be shared between windows. */
269
270 static void wm_draw_region_buffer_free(ARegion *ar)
271 {
272         if (ar->draw_buffer) {
273                 for (int view = 0; view < 2; view++) {
274                         if (ar->draw_buffer->offscreen[view]) {
275                                 GPU_offscreen_free(ar->draw_buffer->offscreen[view]);
276                         }
277                         if (ar->draw_buffer->viewport[view]) {
278                                 GPU_viewport_free(ar->draw_buffer->viewport[view]);
279                         }
280                 }
281
282                 MEM_freeN(ar->draw_buffer);
283                 ar->draw_buffer = NULL;
284         }
285 }
286
287 static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen)
288 {
289         /* Setup offscreen color texture for drawing. */
290         GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
291
292         /* We don't support multisample textures here. */
293         BLI_assert(GPU_texture_target(texture) == GL_TEXTURE_2D);
294
295         glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
296
297         /* No mipmaps or filtering. */
298         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
299         /* GL_TEXTURE_BASE_LEVEL = 0 by default */
300         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
301         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
302
303         glBindTexture(GL_TEXTURE_2D, 0);
304 }
305
306 static void wm_draw_region_buffer_create(ARegion *ar, bool stereo, bool use_viewport)
307 {
308         if (ar->draw_buffer) {
309                 if (ar->draw_buffer->stereo != stereo) {
310                         /* Free draw buffer on stereo changes. */
311                         wm_draw_region_buffer_free(ar);
312                 }
313                 else {
314                         /* Free offscreen buffer on size changes. Viewport auto resizes. */
315                         GPUOffScreen *offscreen = ar->draw_buffer->offscreen[0];
316                         if (offscreen && (GPU_offscreen_width(offscreen) != ar->winx ||
317                                           GPU_offscreen_height(offscreen) != ar->winy))
318                         {
319                                 wm_draw_region_buffer_free(ar);
320                         }
321                 }
322         }
323
324         if (!ar->draw_buffer) {
325                 if (use_viewport) {
326                         /* Allocate viewport which includes an offscreen buffer with depth
327                          * multisample, etc. */
328                         ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer");
329                         ar->draw_buffer->viewport[0] = GPU_viewport_create();
330                         ar->draw_buffer->viewport[1] = (stereo) ? GPU_viewport_create() : NULL;
331                 }
332                 else {
333                         /* Allocate offscreen buffer if it does not exist. This one has no
334                          * depth or multisample buffers. 3D view creates own buffers with
335                          * the data it needs. */
336                         GPUOffScreen *offscreen = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL);
337                         if (!offscreen) {
338                                 return;
339                         }
340
341                         wm_draw_offscreen_texture_parameters(offscreen);
342
343                         GPUOffScreen *offscreen_right = NULL;
344                         if (stereo) {
345                                 offscreen_right = GPU_offscreen_create(ar->winx, ar->winy, 0, false, false, NULL);
346
347                                 if (!offscreen_right) {
348                                         GPU_offscreen_free(offscreen);
349                                         return;
350                                 }
351
352                                 wm_draw_offscreen_texture_parameters(offscreen_right);
353                         }
354
355                         ar->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer");
356                         ar->draw_buffer->offscreen[0] = offscreen;
357                         ar->draw_buffer->offscreen[1] = offscreen_right;
358                 }
359
360                 ar->draw_buffer->bound_view = -1;
361                 ar->draw_buffer->stereo = stereo;
362         }
363 }
364
365 static void wm_draw_region_bind(ARegion *ar, int view)
366 {
367         if (!ar->draw_buffer) {
368                 return;
369         }
370
371         if (ar->draw_buffer->viewport[view]) {
372                 GPU_viewport_bind(ar->draw_buffer->viewport[view], &ar->winrct);
373         }
374         else {
375                 GPU_offscreen_bind(ar->draw_buffer->offscreen[view], false);
376
377                 /* For now scissor is expected by region drawing, we could disable it
378                  * and do the enable/disable in the specific cases that setup scissor. */
379                 glEnable(GL_SCISSOR_TEST);
380                 glScissor(0, 0, ar->winx, ar->winy);
381         }
382
383         ar->draw_buffer->bound_view = view;
384 }
385
386 static void wm_draw_region_unbind(ARegion *ar, int view)
387 {
388         if (!ar->draw_buffer) {
389                 return;
390         }
391
392         ar->draw_buffer->bound_view = -1;
393
394         if (ar->draw_buffer->viewport[view]) {
395                 GPU_viewport_unbind(ar->draw_buffer->viewport[view]);
396         }
397         else {
398                 glDisable(GL_SCISSOR_TEST);
399                 GPU_offscreen_unbind(ar->draw_buffer->offscreen[view], false);
400         }
401 }
402
403 static void wm_draw_region_blit(ARegion *ar, int view)
404 {
405         if (!ar->draw_buffer) {
406                 return;
407         }
408
409         if (ar->draw_buffer->viewport[view]) {
410                 GPU_viewport_draw_to_screen(ar->draw_buffer->viewport[view], &ar->winrct);
411         }
412         else {
413                 GPU_offscreen_draw_to_screen(ar->draw_buffer->offscreen[view], ar->winrct.xmin, ar->winrct.ymin);
414         }
415 }
416
417 GPUTexture *wm_draw_region_texture(ARegion *ar, int view)
418 {
419         if (!ar->draw_buffer) {
420                 return NULL;
421         }
422
423         if (ar->draw_buffer->viewport[view]) {
424                 return GPU_viewport_color_texture(ar->draw_buffer->viewport[view]);
425         }
426         else {
427                 return GPU_offscreen_color_texture(ar->draw_buffer->offscreen[view]);
428         }
429 }
430
431 void wm_draw_region_blend(ARegion *ar, int view, bool blend)
432 {
433         if (!ar->draw_buffer) {
434                 return;
435         }
436
437         /* Alpha is always 1, except when blend timer is running. */
438         float alpha = ED_region_blend_alpha(ar);
439         if (alpha <= 0.0f) {
440                 return;
441         }
442
443         if (!blend) {
444                 alpha = 1.0f;
445         }
446
447         /* setup actual texture */
448         GPUTexture *texture = wm_draw_region_texture(ar, view);
449         glActiveTexture(GL_TEXTURE0);
450         glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
451
452         /* wmOrtho for the screen has this same offset */
453         const float halfx = GLA_PIXEL_OFS / (BLI_rcti_size_x(&ar->winrct) + 1);
454         const float halfy = GLA_PIXEL_OFS / (BLI_rcti_size_y(&ar->winrct) + 1);
455
456         if (blend) {
457                 /* GL_ONE because regions drawn offscreen have premultiplied alpha. */
458                 glEnable(GL_BLEND);
459                 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
460         }
461
462         GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
463         GPU_shader_bind(shader);
464
465         rcti rect_geo = ar->winrct;
466         rect_geo.xmax += 1;
467         rect_geo.ymax += 1;
468
469         rctf rect_tex;
470         rect_tex.xmin = halfx;
471         rect_tex.ymin = halfy;
472         rect_tex.xmax = 1.0f + halfx;
473         rect_tex.ymax = 1.0f + halfy;
474
475         float alpha_easing = 1.0f - alpha;
476         alpha_easing = 1.0f - alpha_easing * alpha_easing;
477
478         /* Slide vertical panels */
479         float ofs_x = BLI_rcti_size_x(&ar->winrct) * (1.0f - alpha_easing);
480         if (ar->alignment == RGN_ALIGN_RIGHT) {
481                 rect_geo.xmin += ofs_x;
482                 rect_tex.xmax *= alpha_easing;
483                 alpha = 1.0f;
484         }
485         else if (ar->alignment == RGN_ALIGN_LEFT) {
486                 rect_geo.xmax -= ofs_x;
487                 rect_tex.xmin += 1.0f - alpha_easing;
488                 alpha = 1.0f;
489         }
490
491         glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
492         glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), rect_tex.xmin, rect_tex.ymin, rect_tex.xmax, rect_tex.ymax);
493         glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), rect_geo.xmin, rect_geo.ymin, rect_geo.xmax, rect_geo.ymax);
494         glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
495
496         GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
497
498         glBindTexture(GL_TEXTURE_2D, 0);
499
500         if (blend) {
501                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
502                 glDisable(GL_BLEND);
503         }
504 }
505
506 GPUViewport *WM_draw_region_get_viewport(ARegion *ar, int view)
507 {
508         if (!ar->draw_buffer) {
509                 return NULL;
510         }
511
512         return ar->draw_buffer->viewport[view];
513 }
514
515 GPUViewport *WM_draw_region_get_bound_viewport(ARegion *ar)
516 {
517         if (!ar->draw_buffer || ar->draw_buffer->bound_view == -1) {
518                 return NULL;
519         }
520
521         int view = ar->draw_buffer->bound_view;
522         return ar->draw_buffer->viewport[view];
523 }
524
525 static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
526 {
527         Main *bmain = CTX_data_main(C);
528         wmWindowManager *wm = CTX_wm_manager(C);
529         bScreen *screen = WM_window_get_active_screen(win);
530
531         /* Draw screen areas into own frame buffer. */
532         ED_screen_areas_iter(win, screen, sa) {
533                 CTX_wm_area_set(C, sa);
534
535                 /* Compute UI layouts for dynamically size regions. */
536                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
537                         if (ar->visible && ar->do_draw && ar->type && ar->type->layout) {
538                                 CTX_wm_region_set(C, ar);
539                                 ED_region_do_layout(C, ar);
540                                 CTX_wm_region_set(C, NULL);
541                         }
542                 }
543
544                 ED_area_update_region_sizes(wm, win, sa);
545
546                 if (sa->flag & AREA_FLAG_ACTIVE_TOOL_UPDATE) {
547                         if ((1 << sa->spacetype) & WM_TOOLSYSTEM_SPACE_MASK) {
548                                 WM_toolsystem_update_from_context(C, CTX_wm_workspace(C), CTX_data_view_layer(C), sa);
549                         }
550                         sa->flag &= ~AREA_FLAG_ACTIVE_TOOL_UPDATE;
551                 }
552
553                 /* Then do actual drawing of regions. */
554                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
555                         if (ar->visible && ar->do_draw) {
556                                 CTX_wm_region_set(C, ar);
557                                 bool use_viewport = wm_region_use_viewport(sa, ar);
558
559                                 if (stereo && wm_draw_region_stereo_set(bmain, sa, ar, STEREO_LEFT_ID)) {
560                                         wm_draw_region_buffer_create(ar, true, use_viewport);
561
562                                         for (int view = 0; view < 2; view++) {
563                                                 eStereoViews sview;
564                                                 if (view == 0) {
565                                                         sview = STEREO_LEFT_ID;
566                                                 }
567                                                 else {
568                                                         sview = STEREO_RIGHT_ID;
569                                                         wm_draw_region_stereo_set(bmain, sa, ar, sview);
570                                                 }
571
572                                                 wm_draw_region_bind(ar, view);
573                                                 ED_region_do_draw(C, ar);
574                                                 wm_draw_region_unbind(ar, view);
575                                         }
576                                 }
577                                 else {
578                                         wm_draw_region_buffer_create(ar, false, use_viewport);
579                                         wm_draw_region_bind(ar, 0);
580                                         ED_region_do_draw(C, ar);
581                                         wm_draw_region_unbind(ar, 0);
582                                 }
583
584                                 ar->do_draw = false;
585                                 CTX_wm_region_set(C, NULL);
586                         }
587                 }
588
589                 wm_area_mark_invalid_backbuf(sa);
590                 CTX_wm_area_set(C, NULL);
591         }
592
593         /* Draw menus into their own framebuffer. */
594         for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
595                 if (ar->visible) {
596                         CTX_wm_menu_set(C, ar);
597
598                         if (ar->type && ar->type->layout) {
599                                 /* UI code reads the OpenGL state, but we have to refresh
600                                  * the UI layout beforehand in case the menu size changes. */
601                                 wmViewport(&ar->winrct);
602                                 ar->type->layout(C, ar);
603                         }
604
605                         wm_draw_region_buffer_create(ar, false, false);
606                         wm_draw_region_bind(ar, 0);
607                         glClearColor(0, 0, 0, 0);
608                         glClear(GL_COLOR_BUFFER_BIT);
609                         ED_region_do_draw(C, ar);
610                         wm_draw_region_unbind(ar, 0);
611
612                         ar->do_draw = false;
613                         CTX_wm_menu_set(C, NULL);
614                 }
615         }
616 }
617
618 static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
619 {
620         wmWindowManager *wm = CTX_wm_manager(C);
621         bScreen *screen = WM_window_get_active_screen(win);
622
623         /* Draw into the window framebuffer, in full window coordinates. */
624         wmWindowViewport(win);
625
626         /* We draw on all pixels of the windows so we don't need to clear them before.
627          * Actually this is only a problem when resizing the window.
628          * If it becomes a problem we should clear only when window size changes. */
629 #if 0
630         glClearColor(0, 0, 0, 0);
631         glClear(GL_COLOR_BUFFER_BIT);
632 #endif
633
634         /* Blit non-overlapping area regions. */
635         ED_screen_areas_iter(win, screen, sa) {
636                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
637                         if (ar->visible && ar->overlap == false) {
638                                 if (view == -1 && ar->draw_buffer && ar->draw_buffer->stereo) {
639                                         /* Stereo drawing from textures. */
640                                         if (win->stereo3d_format->display_mode == S3D_DISPLAY_ANAGLYPH) {
641                                                 wm_stereo3d_draw_anaglyph(win, ar);
642                                         }
643                                         else {
644                                                 wm_stereo3d_draw_interlace(win, ar);
645                                         }
646                                 }
647                                 else {
648                                         /* Blit from offscreen buffer. */
649                                         wm_draw_region_blit(ar, 0);
650                                 }
651                         }
652                 }
653         }
654
655         /* Draw paint cursors. */
656         if (wm->paintcursors.first) {
657                 ED_screen_areas_iter(win, screen, sa) {
658                         for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
659                                 if (ar->visible && ar == screen->active_region) {
660                                         CTX_wm_area_set(C, sa);
661                                         CTX_wm_region_set(C, ar);
662
663                                         /* make region ready for draw, scissor, pixelspace */
664                                         wm_paintcursor_draw(C, sa, ar);
665
666                                         CTX_wm_region_set(C, NULL);
667                                         CTX_wm_area_set(C, NULL);
668                                 }
669                         }
670                 }
671
672                 wmWindowViewport(win);
673         }
674
675         /* Blend in overlapping area regions */
676         ED_screen_areas_iter(win, screen, sa) {
677                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
678                         if (ar->visible && ar->overlap) {
679                                 wm_draw_region_blend(ar, 0, true);
680                         }
681                 }
682         }
683
684         /* After area regions so we can do area 'overlay' drawing. */
685         ED_screen_draw_edges(win);
686         wm_draw_callbacks(win);
687
688         /* Blend in floating regions (menus). */
689         for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
690                 if (ar->visible) {
691                         wm_draw_region_blend(ar, 0, true);
692                 }
693         }
694
695         /* always draw, not only when screen tagged */
696         if (win->gesture.first)
697                 wm_gesture_draw(win);
698
699         /* needs pixel coords in screen */
700         if (wm->drags.first) {
701                 wm_drags_draw(C, win, NULL);
702         }
703 }
704
705 static void wm_draw_window(bContext *C, wmWindow *win)
706 {
707         bScreen *screen = WM_window_get_active_screen(win);
708         bool stereo = WM_stereo3d_enabled(win, false);
709
710         /* Draw area regions into their own framebuffer. This way we can redraw
711          * the areas that need it, and blit the rest from existing framebuffers. */
712         wm_draw_window_offscreen(C, win, stereo);
713
714         /* Now we draw into the window framebuffer, in full window coordinates. */
715         if (!stereo) {
716                 /* Regular mono drawing. */
717                 wm_draw_window_onscreen(C, win, -1);
718         }
719         else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
720                 /* For pageflip we simply draw to both back buffers. */
721                 glDrawBuffer(GL_BACK_LEFT);
722                 wm_draw_window_onscreen(C, win, 0);
723                 glDrawBuffer(GL_BACK_RIGHT);
724                 wm_draw_window_onscreen(C, win, 1);
725                 glDrawBuffer(GL_BACK);
726         }
727         else if (ELEM(win->stereo3d_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) {
728                 /* For anaglyph and interlace, we draw individual regions with
729                  * stereo framebuffers using different shaders. */
730                 wm_draw_window_onscreen(C, win, -1);
731         }
732         else {
733                 /* For side-by-side and top-bottom, we need to render each view to an
734                  * an offscreen texture and then draw it. This used to happen for all
735                  * stereo methods, but it's less efficient than drawing directly. */
736                 const int width = WM_window_pixels_x(win);
737                 const int height = WM_window_pixels_y(win);
738                 GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL);
739
740                 if (offscreen) {
741                         GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
742                         wm_draw_offscreen_texture_parameters(offscreen);
743
744                         for (int view = 0; view < 2; view++) {
745                                 /* Draw view into offscreen buffer. */
746                                 GPU_offscreen_bind(offscreen, false);
747                                 wm_draw_window_onscreen(C, win, view);
748                                 GPU_offscreen_unbind(offscreen, false);
749
750                                 /* Draw offscreen buffer to screen. */
751                                 glActiveTexture(GL_TEXTURE0);
752                                 glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
753
754                                 if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) {
755                                         wm_stereo3d_draw_sidebyside(win, view);
756                                 }
757                                 else {
758                                         wm_stereo3d_draw_topbottom(win, view);
759                                 }
760
761                                 glBindTexture(GL_TEXTURE_2D, 0);
762                         }
763
764                         GPU_offscreen_free(offscreen);
765                 }
766                 else {
767                         /* Still draw something in case of allocation failure. */
768                         wm_draw_window_onscreen(C, win, 0);
769                 }
770         }
771
772         screen->do_draw = false;
773 }
774
775 /****************** main update call **********************/
776
777 /* quick test to prevent changing window drawable */
778 static bool wm_draw_update_test_window(wmWindow *win)
779 {
780         Scene *scene = WM_window_get_active_scene(win);
781         ViewLayer *view_layer = WM_window_get_active_view_layer(win);
782         struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
783         bScreen *screen = WM_window_get_active_screen(win);
784         ARegion *ar;
785         bool do_draw = false;
786
787         for (ar = screen->regionbase.first; ar; ar = ar->next) {
788                 if (ar->do_draw_overlay) {
789                         screen->do_draw_paintcursor = true;
790                         ar->do_draw_overlay = false;
791                 }
792                 if (ar->visible && ar->do_draw)
793                         do_draw = true;
794         }
795
796         ED_screen_areas_iter(win, screen, sa) {
797                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
798                         wm_region_test_render_do_draw(scene, depsgraph, sa, ar);
799
800                         if (ar->visible && ar->do_draw)
801                                 do_draw = true;
802                 }
803         }
804
805         if (do_draw)
806                 return true;
807
808         if (screen->do_refresh)
809                 return true;
810         if (screen->do_draw)
811                 return true;
812         if (screen->do_draw_gesture)
813                 return true;
814         if (screen->do_draw_paintcursor)
815                 return true;
816         if (screen->do_draw_drag)
817                 return true;
818
819         return false;
820 }
821
822 void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *UNUSED(ar))
823 {
824         if (win) {
825                 bScreen *screen = WM_window_get_active_screen(win);
826                 screen->do_draw_paintcursor = true;
827         }
828 }
829
830 void wm_draw_update(bContext *C)
831 {
832         Main *bmain = CTX_data_main(C);
833         wmWindowManager *wm = CTX_wm_manager(C);
834         wmWindow *win;
835
836 #ifdef WITH_OPENSUBDIV
837         BKE_subsurf_free_unused_buffers();
838 #endif
839
840         GPU_free_unused_buffers(bmain);
841
842         for (win = wm->windows.first; win; win = win->next) {
843 #ifdef WIN32
844                 GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
845
846                 if (state == GHOST_kWindowStateMinimized) {
847                         /* do not update minimized windows, gives issues on Intel (see T33223)
848                          * and AMD (see T50856). it seems logical to skip update for invisible
849                          * window anyway.
850                          */
851                         continue;
852                 }
853 #endif
854
855                 if (wm_draw_update_test_window(win)) {
856                         bScreen *screen = WM_window_get_active_screen(win);
857
858                         CTX_wm_window_set(C, win);
859
860                         /* sets context window+screen */
861                         wm_window_make_drawable(wm, win);
862
863                         /* notifiers for screen redraw */
864                         ED_screen_ensure_updated(wm, win, screen);
865
866                         wm_draw_window(C, win);
867
868                         screen->do_draw_gesture = false;
869                         screen->do_draw_paintcursor = false;
870                         screen->do_draw_drag = false;
871
872                         wm_window_swap_buffers(win);
873
874                         CTX_wm_window_set(C, NULL);
875                 }
876         }
877 }
878
879 void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(ar))
880 {
881         bScreen *screen = WM_window_get_active_screen(win);
882         screen->do_draw = true;
883 }
884
885 void WM_draw_region_free(ARegion *ar)
886 {
887         wm_draw_region_buffer_free(ar);
888         ar->visible = 0;
889 }
890
891 void WM_redraw_windows(bContext *C)
892 {
893         wmWindow *win_prev = CTX_wm_window(C);
894         ScrArea *area_prev = CTX_wm_area(C);
895         ARegion *ar_prev = CTX_wm_region(C);
896
897         wm_draw_update(C);
898
899         CTX_wm_window_set(C, win_prev);
900         CTX_wm_area_set(C, area_prev);
901         CTX_wm_region_set(C, ar_prev);
902 }