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