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