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