Cleanup: trailing space for windowmanager
[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_screen_types.h"
38 #include "DNA_windowmanager_types.h"
39 #include "DNA_userdef_types.h"
40 #include "DNA_view3d_types.h"
41
42 #include "MEM_guardedalloc.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_utildefines.h"
46
47 #include "BIF_gl.h"
48
49 #include "BKE_context.h"
50 #include "BKE_image.h"
51
52 #include "GHOST_C-api.h"
53
54 #include "ED_node.h"
55 #include "ED_view3d.h"
56 #include "ED_screen.h"
57
58 #include "GPU_draw.h"
59 #include "GPU_extensions.h"
60 #include "GPU_glew.h"
61 #include "GPU_basic_shader.h"
62
63 #include "RE_engine.h"
64
65 #include "WM_api.h"
66 #include "WM_types.h"
67 #include "wm.h"
68 #include "wm_draw.h"
69 #include "wm_window.h"
70 #include "wm_event_system.h"
71
72 #ifdef WITH_OPENSUBDIV
73 #  include "BKE_subsurf.h"
74 #endif
75
76 /* swap */
77 #define WIN_NONE_OK     0
78 #define WIN_BACK_OK     1
79 #define WIN_FRONT_OK    2
80 #define WIN_BOTH_OK     3
81
82 /* ******************* drawing, overlays *************** */
83
84
85 static void wm_paintcursor_draw(bContext *C, ARegion *ar)
86 {
87         wmWindowManager *wm = CTX_wm_manager(C);
88
89         if (wm->paintcursors.first) {
90                 wmWindow *win = CTX_wm_window(C);
91                 bScreen *screen = win->screen;
92                 wmPaintCursor *pc;
93
94                 if (ar->swinid && screen->subwinactive == ar->swinid) {
95                         for (pc = wm->paintcursors.first; pc; pc = pc->next) {
96                                 if (pc->poll == NULL || pc->poll(C)) {
97                                         ARegion *ar_other = CTX_wm_region(C);
98                                         if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) {
99                                                 int x = 0, y = 0;
100                                                 wm_get_cursor_position(win, &x, &y);
101                                                 pc->draw(C,
102                                                          x - ar_other->winrct.xmin,
103                                                          y - ar_other->winrct.ymin,
104                                                          pc->customdata);
105                                         }
106                                         else {
107                                                 pc->draw(C,
108                                                          win->eventstate->x - ar_other->winrct.xmin,
109                                                          win->eventstate->y - ar_other->winrct.ymin,
110                                                          pc->customdata);
111                                         }
112                                 }
113                         }
114                 }
115         }
116 }
117
118 /* ********************* drawing, swap ****************** */
119
120 static void wm_area_mark_invalid_backbuf(ScrArea *sa)
121 {
122         if (sa->spacetype == SPACE_VIEW3D)
123                 ((View3D *)sa->spacedata.first)->flag |= V3D_INVALID_BACKBUF;
124 }
125
126 static bool wm_area_test_invalid_backbuf(ScrArea *sa)
127 {
128         if (sa->spacetype == SPACE_VIEW3D)
129                 return (((View3D *)sa->spacedata.first)->flag & V3D_INVALID_BACKBUF) != 0;
130         else
131                 return true;
132 }
133
134 static void wm_region_test_render_do_draw(const bScreen *screen, ScrArea *sa, ARegion *ar)
135 {
136         /* tag region for redraw from render engine preview running inside of it */
137         if (sa->spacetype == SPACE_VIEW3D) {
138                 RegionView3D *rv3d = ar->regiondata;
139                 RenderEngine *engine = (rv3d) ? rv3d->render_engine : NULL;
140
141                 if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) {
142                         Scene *scene = screen->scene;
143                         View3D *v3d = sa->spacedata.first;
144                         rcti border_rect;
145
146                         /* do partial redraw when possible */
147                         if (ED_view3d_calc_render_border(scene, v3d, ar, &border_rect))
148                                 ED_region_tag_redraw_partial(ar, &border_rect);
149                         else
150                                 ED_region_tag_redraw(ar);
151
152                         engine->flag &= ~RE_ENGINE_DO_DRAW;
153                 }
154         }
155 }
156
157 /********************** draw all **************************/
158 /* - reference method, draw all each time                 */
159
160 typedef struct WindowDrawCB {
161         struct WindowDrawCB *next, *prev;
162
163         void(*draw)(const struct wmWindow *, void *);
164         void *customdata;
165
166 } WindowDrawCB;
167
168 void *WM_draw_cb_activate(
169         wmWindow *win,
170         void(*draw)(const struct wmWindow *, void *),
171         void *customdata)
172 {
173         WindowDrawCB *wdc = MEM_callocN(sizeof(*wdc), "WindowDrawCB");
174
175         BLI_addtail(&win->drawcalls, wdc);
176         wdc->draw = draw;
177         wdc->customdata = customdata;
178
179         return wdc;
180 }
181
182 void WM_draw_cb_exit(wmWindow *win, void *handle)
183 {
184         for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) {
185                 if (wdc == (WindowDrawCB *)handle) {
186                         BLI_remlink(&win->drawcalls, wdc);
187                         MEM_freeN(wdc);
188                         return;
189                 }
190         }
191 }
192
193 static void wm_draw_callbacks(wmWindow *win)
194 {
195         for (WindowDrawCB *wdc = win->drawcalls.first; wdc; wdc = wdc->next) {
196                 wdc->draw(win, wdc->customdata);
197         }
198 }
199
200 static void wm_method_draw_full(bContext *C, wmWindow *win)
201 {
202         bScreen *screen = win->screen;
203         ScrArea *sa;
204         ARegion *ar;
205
206         /* draw area regions */
207         for (sa = screen->areabase.first; sa; sa = sa->next) {
208                 CTX_wm_area_set(C, sa);
209
210                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
211                         if (ar->swinid) {
212                                 CTX_wm_region_set(C, ar);
213                                 ED_region_do_draw(C, ar);
214                                 ar->do_draw = false;
215                                 wm_paintcursor_draw(C, ar);
216                                 CTX_wm_region_set(C, NULL);
217                         }
218                 }
219
220                 wm_area_mark_invalid_backbuf(sa);
221                 CTX_wm_area_set(C, NULL);
222         }
223
224         ED_screen_draw_edges(win);
225         screen->do_draw = false;
226         wm_draw_callbacks(win);
227
228         /* draw overlapping regions */
229         for (ar = screen->regionbase.first; ar; ar = ar->next) {
230                 if (ar->swinid) {
231                         CTX_wm_menu_set(C, ar);
232                         ED_region_do_draw(C, ar);
233                         ar->do_draw = false;
234                         CTX_wm_menu_set(C, NULL);
235                 }
236         }
237
238         if (screen->do_draw_gesture)
239                 wm_gesture_draw(win);
240 }
241
242 /****************** draw overlap all **********************/
243 /* - redraw marked areas, and anything that overlaps it   */
244 /* - it also handles swap exchange optionally, assuming   */
245 /*   that on swap no clearing happens and we get back the */
246 /*   same buffer as we swapped to the front               */
247
248 /* mark area-regions to redraw if overlapped with rect */
249 static void wm_flush_regions_down(bScreen *screen, rcti *dirty)
250 {
251         ScrArea *sa;
252         ARegion *ar;
253
254         for (sa = screen->areabase.first; sa; sa = sa->next) {
255                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
256                         if (BLI_rcti_isect(dirty, &ar->winrct, NULL)) {
257                                 ar->do_draw = RGN_DRAW;
258                                 memset(&ar->drawrct, 0, sizeof(ar->drawrct));
259                                 ar->swap = WIN_NONE_OK;
260                         }
261                 }
262         }
263 }
264
265 /* mark menu-regions to redraw if overlapped with rect */
266 static void wm_flush_regions_up(bScreen *screen, rcti *dirty)
267 {
268         ARegion *ar;
269
270         for (ar = screen->regionbase.first; ar; ar = ar->next) {
271                 if (BLI_rcti_isect(dirty, &ar->winrct, NULL)) {
272                         ar->do_draw = RGN_DRAW;
273                         memset(&ar->drawrct, 0, sizeof(ar->drawrct));
274                         ar->swap = WIN_NONE_OK;
275                 }
276         }
277 }
278
279 static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
280 {
281         wmWindowManager *wm = CTX_wm_manager(C);
282         bScreen *screen = win->screen;
283         ScrArea *sa;
284         ARegion *ar;
285         static rcti rect = {0, 0, 0, 0};
286
287         /* after backbuffer selection draw, we need to redraw */
288         for (sa = screen->areabase.first; sa; sa = sa->next)
289                 for (ar = sa->regionbase.first; ar; ar = ar->next)
290                         if (ar->swinid && !wm_area_test_invalid_backbuf(sa))
291                                 ED_region_tag_redraw(ar);
292
293         /* flush overlapping regions */
294         if (screen->regionbase.first) {
295                 /* flush redraws of area regions up to overlapping regions */
296                 for (sa = screen->areabase.first; sa; sa = sa->next)
297                         for (ar = sa->regionbase.first; ar; ar = ar->next)
298                                 if (ar->swinid && ar->do_draw)
299                                         wm_flush_regions_up(screen, &ar->winrct);
300
301                 /* flush between overlapping regions */
302                 for (ar = screen->regionbase.last; ar; ar = ar->prev)
303                         if (ar->swinid && ar->do_draw)
304                                 wm_flush_regions_up(screen, &ar->winrct);
305
306                 /* flush redraws of overlapping regions down to area regions */
307                 for (ar = screen->regionbase.last; ar; ar = ar->prev)
308                         if (ar->swinid && ar->do_draw)
309                                 wm_flush_regions_down(screen, &ar->winrct);
310         }
311
312         /* flush drag item */
313         if (rect.xmin != rect.xmax) {
314                 wm_flush_regions_down(screen, &rect);
315                 rect.xmin = rect.xmax = 0;
316         }
317         if (wm->drags.first) {
318                 /* doesnt draw, fills rect with boundbox */
319                 wm_drags_draw(C, win, &rect);
320         }
321
322         /* draw marked area regions */
323         for (sa = screen->areabase.first; sa; sa = sa->next) {
324                 CTX_wm_area_set(C, sa);
325
326                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
327                         if (ar->swinid) {
328                                 if (ar->do_draw) {
329                                         CTX_wm_region_set(C, ar);
330                                         ED_region_do_draw(C, ar);
331                                         ar->do_draw = false;
332                                         wm_paintcursor_draw(C, ar);
333                                         CTX_wm_region_set(C, NULL);
334
335                                         if (exchange)
336                                                 ar->swap = WIN_FRONT_OK;
337                                 }
338                                 else if (exchange) {
339                                         if (ar->swap == WIN_FRONT_OK) {
340                                                 CTX_wm_region_set(C, ar);
341                                                 ED_region_do_draw(C, ar);
342                                                 ar->do_draw = false;
343                                                 wm_paintcursor_draw(C, ar);
344                                                 CTX_wm_region_set(C, NULL);
345
346                                                 ar->swap = WIN_BOTH_OK;
347                                         }
348                                         else if (ar->swap == WIN_BACK_OK)
349                                                 ar->swap = WIN_FRONT_OK;
350                                         else if (ar->swap == WIN_BOTH_OK)
351                                                 ar->swap = WIN_BOTH_OK;
352                                 }
353                         }
354                 }
355
356                 wm_area_mark_invalid_backbuf(sa);
357                 CTX_wm_area_set(C, NULL);
358         }
359
360         /* after area regions so we can do area 'overlay' drawing */
361         if (screen->do_draw) {
362                 ED_screen_draw_edges(win);
363                 screen->do_draw = false;
364                 wm_draw_callbacks(win);
365
366                 if (exchange)
367                         screen->swap = WIN_FRONT_OK;
368         }
369         else if (exchange) {
370                 if (screen->swap == WIN_FRONT_OK) {
371                         ED_screen_draw_edges(win);
372                         screen->do_draw = false;
373                         screen->swap = WIN_BOTH_OK;
374                         wm_draw_callbacks(win);
375                 }
376                 else if (screen->swap == WIN_BACK_OK)
377                         screen->swap = WIN_FRONT_OK;
378                 else if (screen->swap == WIN_BOTH_OK)
379                         screen->swap = WIN_BOTH_OK;
380         }
381
382         /* draw marked overlapping regions */
383         for (ar = screen->regionbase.first; ar; ar = ar->next) {
384                 if (ar->swinid && ar->do_draw) {
385                         CTX_wm_menu_set(C, ar);
386                         ED_region_do_draw(C, ar);
387                         ar->do_draw = false;
388                         CTX_wm_menu_set(C, NULL);
389                 }
390         }
391
392         if (screen->do_draw_gesture)
393                 wm_gesture_draw(win);
394
395         /* needs pixel coords in screen */
396         if (wm->drags.first) {
397                 wm_drags_draw(C, win, NULL);
398         }
399 }
400
401 /****************** draw triple buffer ********************/
402 /* - area regions are written into a texture, without any */
403 /*   of the overlapping menus, brushes, gestures. these   */
404 /*   are redrawn each time.                               */
405
406 static void wm_draw_triple_free(wmDrawTriple *triple)
407 {
408         if (triple) {
409                 glDeleteTextures(1, &triple->bind);
410                 MEM_freeN(triple);
411         }
412 }
413
414 static void wm_draw_triple_fail(bContext *C, wmWindow *win)
415 {
416         wm_draw_window_clear(win);
417
418         win->drawfail = 1;
419         wm_method_draw_overlap_all(C, win, 0);
420 }
421
422 static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
423 {
424         const int winsize_x = WM_window_pixels_x(win);
425         const int winsize_y = WM_window_pixels_y(win);
426
427         GLint maxsize;
428
429         /* compute texture sizes */
430         if (GLEW_ARB_texture_rectangle || GLEW_NV_texture_rectangle || GLEW_EXT_texture_rectangle) {
431                 triple->target = GL_TEXTURE_RECTANGLE_ARB;
432         }
433         else {
434                 triple->target = GL_TEXTURE_2D;
435         }
436
437         triple->x = winsize_x;
438         triple->y = winsize_y;
439
440         /* generate texture names */
441         glGenTextures(1, &triple->bind);
442
443         if (!triple->bind) {
444                 /* not the typical failure case but we handle it anyway */
445                 printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
446                 return 0;
447         }
448
449         /* proxy texture is only guaranteed to test for the cases that
450          * there is only one texture in use, which may not be the case */
451         maxsize = GPU_max_texture_size();
452
453         if (triple->x > maxsize || triple->y > maxsize) {
454                 glBindTexture(triple->target, 0);
455                 printf("WM: failed to allocate texture for triple buffer drawing "
456                            "(texture too large for graphics card).\n");
457                 return 0;
458         }
459
460         /* setup actual texture */
461         glBindTexture(triple->target, triple->bind);
462         glTexImage2D(triple->target, 0, GL_RGB8, triple->x, triple->y, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
463         glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
464         glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
465         glBindTexture(triple->target, 0);
466
467         /* not sure if this works everywhere .. */
468         if (glGetError() == GL_OUT_OF_MEMORY) {
469                 printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
470                 return 0;
471         }
472
473         return 1;
474 }
475
476 void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha, bool is_interlace)
477 {
478         const int sizex = WM_window_pixels_x(win);
479         const int sizey = WM_window_pixels_y(win);
480
481         float halfx, halfy, ratiox, ratioy;
482
483         /* wmOrtho for the screen has this same offset */
484         ratiox = sizex;
485         ratioy = sizey;
486         halfx = GLA_PIXEL_OFS;
487         halfy = GLA_PIXEL_OFS;
488
489         /* texture rectangle has unnormalized coordinates */
490         if (triple->target == GL_TEXTURE_2D) {
491                 ratiox /= triple->x;
492                 ratioy /= triple->y;
493                 halfx /= triple->x;
494                 halfy /= triple->y;
495         }
496
497         /* interlace stereo buffer bind the shader before calling wm_triple_draw_textures */
498         if (is_interlace) {
499                 glEnable(triple->target);
500         }
501         else {
502                 GPU_basic_shader_bind((triple->target == GL_TEXTURE_2D) ? GPU_SHADER_TEXTURE_2D : GPU_SHADER_TEXTURE_RECT);
503         }
504
505         glBindTexture(triple->target, triple->bind);
506
507         glColor4f(1.0f, 1.0f, 1.0f, alpha);
508         glBegin(GL_QUADS);
509         glTexCoord2f(halfx, halfy);
510         glVertex2f(0, 0);
511
512         glTexCoord2f(ratiox + halfx, halfy);
513         glVertex2f(sizex, 0);
514
515         glTexCoord2f(ratiox + halfx, ratioy + halfy);
516         glVertex2f(sizex, sizey);
517
518         glTexCoord2f(halfx, ratioy + halfy);
519         glVertex2f(0, sizey);
520         glEnd();
521
522         glBindTexture(triple->target, 0);
523
524         if (is_interlace) {
525                 glDisable(triple->target);
526         }
527         else {
528                 GPU_basic_shader_bind(GPU_SHADER_USE_COLOR);
529         }
530 }
531
532 static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
533 {
534         const int sizex = WM_window_pixels_x(win);
535         const int sizey = WM_window_pixels_y(win);
536
537         glBindTexture(triple->target, triple->bind);
538         glCopyTexSubImage2D(triple->target, 0, 0, 0, 0, 0, sizex, sizey);
539
540         glBindTexture(triple->target, 0);
541 }
542
543 static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *triple)
544 {
545         float fac = ED_region_blend_factor(ar);
546
547         /* region blend always is 1, except when blend timer is running */
548         if (fac < 1.0f) {
549                 wmSubWindowScissorSet(win, win->screen->mainwin, &ar->winrct, true);
550
551                 glEnable(GL_BLEND);
552                 wm_triple_draw_textures(win, triple, 1.0f - fac, false);
553                 glDisable(GL_BLEND);
554         }
555 }
556
557 static void wm_method_draw_triple(bContext *C, wmWindow *win)
558 {
559         wmWindowManager *wm = CTX_wm_manager(C);
560         wmDrawData *dd, *dd_next, *drawdata = win->drawdata.first;
561         bScreen *screen = win->screen;
562         ScrArea *sa;
563         ARegion *ar;
564         int copytex = false;
565
566         if (drawdata && drawdata->triple) {
567                 glClearColor(0, 0, 0, 0);
568                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
569
570                 wmSubWindowSet(win, screen->mainwin);
571
572                 wm_triple_draw_textures(win, drawdata->triple, 1.0f, false);
573         }
574         else {
575                 /* we run it when we start OR when we turn stereo on */
576                 if (drawdata == NULL) {
577                         drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData");
578                         BLI_addhead(&win->drawdata, drawdata);
579                 }
580
581                 drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
582
583                 if (!wm_triple_gen_textures(win, drawdata->triple)) {
584                         wm_draw_triple_fail(C, win);
585                         return;
586                 }
587         }
588
589         /* it means stereo was just turned off */
590         /* note: we are removing all drawdatas that are not the first */
591         for (dd = drawdata->next; dd; dd = dd_next) {
592                 dd_next = dd->next;
593
594                 BLI_remlink(&win->drawdata, dd);
595                 wm_draw_triple_free(dd->triple);
596                 MEM_freeN(dd);
597         }
598
599         wmDrawTriple *triple = drawdata->triple;
600
601         /* draw marked area regions */
602         for (sa = screen->areabase.first; sa; sa = sa->next) {
603                 CTX_wm_area_set(C, sa);
604
605                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
606                         if (ar->swinid && ar->do_draw) {
607                                 if (ar->overlap == false) {
608                                         CTX_wm_region_set(C, ar);
609                                         ED_region_do_draw(C, ar);
610                                         ar->do_draw = false;
611                                         CTX_wm_region_set(C, NULL);
612                                         copytex = true;
613                                 }
614                         }
615                 }
616
617                 wm_area_mark_invalid_backbuf(sa);
618                 CTX_wm_area_set(C, NULL);
619         }
620
621         if (copytex) {
622                 wmSubWindowSet(win, screen->mainwin);
623
624                 wm_triple_copy_textures(win, triple);
625         }
626
627         if (wm->paintcursors.first) {
628                 for (sa = screen->areabase.first; sa; sa = sa->next) {
629                         for (ar = sa->regionbase.first; ar; ar = ar->next) {
630                                 if (ar->swinid && ar->swinid == screen->subwinactive) {
631                                         CTX_wm_area_set(C, sa);
632                                         CTX_wm_region_set(C, ar);
633
634                                         /* make region ready for draw, scissor, pixelspace */
635                                         ED_region_set(C, ar);
636                                         wm_paintcursor_draw(C, ar);
637
638                                         CTX_wm_region_set(C, NULL);
639                                         CTX_wm_area_set(C, NULL);
640                                 }
641                         }
642                 }
643
644                 wmSubWindowSet(win, screen->mainwin);
645         }
646
647         /* draw overlapping area regions (always like popups) */
648         for (sa = screen->areabase.first; sa; sa = sa->next) {
649                 CTX_wm_area_set(C, sa);
650
651                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
652                         if (ar->swinid && ar->overlap) {
653                                 CTX_wm_region_set(C, ar);
654                                 ED_region_do_draw(C, ar);
655                                 ar->do_draw = false;
656                                 CTX_wm_region_set(C, NULL);
657
658                                 wm_draw_region_blend(win, ar, triple);
659                         }
660                 }
661
662                 CTX_wm_area_set(C, NULL);
663         }
664
665         /* after area regions so we can do area 'overlay' drawing */
666         ED_screen_draw_edges(win);
667         win->screen->do_draw = false;
668         wm_draw_callbacks(win);
669
670         /* draw floating regions (menus) */
671         for (ar = screen->regionbase.first; ar; ar = ar->next) {
672                 if (ar->swinid) {
673                         CTX_wm_menu_set(C, ar);
674                         ED_region_do_draw(C, ar);
675                         ar->do_draw = false;
676                         CTX_wm_menu_set(C, NULL);
677                 }
678         }
679
680         /* always draw, not only when screen tagged */
681         if (win->gesture.first)
682                 wm_gesture_draw(win);
683
684         /* needs pixel coords in screen */
685         if (wm->drags.first) {
686                 wm_drags_draw(C, win, NULL);
687         }
688 }
689
690 static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, eStereoViews sview)
691 {
692         wmWindowManager *wm = CTX_wm_manager(C);
693         wmDrawData *drawdata;
694         wmDrawTriple *triple_data, *triple_all;
695         bScreen *screen = win->screen;
696         ScrArea *sa;
697         ARegion *ar;
698         int copytex = false;
699         int id;
700
701         /* we store the triple_data in sequence to triple_all */
702         for (id = 0; id < 2; id++) {
703                 drawdata = BLI_findlink(&win->drawdata, (sview * 2) + id);
704
705                 if (drawdata && drawdata->triple) {
706                         if (id == 0) {
707                                 glClearColor(0, 0, 0, 0);
708                                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
709
710                                 wmSubWindowSet(win, screen->mainwin);
711
712                                 wm_triple_draw_textures(win, drawdata->triple, 1.0f, false);
713                         }
714                 }
715                 else {
716                         /* we run it when we start OR when we turn stereo on */
717                         if (drawdata == NULL) {
718                                 drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData");
719                                 BLI_addtail(&win->drawdata, drawdata);
720                         }
721
722                         drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
723
724                         if (!wm_triple_gen_textures(win, drawdata->triple)) {
725                                 wm_draw_triple_fail(C, win);
726                                 return;
727                         }
728                 }
729         }
730
731         triple_data = ((wmDrawData *) BLI_findlink(&win->drawdata, sview * 2))->triple;
732         triple_all  = ((wmDrawData *) BLI_findlink(&win->drawdata, (sview * 2) + 1))->triple;
733
734         /* draw marked area regions */
735         for (sa = screen->areabase.first; sa; sa = sa->next) {
736                 CTX_wm_area_set(C, sa);
737
738                 switch (sa->spacetype) {
739                         case SPACE_IMAGE:
740                         {
741                                 SpaceImage *sima = sa->spacedata.first;
742                                 sima->iuser.multiview_eye = sview;
743                                 break;
744                         }
745                         case SPACE_VIEW3D:
746                         {
747                                 View3D *v3d = sa->spacedata.first;
748                                 BGpic *bgpic = v3d->bgpicbase.first;
749                                 v3d->multiview_eye = sview;
750                                 if (bgpic) bgpic->iuser.multiview_eye = sview;
751                                 break;
752                         }
753                         case SPACE_NODE:
754                         {
755                                 SpaceNode *snode = sa->spacedata.first;
756                                 if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
757                                         Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
758                                         ima->eye = sview;
759                                 }
760                                 break;
761                         }
762                         case SPACE_SEQ:
763                         {
764                                 SpaceSeq *sseq = sa->spacedata.first;
765                                 sseq->multiview_eye = sview;
766                                 break;
767                         }
768                 }
769
770                 /* draw marked area regions */
771                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
772                         if (ar->swinid && ar->do_draw) {
773
774                                 if (ar->overlap == false) {
775                                         CTX_wm_region_set(C, ar);
776                                         ED_region_do_draw(C, ar);
777
778                                         if (sview == STEREO_RIGHT_ID)
779                                                 ar->do_draw = false;
780
781                                         CTX_wm_region_set(C, NULL);
782                                         copytex = true;
783                                 }
784                         }
785                 }
786
787                 wm_area_mark_invalid_backbuf(sa);
788                 CTX_wm_area_set(C, NULL);
789         }
790
791         if (copytex) {
792                 wmSubWindowSet(win, screen->mainwin);
793
794                 wm_triple_copy_textures(win, triple_data);
795         }
796
797         if (wm->paintcursors.first) {
798                 for (sa = screen->areabase.first; sa; sa = sa->next) {
799                         for (ar = sa->regionbase.first; ar; ar = ar->next) {
800                                 if (ar->swinid && ar->swinid == screen->subwinactive) {
801                                         CTX_wm_area_set(C, sa);
802                                         CTX_wm_region_set(C, ar);
803
804                                         /* make region ready for draw, scissor, pixelspace */
805                                         ED_region_set(C, ar);
806                                         wm_paintcursor_draw(C, ar);
807
808                                         CTX_wm_region_set(C, NULL);
809                                         CTX_wm_area_set(C, NULL);
810                                 }
811                         }
812                 }
813
814                 wmSubWindowSet(win, screen->mainwin);
815         }
816
817         /* draw overlapping area regions (always like popups) */
818         for (sa = screen->areabase.first; sa; sa = sa->next) {
819                 CTX_wm_area_set(C, sa);
820
821                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
822                         if (ar->swinid && ar->overlap) {
823                                 CTX_wm_region_set(C, ar);
824                                 ED_region_do_draw(C, ar);
825                                 if (sview == STEREO_RIGHT_ID)
826                                         ar->do_draw = false;
827                                 CTX_wm_region_set(C, NULL);
828
829                                 wm_draw_region_blend(win, ar, triple_data);
830                         }
831                 }
832
833                 CTX_wm_area_set(C, NULL);
834         }
835
836         /* after area regions so we can do area 'overlay' drawing */
837         ED_screen_draw_edges(win);
838         if (sview == STEREO_RIGHT_ID)
839                 win->screen->do_draw = false;
840         wm_draw_callbacks(win);
841
842         /* draw floating regions (menus) */
843         for (ar = screen->regionbase.first; ar; ar = ar->next) {
844                 if (ar->swinid) {
845                         CTX_wm_menu_set(C, ar);
846                         ED_region_do_draw(C, ar);
847                         if (sview == STEREO_RIGHT_ID)
848                                 ar->do_draw = false;
849                         CTX_wm_menu_set(C, NULL);
850                 }
851         }
852
853         /* always draw, not only when screen tagged */
854         if (win->gesture.first)
855                 wm_gesture_draw(win);
856
857         /* needs pixel coords in screen */
858         if (wm->drags.first) {
859                 wm_drags_draw(C, win, NULL);
860         }
861
862         /* copy the ui + overlays */
863         wmSubWindowSet(win, screen->mainwin);
864         wm_triple_copy_textures(win, triple_all);
865 }
866
867 /****************** main update call **********************/
868
869 /* quick test to prevent changing window drawable */
870 static bool wm_draw_update_test_window(wmWindow *win)
871 {
872         const bScreen *screen = win->screen;
873         ScrArea *sa;
874         ARegion *ar;
875         bool do_draw = false;
876
877         for (ar = screen->regionbase.first; ar; ar = ar->next) {
878                 if (ar->do_draw_overlay) {
879                         wm_tag_redraw_overlay(win, ar);
880                         ar->do_draw_overlay = false;
881                 }
882                 if (ar->swinid && ar->do_draw)
883                         do_draw = true;
884         }
885
886         for (sa = screen->areabase.first; sa; sa = sa->next) {
887                 for (ar = sa->regionbase.first; ar; ar = ar->next) {
888                         wm_region_test_render_do_draw(screen, sa, ar);
889
890                         if (ar->swinid && ar->do_draw)
891                                 do_draw = true;
892                 }
893         }
894
895         if (do_draw)
896                 return true;
897
898         if (screen->do_refresh)
899                 return true;
900         if (screen->do_draw)
901                 return true;
902         if (screen->do_draw_gesture)
903                 return true;
904         if (screen->do_draw_paintcursor)
905                 return true;
906         if (screen->do_draw_drag)
907                 return true;
908
909         return false;
910 }
911
912 static int wm_automatic_draw_method(wmWindow *win)
913 {
914         /* We assume all supported GPUs now support triple buffer well. */
915         if (win->drawmethod == USER_DRAW_AUTOMATIC) {
916                 return USER_DRAW_TRIPLE;
917         }
918         else {
919                 return win->drawmethod;
920         }
921 }
922
923 bool WM_is_draw_triple(wmWindow *win)
924 {
925         /* function can get called before this variable is set in drawing code below */
926         if (win->drawmethod != U.wmdrawmethod)
927                 win->drawmethod = U.wmdrawmethod;
928         return (USER_DRAW_TRIPLE == wm_automatic_draw_method(win));
929 }
930
931 void wm_tag_redraw_overlay(wmWindow *win, ARegion *ar)
932 {
933         /* for draw triple gestures, paint cursors don't need region redraw */
934         if (ar && win) {
935                 if (wm_automatic_draw_method(win) != USER_DRAW_TRIPLE)
936                         ED_region_tag_redraw(ar);
937                 win->screen->do_draw_paintcursor = true;
938         }
939 }
940
941 void WM_paint_cursor_tag_redraw(wmWindow *win, ARegion *ar)
942 {
943         win->screen->do_draw_paintcursor = true;
944         wm_tag_redraw_overlay(win, ar);
945 }
946
947 void wm_draw_update(bContext *C)
948 {
949         wmWindowManager *wm = CTX_wm_manager(C);
950         wmWindow *win;
951
952 #ifdef WITH_OPENSUBDIV
953         BKE_subsurf_free_unused_buffers();
954 #endif
955
956         GPU_free_unused_buffers();
957
958         for (win = wm->windows.first; win; win = win->next) {
959 #ifdef WIN32
960                 GHOST_TWindowState state = GHOST_GetWindowState(win->ghostwin);
961
962                 if (state == GHOST_kWindowStateMinimized) {
963                         /* do not update minimized windows, gives issues on Intel (see T33223)
964                          * and AMD (see T50856). it seems logical to skip update for invisible
965                          * window anyway.
966                          */
967                         continue;
968                 }
969 #endif
970                 if (win->drawmethod != U.wmdrawmethod) {
971                         wm_draw_window_clear(win);
972                         win->drawmethod = U.wmdrawmethod;
973                 }
974
975                 if (wm_draw_update_test_window(win)) {
976                         bScreen *screen = win->screen;
977
978                         CTX_wm_window_set(C, win);
979
980                         /* sets context window+screen */
981                         wm_window_make_drawable(wm, win);
982
983                         /* notifiers for screen redraw */
984                         if (screen->do_refresh)
985                                 ED_screen_refresh(wm, win);
986
987                         int drawmethod = wm_automatic_draw_method(win);
988
989                         if (win->drawfail)
990                                 wm_method_draw_overlap_all(C, win, 0);
991                         else if (drawmethod == USER_DRAW_FULL)
992                                 wm_method_draw_full(C, win);
993                         else if (drawmethod == USER_DRAW_OVERLAP)
994                                 wm_method_draw_overlap_all(C, win, 0);
995                         else if (drawmethod == USER_DRAW_OVERLAP_FLIP)
996                                 wm_method_draw_overlap_all(C, win, 1);
997                         else { /* USER_DRAW_TRIPLE */
998                                 if ((WM_stereo3d_enabled(win, false)) == false) {
999                                         wm_method_draw_triple(C, win);
1000                                 }
1001                                 else {
1002                                         wm_method_draw_triple_multiview(C, win, STEREO_LEFT_ID);
1003                                         wm_method_draw_triple_multiview(C, win, STEREO_RIGHT_ID);
1004                                         wm_method_draw_stereo3d(C, win);
1005                                 }
1006                         }
1007
1008                         screen->do_draw_gesture = false;
1009                         screen->do_draw_paintcursor = false;
1010                         screen->do_draw_drag = false;
1011
1012                         wm_window_swap_buffers(win);
1013
1014                         CTX_wm_window_set(C, NULL);
1015                 }
1016         }
1017 }
1018
1019 void wm_draw_data_free(wmWindow *win)
1020 {
1021         wmDrawData *dd;
1022
1023         for (dd = win->drawdata.first; dd; dd = dd->next) {
1024                 wm_draw_triple_free(dd->triple);
1025         }
1026         BLI_freelistN(&win->drawdata);
1027 }
1028
1029 void wm_draw_window_clear(wmWindow *win)
1030 {
1031         bScreen *screen = win->screen;
1032         ScrArea *sa;
1033         ARegion *ar;
1034
1035         wm_draw_data_free(win);
1036
1037         /* clear screen swap flags */
1038         if (screen) {
1039                 for (sa = screen->areabase.first; sa; sa = sa->next)
1040                         for (ar = sa->regionbase.first; ar; ar = ar->next)
1041                                 ar->swap = WIN_NONE_OK;
1042
1043                 screen->swap = WIN_NONE_OK;
1044         }
1045 }
1046
1047 void wm_draw_region_clear(wmWindow *win, ARegion *ar)
1048 {
1049         int drawmethod = wm_automatic_draw_method(win);
1050
1051         if (ELEM(drawmethod, USER_DRAW_OVERLAP, USER_DRAW_OVERLAP_FLIP))
1052                 wm_flush_regions_down(win->screen, &ar->winrct);
1053
1054         win->screen->do_draw = true;
1055 }
1056
1057 void WM_redraw_windows(bContext *C)
1058 {
1059         wmWindow *win_prev = CTX_wm_window(C);
1060         ScrArea *area_prev = CTX_wm_area(C);
1061         ARegion *ar_prev = CTX_wm_region(C);
1062
1063         wm_draw_update(C);
1064
1065         CTX_wm_window_set(C, win_prev);
1066         CTX_wm_area_set(C, area_prev);
1067         CTX_wm_region_set(C, ar_prev);
1068 }
1069