Fix syntax for ID keyword.
[blender-staging.git] / source / blender / windowmanager / intern / wm_draw.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2007 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <GL/glew.h>
32
33 #include "DNA_listBase.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_windowmanager_types.h"
36 #include "DNA_userdef_types.h"
37 #include "DNA_view3d_types.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42
43 #include "BKE_context.h"
44 #include "BKE_global.h"
45 #include "BKE_utildefines.h"
46
47 #include "GHOST_C-api.h"
48
49 #include "ED_screen.h"
50
51 #include "GPU_extensions.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55 #include "wm.h"
56 #include "wm_draw.h"
57 #include "wm_window.h"
58 #include "wm_event_system.h"
59
60 /* swap */
61 #define WIN_NONE_OK             0
62 #define WIN_BACK_OK     1
63 #define WIN_FRONT_OK    2
64 #define WIN_BOTH_OK             3
65
66 /* ******************* drawing, overlays *************** */
67
68
69 static void wm_paintcursor_draw(bContext *C, ARegion *ar)
70 {
71         wmWindowManager *wm= CTX_wm_manager(C);
72         
73         if(wm->paintcursors.first) {
74                 wmWindow *win= CTX_wm_window(C);
75                 bScreen *screen= win->screen;
76                 wmPaintCursor *pc;
77
78                 if(screen->subwinactive == ar->swinid) {
79                         for(pc= wm->paintcursors.first; pc; pc= pc->next) {
80                                 if(pc->poll == NULL || pc->poll(C)) {
81                                         ARegion *ar= CTX_wm_region(C);
82                                         if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) {
83                                                 int x = 0, y = 0;
84                                                 wm_get_cursor_position(win, &x, &y);
85                                                 pc->draw(C, x - ar->winrct.xmin, y - ar->winrct.ymin, pc->customdata);
86                                         } else {
87                                                 pc->draw(C, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin, pc->customdata);
88                                         }
89                                 }
90                         }
91                 }
92         }
93 }
94
95 /* ********************* drawing, swap ****************** */
96
97 static void wm_area_mark_invalid_backbuf(ScrArea *sa)
98 {
99         if(sa->spacetype == SPACE_VIEW3D)
100                 ((View3D*)sa->spacedata.first)->flag |= V3D_INVALID_BACKBUF;
101 }
102
103 /********************** draw all **************************/
104 /* - reference method, draw all each time                 */
105
106 static void wm_method_draw_full(bContext *C, wmWindow *win)
107 {
108         bScreen *screen= win->screen;
109         ScrArea *sa;
110         ARegion *ar;
111
112         /* draw area regions */
113         for(sa= screen->areabase.first; sa; sa= sa->next) {
114                 CTX_wm_area_set(C, sa);
115
116                 for(ar=sa->regionbase.first; ar; ar= ar->next) {
117                         if(ar->swinid) {
118                                 CTX_wm_region_set(C, ar);
119                                 ED_region_do_draw(C, ar);
120                                 wm_paintcursor_draw(C, ar);
121                                 ED_area_overdraw_flush(C, sa, ar);
122                                 CTX_wm_region_set(C, NULL);
123                         }
124                 }
125                 
126                 wm_area_mark_invalid_backbuf(sa);
127                 CTX_wm_area_set(C, NULL);
128         }
129
130         ED_screen_draw(win);
131         ED_area_overdraw(C);
132
133         /* draw overlapping regions */
134         for(ar=screen->regionbase.first; ar; ar= ar->next) {
135                 if(ar->swinid) {
136                         CTX_wm_menu_set(C, ar);
137                         ED_region_do_draw(C, ar);
138                         CTX_wm_menu_set(C, NULL);
139                 }
140         }
141
142         if(screen->do_draw_gesture)
143                 wm_gesture_draw(win);
144 }
145
146 /****************** draw overlap all **********************/
147 /* - redraw marked areas, and anything that overlaps it   */
148 /* - it also handles swap exchange optionally, assuming   */
149 /*   that on swap no clearing happens and we get back the */
150 /*   same buffer as we swapped to the front               */
151
152 /* mark area-regions to redraw if overlapped with rect */
153 static void wm_flush_regions_down(bScreen *screen, rcti *dirty)
154 {
155         ScrArea *sa;
156         ARegion *ar;
157
158         for(sa= screen->areabase.first; sa; sa= sa->next) {
159                 for(ar= sa->regionbase.first; ar; ar= ar->next) {
160                         if(BLI_isect_rcti(dirty, &ar->winrct, NULL)) {
161                                 ar->do_draw= 1;
162                                 memset(&ar->drawrct, 0, sizeof(ar->drawrct));
163                                 ar->swap= WIN_NONE_OK;
164                         }
165                 }
166         }
167 }
168
169 /* mark menu-regions to redraw if overlapped with rect */
170 static void wm_flush_regions_up(bScreen *screen, rcti *dirty)
171 {
172         ARegion *ar;
173         
174         for(ar= screen->regionbase.first; ar; ar= ar->next) {
175                 if(BLI_isect_rcti(dirty, &ar->winrct, NULL)) {
176                         ar->do_draw= 1;
177                         memset(&ar->drawrct, 0, sizeof(ar->drawrct));
178                         ar->swap= WIN_NONE_OK;
179                 }
180         }
181 }
182
183 static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
184 {
185         wmWindowManager *wm= CTX_wm_manager(C);
186         bScreen *screen= win->screen;
187         ScrArea *sa;
188         ARegion *ar;
189         static rcti rect= {0, 0, 0, 0};
190
191         /* flush overlapping regions */
192         if(screen->regionbase.first) {
193                 /* flush redraws of area regions up to overlapping regions */
194                 for(sa= screen->areabase.first; sa; sa= sa->next)
195                         for(ar= sa->regionbase.first; ar; ar= ar->next)
196                                 if(ar->swinid && ar->do_draw)
197                                         wm_flush_regions_up(screen, &ar->winrct);
198                 
199                 /* flush between overlapping regions */
200                 for(ar= screen->regionbase.last; ar; ar= ar->prev)
201                         if(ar->swinid && ar->do_draw)
202                                 wm_flush_regions_up(screen, &ar->winrct);
203                 
204                 /* flush redraws of overlapping regions down to area regions */
205                 for(ar= screen->regionbase.last; ar; ar= ar->prev)
206                         if(ar->swinid && ar->do_draw)
207                                 wm_flush_regions_down(screen, &ar->winrct);
208         }
209
210         /* flush drag item */
211         if(rect.xmin!=rect.xmax) {
212                 wm_flush_regions_down(screen, &rect);
213                 rect.xmin= rect.xmax = 0;
214         }
215         if(wm->drags.first) {
216                 /* doesnt draw, fills rect with boundbox */
217                 wm_drags_draw(C, win, &rect);
218         }
219         
220         /* draw marked area regions */
221         for(sa= screen->areabase.first; sa; sa= sa->next) {
222                 CTX_wm_area_set(C, sa);
223
224                 for(ar=sa->regionbase.first; ar; ar= ar->next) {
225                         if(ar->swinid) {
226                                 if(ar->do_draw) {
227                                         CTX_wm_region_set(C, ar);
228                                         ED_region_do_draw(C, ar);
229                                         wm_paintcursor_draw(C, ar);
230                                         ED_area_overdraw_flush(C, sa, ar);
231                                         CTX_wm_region_set(C, NULL);
232
233                                         if(exchange)
234                                                 ar->swap= WIN_FRONT_OK;
235                                 }
236                                 else if(exchange) {
237                                         if(ar->swap == WIN_FRONT_OK) {
238                                                 CTX_wm_region_set(C, ar);
239                                                 ED_region_do_draw(C, ar);
240                                                 wm_paintcursor_draw(C, ar);
241                                                 ED_area_overdraw_flush(C, sa, ar);
242                                                 CTX_wm_region_set(C, NULL);
243
244                                                 ar->swap= WIN_BOTH_OK;
245                                                 printf("draws swap exchange %d\n", ar->swinid);
246                                         }
247                                         else if(ar->swap == WIN_BACK_OK)
248                                                 ar->swap= WIN_FRONT_OK;
249                                         else if(ar->swap == WIN_BOTH_OK)
250                                                 ar->swap= WIN_BOTH_OK;
251                                 }
252                         }
253                 }
254                 
255                 wm_area_mark_invalid_backbuf(sa);
256                 CTX_wm_area_set(C, NULL);
257         }
258
259         /* after area regions so we can do area 'overlay' drawing */
260         if(screen->do_draw) {
261                 ED_screen_draw(win);
262
263                 if(exchange)
264                         screen->swap= WIN_FRONT_OK;
265         }
266         else if(exchange) {
267                 if(screen->swap==WIN_FRONT_OK) {
268                         ED_screen_draw(win);
269                         screen->swap= WIN_BOTH_OK;
270                 }
271                 else if(screen->swap==WIN_BACK_OK)
272                         screen->swap= WIN_FRONT_OK;
273                 else if(screen->swap==WIN_BOTH_OK)
274                         screen->swap= WIN_BOTH_OK;
275         }
276
277         ED_area_overdraw(C);
278
279         /* draw marked overlapping regions */
280         for(ar=screen->regionbase.first; ar; ar= ar->next) {
281                 if(ar->swinid && ar->do_draw) {
282                         CTX_wm_menu_set(C, ar);
283                         ED_region_do_draw(C, ar);
284                         CTX_wm_menu_set(C, NULL);
285                 }
286         }
287
288         if(screen->do_draw_gesture)
289                 wm_gesture_draw(win);
290         
291         /* needs pixel coords in screen */
292         if(wm->drags.first) {
293                 wm_drags_draw(C, win, NULL);
294         }
295 }
296
297 #if 0
298 /******************** draw damage ************************/
299 /* - not implemented                                      */
300
301 static void wm_method_draw_damage(bContext *C, wmWindow *win)
302 {
303         wm_method_draw_all(C, win);
304 }
305 #endif
306
307 /****************** draw triple buffer ********************/
308 /* - area regions are written into a texture, without any */
309 /*   of the overlapping menus, brushes, gestures. these   */
310 /*   are redrawn each time.                               */
311 /*                                                        */
312 /* - if non-power of two textures are supported, that is  */
313 /*   used. if not, multiple smaller ones are used, with   */
314 /*   worst case wasted space being 23.4% for 3x3 textures */
315
316 #define MAX_N_TEX 3
317
318 typedef struct wmDrawTriple {
319         GLuint bind[MAX_N_TEX*MAX_N_TEX];
320         int x[MAX_N_TEX], y[MAX_N_TEX];
321         int nx, ny;
322         GLenum target;
323 } wmDrawTriple;
324
325 static int is_pow2(int n)
326 {
327         return ((n)&(n-1))==0;
328 }
329
330 static int smaller_pow2(int n)
331 {
332     while (!is_pow2(n))
333                 n= n&(n-1);
334
335         return n;
336 }
337
338 static int larger_pow2(int n)
339 {
340         if (is_pow2(n))
341                 return n;
342
343         while(!is_pow2(n))
344                 n= n&(n-1);
345
346         return n*2;
347 }
348
349 static void split_width(int x, int n, int *splitx, int *nx)
350 {
351         int a, newnx, waste;
352
353         /* if already power of two just use it */
354         if(is_pow2(x)) {
355                 splitx[0]= x;
356                 (*nx)++;
357                 return;
358         }
359
360         if(n == 1) {
361                 /* last part, we have to go larger */
362                 splitx[0]= larger_pow2(x);
363                 (*nx)++;
364         }
365         else {
366                 /* two or more parts to go, use smaller part */
367                 splitx[0]= smaller_pow2(x);
368                 newnx= ++(*nx);
369                 split_width(x-splitx[0], n-1, splitx+1, &newnx);
370
371                 for(waste=0, a=0; a<n; a++)
372                         waste += splitx[a];
373
374                 /* if we waste more space or use the same amount,
375                  * revert deeper splits and just use larger */
376                 if(waste >= larger_pow2(x)) {
377                         splitx[0]= larger_pow2(x);
378                         memset(splitx+1, 0, sizeof(int)*(n-1));
379                 }
380                 else
381                         *nx= newnx;
382         }
383 }
384
385 static void wm_draw_triple_free(wmWindow *win)
386 {
387         if(win->drawdata) {
388                 wmDrawTriple *triple= win->drawdata;
389
390                 glDeleteTextures(triple->nx*triple->ny, triple->bind);
391                 MEM_freeN(triple);
392
393                 win->drawdata= NULL;
394         }
395 }
396
397 static void wm_draw_triple_fail(bContext *C, wmWindow *win)
398 {
399         wm_draw_window_clear(win);
400
401         win->drawfail= 1;
402         wm_method_draw_overlap_all(C, win, 0);
403 }
404
405 static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
406 {
407         GLint maxsize;
408         int x, y;
409
410         /* compute texture sizes */
411         if(GLEW_ARB_texture_rectangle || GLEW_NV_texture_rectangle || GLEW_EXT_texture_rectangle) {
412                 triple->target= GL_TEXTURE_RECTANGLE_ARB;
413                 triple->nx= 1;
414                 triple->ny= 1;
415                 triple->x[0]= win->sizex;
416                 triple->y[0]= win->sizey;
417         }
418         else if(GPU_non_power_of_two_support()) {
419                 triple->target= GL_TEXTURE_2D;
420                 triple->nx= 1;
421                 triple->ny= 1;
422                 triple->x[0]= win->sizex;
423                 triple->y[0]= win->sizey;
424         }
425         else {
426                 triple->target= GL_TEXTURE_2D;
427                 triple->nx= 0;
428                 triple->ny= 0;
429                 split_width(win->sizex, MAX_N_TEX, triple->x, &triple->nx);
430                 split_width(win->sizey, MAX_N_TEX, triple->y, &triple->ny);
431         }
432
433         /* generate texture names */
434         glGenTextures(triple->nx*triple->ny, triple->bind);
435
436         if(!triple->bind[0]) {
437                 /* not the typical failure case but we handle it anyway */
438                 printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
439                 return 0;
440         }
441
442         for(y=0; y<triple->ny; y++) {
443                 for(x=0; x<triple->nx; x++) {
444                         /* proxy texture is only guaranteed to test for the cases that
445                          * there is only one texture in use, which may not be the case */
446                         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
447
448                         if(triple->x[x] > maxsize || triple->y[y] > maxsize) {
449                                 glBindTexture(triple->target, 0);
450                                 printf("WM: failed to allocate texture for triple buffer drawing (texture too large for graphics card).\n");
451                                 return 0;
452                         }
453
454                         /* setup actual texture */
455                         glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
456                         glTexImage2D(triple->target, 0, GL_RGB8, triple->x[x], triple->y[y], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
457                         glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
458                         glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
459                         // glColor still used with this enabled?
460                         // glTexEnvi(triple->target, GL_TEXTURE_ENV_MODE, GL_REPLACE);
461                         glBindTexture(triple->target, 0);
462
463                         /* not sure if this works everywhere .. */
464                         if(glGetError() == GL_OUT_OF_MEMORY) {
465                                 printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
466                                 return 0;
467                         }
468                 }
469         }
470
471         return 1;
472 }
473
474 static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple)
475 {
476         float halfx, halfy, ratiox, ratioy;
477         int x, y, sizex, sizey, offx, offy;
478
479         glEnable(triple->target);
480
481         for(y=0, offy=0; y<triple->ny; offy+=triple->y[y], y++) {
482                 for(x=0, offx=0; x<triple->nx; offx+=triple->x[x], x++) {
483                         sizex= (x == triple->nx-1)? win->sizex-offx: triple->x[x];
484                         sizey= (y == triple->ny-1)? win->sizey-offy: triple->y[y];
485
486                         /* wmOrtho for the screen has this same offset */
487                         ratiox= sizex;
488                         ratioy= sizey;
489                         halfx= 0.375f;
490                         halfy= 0.375f;
491
492                         /* texture rectangle has unnormalized coordinates */
493                         if(triple->target == GL_TEXTURE_2D) {
494                                 ratiox /= triple->x[x];
495                                 ratioy /= triple->y[y];
496                                 halfx /= triple->x[x];
497                                 halfy /= triple->y[y];
498                         }
499
500                         glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
501
502                         glColor3f(1.0f, 1.0f, 1.0f);
503                         glBegin(GL_QUADS);
504                                 glTexCoord2f(halfx, halfy);
505                                 glVertex2f(offx, offy);
506
507                                 glTexCoord2f(ratiox+halfx, halfy);
508                                 glVertex2f(offx+sizex, offy);
509
510                                 glTexCoord2f(ratiox+halfx, ratioy+halfy);
511                                 glVertex2f(offx+sizex, offy+sizey);
512
513                                 glTexCoord2f(halfx, ratioy+halfy);
514                                 glVertex2f(offx, offy+sizey);
515                         glEnd();
516                 }
517         }
518
519         glBindTexture(triple->target, 0);
520         glDisable(triple->target);
521 }
522
523 static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
524 {
525         int x, y, sizex, sizey, offx, offy;
526
527         for(y=0, offy=0; y<triple->ny; offy+=triple->y[y], y++) {
528                 for(x=0, offx=0; x<triple->nx; offx+=triple->x[x], x++) {
529                         sizex= (x == triple->nx-1)? win->sizex-offx: triple->x[x];
530                         sizey= (y == triple->ny-1)? win->sizey-offy: triple->y[y];
531
532                         glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
533                         glCopyTexSubImage2D(triple->target, 0, 0, 0, offx, offy, sizex, sizey);
534                 }
535         }
536
537         glBindTexture(triple->target, 0);
538 }
539
540 static void wm_method_draw_triple(bContext *C, wmWindow *win)
541 {
542         wmWindowManager *wm= CTX_wm_manager(C);
543         wmDrawTriple *triple;
544         bScreen *screen= win->screen;
545         ScrArea *sa;
546         ARegion *ar;
547         int copytex= 0;
548
549         if(win->drawdata) {
550                 glClearColor(0, 0, 0, 0);
551                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
552
553                 wmSubWindowSet(win, screen->mainwin);
554
555                 wm_triple_draw_textures(win, win->drawdata);
556
557                 triple= win->drawdata;
558         }
559         else {
560                 win->drawdata= MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
561
562                 if(!wm_triple_gen_textures(win, win->drawdata)) {
563                         wm_draw_triple_fail(C, win);
564                         return;
565                 }
566         }
567
568         triple= win->drawdata;
569
570         /* draw marked area regions */
571         for(sa= screen->areabase.first; sa; sa= sa->next) {
572                 CTX_wm_area_set(C, sa);
573
574                 for(ar=sa->regionbase.first; ar; ar= ar->next) {
575                         if(ar->swinid && ar->do_draw) {
576                                 CTX_wm_region_set(C, ar);
577                                 ED_region_do_draw(C, ar);
578                                 ED_area_overdraw_flush(C, sa, ar);
579                                 CTX_wm_region_set(C, NULL);
580                                 copytex= 1;
581                         }
582                 }
583                 
584                 wm_area_mark_invalid_backbuf(sa);
585                 CTX_wm_area_set(C, NULL);
586         }
587
588         if(copytex) {
589                 wmSubWindowSet(win, screen->mainwin);
590                 ED_area_overdraw(C);
591
592                 wm_triple_copy_textures(win, triple);
593         }
594
595         /* after area regions so we can do area 'overlay' drawing */
596         ED_screen_draw(win);
597
598         /* draw overlapping regions */
599         for(ar=screen->regionbase.first; ar; ar= ar->next) {
600                 if(ar->swinid) {
601                         CTX_wm_menu_set(C, ar);
602                         ED_region_do_draw(C, ar);
603                         CTX_wm_menu_set(C, NULL);
604                 }
605         }
606
607         if(screen->do_draw_gesture)
608                 wm_gesture_draw(win);
609
610         if(wm->paintcursors.first) {
611                 for(sa= screen->areabase.first; sa; sa= sa->next) {
612                         for(ar=sa->regionbase.first; ar; ar= ar->next) {
613                                 if(ar->swinid == screen->subwinactive) {
614                                         CTX_wm_area_set(C, sa);
615                                         CTX_wm_region_set(C, ar);
616
617                                         /* make region ready for draw, scissor, pixelspace */
618                                         ED_region_set(C, ar);
619                                         wm_paintcursor_draw(C, ar);
620
621                                         CTX_wm_region_set(C, NULL);
622                                         CTX_wm_area_set(C, NULL);
623                                 }
624                         }
625                 }
626
627                 wmSubWindowSet(win, screen->mainwin);
628         }
629         
630         /* needs pixel coords in screen */
631         if(wm->drags.first) {
632                 wm_drags_draw(C, win, NULL);
633         }
634
635 }
636
637 /****************** main update call **********************/
638
639 /* quick test to prevent changing window drawable */
640 static int wm_draw_update_test_window(wmWindow *win)
641 {
642         ScrArea *sa;
643         ARegion *ar;
644         
645         if(win->screen->do_refresh)
646                 return 1;
647         if(win->screen->do_draw)
648                 return 1;
649         if(win->screen->do_draw_gesture)
650                 return 1;
651         if(win->screen->do_draw_paintcursor)
652                 return 1;
653         if(win->screen->do_draw_drag)
654                 return 1;
655         
656         for(ar= win->screen->regionbase.first; ar; ar= ar->next)
657                 if(ar->swinid && ar->do_draw)
658                         return 1;
659                 
660         for(sa= win->screen->areabase.first; sa; sa= sa->next)
661                 for(ar=sa->regionbase.first; ar; ar= ar->next)
662                         if(ar->swinid && ar->do_draw)
663                                 return 1;
664
665         return 0;
666 }
667
668 static int wm_automatic_draw_method(wmWindow *win)
669 {
670         if(win->drawmethod == USER_DRAW_AUTOMATIC) {
671                 /* ATI opensource driver is known to be very slow at this */
672                 if(GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE))
673                         return USER_DRAW_OVERLAP;
674                 /* Windows software driver darkens color on each redraw */
675                 else if(GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_SOFTWARE))
676                         return USER_DRAW_OVERLAP_FLIP;
677                 else
678                         return USER_DRAW_TRIPLE;
679         }
680         else
681                 return win->drawmethod;
682 }
683
684 void wm_draw_update(bContext *C)
685 {
686         wmWindowManager *wm= CTX_wm_manager(C);
687         wmWindow *win;
688         int drawmethod;
689         
690         for(win= wm->windows.first; win; win= win->next) {
691                 if(win->drawmethod != U.wmdrawmethod) {
692                         wm_draw_window_clear(win);
693                         win->drawmethod= U.wmdrawmethod;
694                 }
695
696                 if(wm_draw_update_test_window(win)) {
697                         CTX_wm_window_set(C, win);
698                         
699                         /* sets context window+screen */
700                         wm_window_make_drawable(C, win);
701
702                         /* notifiers for screen redraw */
703                         if(win->screen->do_refresh)
704                                 ED_screen_refresh(wm, win);
705
706                         drawmethod= wm_automatic_draw_method(win);
707
708                         if(win->drawfail)
709                                 wm_method_draw_overlap_all(C, win, 0);
710                         else if(drawmethod == USER_DRAW_FULL)
711                                 wm_method_draw_full(C, win);
712                         else if(drawmethod == USER_DRAW_OVERLAP)
713                                 wm_method_draw_overlap_all(C, win, 0);
714                         else if(drawmethod == USER_DRAW_OVERLAP_FLIP)
715                                 wm_method_draw_overlap_all(C, win, 1);
716                         else // if(drawmethod == USER_DRAW_TRIPLE)
717                                 wm_method_draw_triple(C, win);
718
719                         win->screen->do_draw_gesture= 0;
720                         win->screen->do_draw_paintcursor= 0;
721                         win->screen->do_draw_drag= 0;
722                 
723                         wm_window_swap_buffers(win);
724
725                         CTX_wm_window_set(C, NULL);
726                 }
727         }
728 }
729
730 void wm_draw_window_clear(wmWindow *win)
731 {
732         bScreen *screen= win->screen;
733         ScrArea *sa;
734         ARegion *ar;
735         int drawmethod= wm_automatic_draw_method(win);
736
737         if(drawmethod == USER_DRAW_TRIPLE)
738                 wm_draw_triple_free(win);
739
740         /* clear screen swap flags */
741         if(screen) {
742                 for(sa= screen->areabase.first; sa; sa= sa->next)
743                         for(ar=sa->regionbase.first; ar; ar= ar->next)
744                                 ar->swap= WIN_NONE_OK;
745                 
746                 screen->swap= WIN_NONE_OK;
747         }
748 }
749
750 void wm_draw_region_clear(wmWindow *win, ARegion *ar)
751 {
752         int drawmethod= wm_automatic_draw_method(win);
753
754         if(ELEM(drawmethod, USER_DRAW_OVERLAP, USER_DRAW_OVERLAP_FLIP))
755                 wm_flush_regions_down(win->screen, &ar->winrct);
756
757         win->screen->do_draw= 1;
758 }
759