b76fc0abfa71e6b73b80bd9f8d1250f6136365eb
[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                                 glEnable(GL_SCISSOR_TEST);
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                                 glDisable(GL_SCISSOR_TEST);
115                         }
116                 }
117         }
118 }
119
120
121 static bool wm_draw_region_stereo_set(Main *bmain, 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(bmain, 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, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
459
460         GPU_draw_primitive(GPU_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         Main *bmain = CTX_data_main(C);
492         wmWindowManager *wm = CTX_wm_manager(C);
493         bScreen *screen = WM_window_get_active_screen(win);
494
495         /* Draw screen areas into own frame buffer. */
496         ED_screen_areas_iter(win, screen, sa) {
497                 CTX_wm_area_set(C, sa);
498
499                 /* Compute UI layouts for dynamically size regions. */
500                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
501                         if (ar->visible && ar->do_draw && ar->type && ar->type->layout) {
502                                 CTX_wm_region_set(C, ar);
503                                 ED_region_do_layout(C, ar);
504                                 CTX_wm_region_set(C, NULL);
505                         }
506                 }
507
508                 ED_area_update_region_sizes(wm, win, sa);
509
510                 /* Then do actual drawing of regions. */
511                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
512                         if (ar->visible && ar->do_draw) {
513                                 CTX_wm_region_set(C, ar);
514                                 bool use_viewport = wm_region_use_viewport(sa, ar);
515
516                                 if (stereo && wm_draw_region_stereo_set(bmain, sa, ar, STEREO_LEFT_ID)) {
517                                         wm_draw_region_buffer_create(ar, true, use_viewport);
518
519                                         for (int view = 0; view < 2; view++) {
520                                                 eStereoViews sview;
521                                                 if (view == 0) {
522                                                         sview = STEREO_LEFT_ID;
523                                                 }
524                                                 else {
525                                                         sview = STEREO_RIGHT_ID;
526                                                         wm_draw_region_stereo_set(bmain, sa, ar, sview);
527                                                 }
528
529                                                 wm_draw_region_bind(ar, view);
530                                                 ED_region_do_draw(C, ar);
531                                                 wm_draw_region_unbind(ar, view);
532                                         }
533                                 }
534                                 else {
535                                         wm_draw_region_buffer_create(ar, false, use_viewport);
536                                         wm_draw_region_bind(ar, 0);
537                                         ED_region_do_draw(C, ar);
538                                         wm_draw_region_unbind(ar, 0);
539                                 }
540
541                                 ar->do_draw = false;
542                                 CTX_wm_region_set(C, NULL);
543                         }
544                 }
545
546                 wm_area_mark_invalid_backbuf(sa);
547                 CTX_wm_area_set(C, NULL);
548         }
549
550         /* Draw menus into their own framebuffer. */
551         for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
552                 if (ar->visible) {
553                         CTX_wm_menu_set(C, ar);
554
555                         if (ar->type && ar->type->layout) {
556                                 /* UI code reads the OpenGL state, but we have to refresh
557                                  * the UI layout beforehand in case the menu size changes. */
558                                 wmViewport(&ar->winrct);
559                                 ar->type->layout(C, ar);
560                         }
561
562                         wm_draw_region_buffer_create(ar, false, false);
563                         wm_draw_region_bind(ar, 0);
564                         glClearColor(0, 0, 0, 0);
565                         glClear(GL_COLOR_BUFFER_BIT);
566                         ED_region_do_draw(C, ar);
567                         wm_draw_region_unbind(ar, 0);
568
569                         ar->do_draw = false;
570                         CTX_wm_menu_set(C, NULL);
571                 }
572         }
573 }
574
575 static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
576 {
577         wmWindowManager *wm = CTX_wm_manager(C);
578         bScreen *screen = WM_window_get_active_screen(win);
579
580         /* Draw into the window framebuffer, in full window coordinates. */
581         wmWindowViewport(win);
582         glClearColor(0, 0, 0, 0);
583         glClear(GL_COLOR_BUFFER_BIT);
584
585         /* Blit non-overlapping area regions. */
586         ED_screen_areas_iter(win, screen, sa) {
587                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
588                         if (ar->visible && ar->overlap == false) {
589                                 if (view == -1 && ar->draw_buffer && ar->draw_buffer->stereo) {
590                                         /* Stereo drawing from textures. */
591                                         if (win->stereo3d_format->display_mode == S3D_DISPLAY_ANAGLYPH) {
592                                                 wm_stereo3d_draw_anaglyph(win, ar);
593                                         }
594                                         else {
595                                                 wm_stereo3d_draw_interlace(win, ar);
596                                         }
597                                 }
598                                 else {
599                                         /* Blit from offscreen buffer. */
600                                         wm_draw_region_blit(ar, 0);
601                                 }
602                         }
603                 }
604         }
605
606         /* Draw paint cursors. */
607         if (wm->paintcursors.first) {
608                 ED_screen_areas_iter(win, screen, sa) {
609                         for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
610                                 if (ar->visible && ar == screen->active_region) {
611                                         CTX_wm_area_set(C, sa);
612                                         CTX_wm_region_set(C, ar);
613
614                                         /* make region ready for draw, scissor, pixelspace */
615                                         wm_paintcursor_draw(C, ar);
616
617                                         CTX_wm_region_set(C, NULL);
618                                         CTX_wm_area_set(C, NULL);
619                                 }
620                         }
621                 }
622
623                 wmWindowViewport(win);
624         }
625
626         /* Blend in overlapping area regions */
627         ED_screen_areas_iter(win, screen, sa) {
628                 for (ARegion *ar = sa->regionbase.first; ar; ar = ar->next) {
629                         if (ar->visible && ar->overlap) {
630                                 wm_draw_region_blend(ar, 0, true);
631                         }
632                 }
633         }
634
635         /* After area regions so we can do area 'overlay' drawing. */
636         ED_screen_draw_edges(win);
637         wm_draw_callbacks(win);
638
639         /* Blend in floating regions (menus). */
640         for (ARegion *ar = screen->regionbase.first; ar; ar = ar->next) {
641                 if (ar->visible) {
642                         wm_draw_region_blend(ar, 0, true);
643                 }
644         }
645
646         /* always draw, not only when screen tagged */
647         if (win->gesture.first)
648                 wm_gesture_draw(win);
649
650         /* needs pixel coords in screen */
651         if (wm->drags.first) {
652                 wm_drags_draw(C, win, NULL);
653         }
654 }
655
656 static void wm_draw_window(bContext *C, wmWindow *win)
657 {
658         bScreen *screen = WM_window_get_active_screen(win);
659         bool stereo = WM_stereo3d_enabled(win, false);
660
661         /* Draw area regions into their own framebuffer. This way we can redraw
662          * the areas that need it, and blit the rest from existing framebuffers. */
663         wm_draw_window_offscreen(C, win, stereo);
664
665         /* Now we draw into the window framebuffer, in full window coordinates. */
666         if (!stereo) {
667                 /* Regular mono drawing. */
668                 wm_draw_window_onscreen(C, win, -1);
669         }
670         else if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
671                 /* For pageflip we simply draw to both back buffers. */
672                 glDrawBuffer(GL_BACK_LEFT);
673                 wm_draw_window_onscreen(C, win, 0);
674                 glDrawBuffer(GL_BACK_RIGHT);
675                 wm_draw_window_onscreen(C, win, 1);
676                 glDrawBuffer(GL_BACK);
677         }
678         else if (ELEM(win->stereo3d_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) {
679                 /* For anaglyph and interlace, we draw individual regions with
680                  * stereo framebuffers using different shaders. */
681                 wm_draw_window_onscreen(C, win, -1);
682         }
683         else {
684                 /* For side-by-side and top-bottom, we need to render each view to an
685                  * an offscreen texture and then draw it. This used to happen for all
686                  * stereo methods, but it's less efficient than drawing directly. */
687                 const int width = WM_window_pixels_x(win);
688                 const int height = WM_window_pixels_y(win);
689                 GPUOffScreen *offscreen = GPU_offscreen_create(width, height, 0, false, false, NULL);
690
691                 if (offscreen) {
692                         GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
693                         wm_draw_offscreen_texture_parameters(offscreen);
694
695                         for (int view = 0; view < 2; view++) {
696                                 /* Draw view into offscreen buffer. */
697                                 GPU_offscreen_bind(offscreen, false);
698                                 wm_draw_window_onscreen(C, win, view);
699                                 GPU_offscreen_unbind(offscreen, false);
700
701                                 /* Draw offscreen buffer to screen. */
702                                 glActiveTexture(GL_TEXTURE0);
703                                 glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
704
705                                 if (win->stereo3d_format->display_mode == S3D_DISPLAY_SIDEBYSIDE) {
706                                         wm_stereo3d_draw_sidebyside(win, view);
707                                 }
708                                 else {
709                                         wm_stereo3d_draw_topbottom(win, view);
710                                 }
711
712                                 glBindTexture(GL_TEXTURE_2D, 0);
713                         }
714
715                         GPU_offscreen_free(offscreen);
716                 }
717                 else {
718                         /* Still draw something in case of allocation failure. */
719                         wm_draw_window_onscreen(C, win, 0);
720                 }
721         }
722
723         screen->do_draw = false;
724 }
725
726 /****************** main update call **********************/
727
728 /* quick test to prevent changing window drawable */
729 static bool wm_draw_update_test_window(wmWindow *win)
730 {
731         Scene *scene = WM_window_get_active_scene(win);
732         ViewLayer *view_layer = WM_window_get_active_view_layer(win);
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         Main *bmain = CTX_data_main(C);
784         wmWindowManager *wm = CTX_wm_manager(C);
785         wmWindow *win;
786
787 #ifdef WITH_OPENSUBDIV
788         BKE_subsurf_free_unused_buffers();
789 #endif
790
791         GPU_free_unused_buffers(bmain);
792
793         for (win = wm->windows.first; win; win = win->next) {
794 #ifdef WIN32
795                 GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
796
797                 if (state == GHOST_kWindowStateMinimized) {
798                         /* do not update minimized windows, gives issues on Intel (see T33223)
799                          * and AMD (see T50856). it seems logical to skip update for invisible
800                          * window anyway.
801                          */
802                         continue;
803                 }
804 #endif
805
806                 if (wm_draw_update_test_window(win)) {
807                         bScreen *screen = WM_window_get_active_screen(win);
808
809                         CTX_wm_window_set(C, win);
810
811                         /* sets context window+screen */
812                         wm_window_make_drawable(wm, win);
813
814                         /* notifiers for screen redraw */
815                         ED_screen_ensure_updated(wm, win, screen);
816
817                         wm_draw_window(C, win);
818
819                         screen->do_draw_gesture = false;
820                         screen->do_draw_paintcursor = false;
821                         screen->do_draw_drag = false;
822
823                         wm_window_swap_buffers(win);
824
825                         CTX_wm_window_set(C, NULL);
826                 }
827         }
828 }
829
830 void wm_draw_region_clear(wmWindow *win, ARegion *UNUSED(ar))
831 {
832         bScreen *screen = WM_window_get_active_screen(win);
833         screen->do_draw = true;
834 }
835
836 void WM_draw_region_free(ARegion *ar)
837 {
838         wm_draw_region_buffer_free(ar);
839         ar->visible = 0;
840 }
841
842 void WM_redraw_windows(bContext *C)
843 {
844         wmWindow *win_prev = CTX_wm_window(C);
845         ScrArea *area_prev = CTX_wm_area(C);
846         ARegion *ar_prev = CTX_wm_region(C);
847
848         wm_draw_update(C);
849
850         CTX_wm_window_set(C, win_prev);
851         CTX_wm_area_set(C, area_prev);
852         CTX_wm_region_set(C, ar_prev);
853 }