Drag and drop 2.5 integration! Finally, slashdot regulars can use
[blender.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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)
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         int exchange= (G.f & G_SWAP_EXCHANGE);
191
192         /* flush overlapping regions */
193         if(screen->regionbase.first) {
194                 /* flush redraws of area regions up to overlapping regions */
195                 for(sa= screen->areabase.first; sa; sa= sa->next)
196                         for(ar= sa->regionbase.first; ar; ar= ar->next)
197                                 if(ar->swinid && ar->do_draw)
198                                         wm_flush_regions_up(screen, &ar->winrct);
199                 
200                 /* flush between overlapping regions */
201                 for(ar= screen->regionbase.last; ar; ar= ar->prev)
202                         if(ar->swinid && ar->do_draw)
203                                 wm_flush_regions_up(screen, &ar->winrct);
204                 
205                 /* flush redraws of overlapping regions down to area regions */
206                 for(ar= screen->regionbase.last; ar; ar= ar->prev)
207                         if(ar->swinid && ar->do_draw)
208                                 wm_flush_regions_down(screen, &ar->winrct);
209         }
210
211         /* flush drag item */
212         if(rect.xmin!=rect.xmax) {
213                 wm_flush_regions_down(screen, &rect);
214                 rect.xmin= rect.xmax = 0;
215         }
216         if(wm->drags.first) {
217                 /* doesnt draw, fills rect with boundbox */
218                 wm_drags_draw(C, win, &rect);
219         }
220         
221         /* draw marked area regions */
222         for(sa= screen->areabase.first; sa; sa= sa->next) {
223                 CTX_wm_area_set(C, sa);
224
225                 for(ar=sa->regionbase.first; ar; ar= ar->next) {
226                         if(ar->swinid) {
227                                 if(ar->do_draw) {
228                                         CTX_wm_region_set(C, ar);
229                                         ED_region_do_draw(C, ar);
230                                         wm_paintcursor_draw(C, ar);
231                                         ED_area_overdraw_flush(C, sa, ar);
232                                         CTX_wm_region_set(C, NULL);
233
234                                         if(exchange)
235                                                 ar->swap= WIN_FRONT_OK;
236                                 }
237                                 else if(exchange) {
238                                         if(ar->swap == WIN_FRONT_OK) {
239                                                 CTX_wm_region_set(C, ar);
240                                                 ED_region_do_draw(C, ar);
241                                                 wm_paintcursor_draw(C, ar);
242                                                 ED_area_overdraw_flush(C, sa, ar);
243                                                 CTX_wm_region_set(C, NULL);
244
245                                                 ar->swap= WIN_BOTH_OK;
246                                                 printf("draws swap exchange %d\n", ar->swinid);
247                                         }
248                                         else if(ar->swap == WIN_BACK_OK)
249                                                 ar->swap= WIN_FRONT_OK;
250                                         else if(ar->swap == WIN_BOTH_OK)
251                                                 ar->swap= WIN_BOTH_OK;
252                                 }
253                         }
254                 }
255                 
256                 wm_area_mark_invalid_backbuf(sa);
257                 CTX_wm_area_set(C, NULL);
258         }
259
260         /* after area regions so we can do area 'overlay' drawing */
261         if(screen->do_draw) {
262                 ED_screen_draw(win);
263
264                 if(exchange)
265                         screen->swap= WIN_FRONT_OK;
266         }
267         else if(exchange) {
268                 if(screen->swap==WIN_FRONT_OK) {
269                         ED_screen_draw(win);
270                         screen->swap= WIN_BOTH_OK;
271                 }
272                 else if(screen->swap==WIN_BACK_OK)
273                         screen->swap= WIN_FRONT_OK;
274                 else if(screen->swap==WIN_BOTH_OK)
275                         screen->swap= WIN_BOTH_OK;
276         }
277
278         ED_area_overdraw(C);
279
280         /* draw marked overlapping regions */
281         for(ar=screen->regionbase.first; ar; ar= ar->next) {
282                 if(ar->swinid && ar->do_draw) {
283                         CTX_wm_menu_set(C, ar);
284                         ED_region_do_draw(C, ar);
285                         CTX_wm_menu_set(C, NULL);
286                 }
287         }
288
289         if(screen->do_draw_gesture)
290                 wm_gesture_draw(win);
291         
292         /* needs pixel coords in screen */
293         if(wm->drags.first) {
294                 wm_drags_draw(C, win, NULL);
295         }
296 }
297
298 #if 0
299 /******************** draw damage ************************/
300 /* - not implemented                                      */
301
302 static void wm_method_draw_damage(bContext *C, wmWindow *win)
303 {
304         wm_method_draw_all(C, win);
305 }
306 #endif
307
308 /****************** draw triple buffer ********************/
309 /* - area regions are written into a texture, without any */
310 /*   of the overlapping menus, brushes, gestures. these   */
311 /*   are redrawn each time.                               */
312 /*                                                        */
313 /* - if non-power of two textures are supported, that is  */
314 /*   used. if not, multiple smaller ones are used, with   */
315 /*   worst case wasted space being 23.4% for 3x3 textures */
316
317 #define MAX_N_TEX 3
318
319 typedef struct wmDrawTriple {
320         GLuint bind[MAX_N_TEX*MAX_N_TEX];
321         int x[MAX_N_TEX], y[MAX_N_TEX];
322         int nx, ny;
323         GLenum target;
324 } wmDrawTriple;
325
326 static int is_pow2(int n)
327 {
328         return ((n)&(n-1))==0;
329 }
330
331 static int smaller_pow2(int n)
332 {
333     while (!is_pow2(n))
334                 n= n&(n-1);
335
336         return n;
337 }
338
339 static int larger_pow2(int n)
340 {
341         if (is_pow2(n))
342                 return n;
343
344         while(!is_pow2(n))
345                 n= n&(n-1);
346
347         return n*2;
348 }
349
350 static void split_width(int x, int n, int *splitx, int *nx)
351 {
352         int a, newnx, waste;
353
354         /* if already power of two just use it */
355         if(is_pow2(x)) {
356                 splitx[0]= x;
357                 (*nx)++;
358                 return;
359         }
360
361         if(n == 1) {
362                 /* last part, we have to go larger */
363                 splitx[0]= larger_pow2(x);
364                 (*nx)++;
365         }
366         else {
367                 /* two or more parts to go, use smaller part */
368                 splitx[0]= smaller_pow2(x);
369                 newnx= ++(*nx);
370                 split_width(x-splitx[0], n-1, splitx+1, &newnx);
371
372                 for(waste=0, a=0; a<n; a++)
373                         waste += splitx[a];
374
375                 /* if we waste more space or use the same amount,
376                  * revert deeper splits and just use larger */
377                 if(waste >= larger_pow2(x)) {
378                         splitx[0]= larger_pow2(x);
379                         memset(splitx+1, 0, sizeof(int)*(n-1));
380                 }
381                 else
382                         *nx= newnx;
383         }
384 }
385
386 static void wm_draw_triple_free(wmWindow *win)
387 {
388         if(win->drawdata) {
389                 wmDrawTriple *triple= win->drawdata;
390
391                 glDeleteTextures(triple->nx*triple->ny, triple->bind);
392                 MEM_freeN(triple);
393
394                 win->drawdata= NULL;
395         }
396 }
397
398 static void wm_draw_triple_fail(bContext *C, wmWindow *win)
399 {
400         wm_draw_window_clear(win);
401
402         win->drawfail= 1;
403         wm_method_draw_overlap_all(C, win);
404 }
405
406 static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
407 {
408         GLint maxsize;
409         int x, y;
410
411         /* compute texture sizes */
412         if(GLEW_ARB_texture_rectangle || GLEW_NV_texture_rectangle || GLEW_EXT_texture_rectangle) {
413                 triple->target= GL_TEXTURE_RECTANGLE_ARB;
414                 triple->nx= 1;
415                 triple->ny= 1;
416                 triple->x[0]= win->sizex;
417                 triple->y[0]= win->sizey;
418         }
419         else if(GPU_non_power_of_two_support()) {
420                 triple->target= GL_TEXTURE_2D;
421                 triple->nx= 1;
422                 triple->ny= 1;
423                 triple->x[0]= win->sizex;
424                 triple->y[0]= win->sizey;
425         }
426         else {
427                 triple->target= GL_TEXTURE_2D;
428                 triple->nx= 0;
429                 triple->ny= 0;
430                 split_width(win->sizex, MAX_N_TEX, triple->x, &triple->nx);
431                 split_width(win->sizey, MAX_N_TEX, triple->y, &triple->ny);
432         }
433
434         /* generate texture names */
435         glGenTextures(triple->nx*triple->ny, triple->bind);
436
437         if(!triple->bind[0]) {
438                 /* not the typical failure case but we handle it anyway */
439                 printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
440                 return 0;
441         }
442
443         for(y=0; y<triple->ny; y++) {
444                 for(x=0; x<triple->nx; x++) {
445                         /* proxy texture is only guaranteed to test for the cases that
446                          * there is only one texture in use, which may not be the case */
447                         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize);
448
449                         if(triple->x[x] > maxsize || triple->y[y] > maxsize) {
450                                 glBindTexture(triple->target, 0);
451                                 printf("WM: failed to allocate texture for triple buffer drawing (texture too large for graphics card).\n");
452                                 return 0;
453                         }
454
455                         /* setup actual texture */
456                         glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
457                         glTexImage2D(triple->target, 0, GL_RGB8, triple->x[x], triple->y[y], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
458                         glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
459                         glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
460                         // glColor still used with this enabled?
461                         // glTexEnvi(triple->target, GL_TEXTURE_ENV_MODE, GL_REPLACE);
462                         glBindTexture(triple->target, 0);
463
464                         /* not sure if this works everywhere .. */
465                         if(glGetError() == GL_OUT_OF_MEMORY) {
466                                 printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
467                                 return 0;
468                         }
469                 }
470         }
471
472         return 1;
473 }
474
475 static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple)
476 {
477         float halfx, halfy, ratiox, ratioy;
478         int x, y, sizex, sizey, offx, offy;
479
480         glEnable(triple->target);
481
482         for(y=0, offy=0; y<triple->ny; offy+=triple->y[y], y++) {
483                 for(x=0, offx=0; x<triple->nx; offx+=triple->x[x], x++) {
484                         sizex= (x == triple->nx-1)? win->sizex-offx: triple->x[x];
485                         sizey= (y == triple->ny-1)? win->sizey-offy: triple->y[y];
486
487                         /* wmOrtho for the screen has this same offset */
488                         ratiox= sizex;
489                         ratioy= sizey;
490                         halfx= 0.375f;
491                         halfy= 0.375f;
492
493                         /* texture rectangle has unnormalized coordinates */
494                         if(triple->target == GL_TEXTURE_2D) {
495                                 ratiox /= triple->x[x];
496                                 ratioy /= triple->y[y];
497                                 halfx /= triple->x[x];
498                                 halfy /= triple->y[y];
499                         }
500
501                         glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
502
503                         glColor3f(1.0f, 1.0f, 1.0f);
504                         glBegin(GL_QUADS);
505                                 glTexCoord2f(halfx, halfy);
506                                 glVertex2f(offx, offy);
507
508                                 glTexCoord2f(ratiox+halfx, halfy);
509                                 glVertex2f(offx+sizex, offy);
510
511                                 glTexCoord2f(ratiox+halfx, ratioy+halfy);
512                                 glVertex2f(offx+sizex, offy+sizey);
513
514                                 glTexCoord2f(halfx, ratioy+halfy);
515                                 glVertex2f(offx, offy+sizey);
516                         glEnd();
517                 }
518         }
519
520         glBindTexture(triple->target, 0);
521         glDisable(triple->target);
522 }
523
524 static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
525 {
526         int x, y, sizex, sizey, offx, offy;
527
528         for(y=0, offy=0; y<triple->ny; offy+=triple->y[y], y++) {
529                 for(x=0, offx=0; x<triple->nx; offx+=triple->x[x], x++) {
530                         sizex= (x == triple->nx-1)? win->sizex-offx: triple->x[x];
531                         sizey= (y == triple->ny-1)? win->sizey-offy: triple->y[y];
532
533                         glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
534                         glCopyTexSubImage2D(triple->target, 0, 0, 0, offx, offy, sizex, sizey);
535                 }
536         }
537
538         glBindTexture(triple->target, 0);
539 }
540
541 static void wm_method_draw_triple(bContext *C, wmWindow *win)
542 {
543         wmWindowManager *wm= CTX_wm_manager(C);
544         wmDrawTriple *triple;
545         bScreen *screen= win->screen;
546         ScrArea *sa;
547         ARegion *ar;
548         int copytex= 0;
549
550         if(win->drawdata) {
551                 glClearColor(0, 0, 0, 0);
552                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
553
554                 wmSubWindowSet(win, screen->mainwin);
555
556                 wm_triple_draw_textures(win, win->drawdata);
557
558                 triple= win->drawdata;
559         }
560         else {
561                 win->drawdata= MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
562
563                 if(!wm_triple_gen_textures(win, win->drawdata)) {
564                         wm_draw_triple_fail(C, win);
565                         return;
566                 }
567         }
568
569         triple= win->drawdata;
570
571         /* draw marked area regions */
572         for(sa= screen->areabase.first; sa; sa= sa->next) {
573                 CTX_wm_area_set(C, sa);
574
575                 for(ar=sa->regionbase.first; ar; ar= ar->next) {
576                         if(ar->swinid && ar->do_draw) {
577                                 CTX_wm_region_set(C, ar);
578                                 ED_region_do_draw(C, ar);
579                                 ED_area_overdraw_flush(C, sa, ar);
580                                 CTX_wm_region_set(C, NULL);
581                                 copytex= 1;
582                         }
583                 }
584                 
585                 wm_area_mark_invalid_backbuf(sa);
586                 CTX_wm_area_set(C, NULL);
587         }
588
589         if(copytex) {
590                 wmSubWindowSet(win, screen->mainwin);
591                 ED_area_overdraw(C);
592
593                 wm_triple_copy_textures(win, triple);
594         }
595
596         /* after area regions so we can do area 'overlay' drawing */
597         ED_screen_draw(win);
598
599         /* draw overlapping regions */
600         for(ar=screen->regionbase.first; ar; ar= ar->next) {
601                 if(ar->swinid) {
602                         CTX_wm_menu_set(C, ar);
603                         ED_region_do_draw(C, ar);
604                         CTX_wm_menu_set(C, NULL);
605                 }
606         }
607
608         if(screen->do_draw_gesture)
609                 wm_gesture_draw(win);
610
611         if(wm->paintcursors.first) {
612                 for(sa= screen->areabase.first; sa; sa= sa->next) {
613                         for(ar=sa->regionbase.first; ar; ar= ar->next) {
614                                 if(ar->swinid == screen->subwinactive) {
615                                         CTX_wm_area_set(C, sa);
616                                         CTX_wm_region_set(C, ar);
617
618                                         /* make region ready for draw, scissor, pixelspace */
619                                         ED_region_set(C, ar);
620                                         wm_paintcursor_draw(C, ar);
621
622                                         CTX_wm_region_set(C, NULL);
623                                         CTX_wm_area_set(C, NULL);
624                                 }
625                         }
626                 }
627
628                 wmSubWindowSet(win, screen->mainwin);
629         }
630         
631         /* needs pixel coords in screen */
632         if(wm->drags.first) {
633                 wm_drags_draw(C, win, NULL);
634         }
635
636 }
637
638 /****************** main update call **********************/
639
640 /* quick test to prevent changing window drawable */
641 static int wm_draw_update_test_window(wmWindow *win)
642 {
643         ScrArea *sa;
644         ARegion *ar;
645         
646         if(win->screen->do_refresh)
647                 return 1;
648         if(win->screen->do_draw)
649                 return 1;
650         if(win->screen->do_draw_gesture)
651                 return 1;
652         if(win->screen->do_draw_paintcursor)
653                 return 1;
654         if(win->screen->do_draw_drag)
655                 return 1;
656         
657         for(ar= win->screen->regionbase.first; ar; ar= ar->next)
658                 if(ar->swinid && ar->do_draw)
659                         return 1;
660                 
661         for(sa= win->screen->areabase.first; sa; sa= sa->next)
662                 for(ar=sa->regionbase.first; ar; ar= ar->next)
663                         if(ar->swinid && ar->do_draw)
664                                 return 1;
665
666         return 0;
667 }
668
669 void wm_draw_update(bContext *C)
670 {
671         wmWindowManager *wm= CTX_wm_manager(C);
672         wmWindow *win;
673         
674         for(win= wm->windows.first; win; win= win->next) {
675                 if(win->drawmethod != U.wmdrawmethod) {
676                         wm_draw_window_clear(win);
677                         win->drawmethod= U.wmdrawmethod;
678                 }
679
680                 if(wm_draw_update_test_window(win)) {
681                         CTX_wm_window_set(C, win);
682                         
683                         /* sets context window+screen */
684                         wm_window_make_drawable(C, win);
685
686                         /* notifiers for screen redraw */
687                         if(win->screen->do_refresh)
688                                 ED_screen_refresh(wm, win);
689
690                         if(win->drawfail)
691                                 wm_method_draw_overlap_all(C, win);
692                         else if(win->drawmethod == USER_DRAW_FULL)
693                                 wm_method_draw_full(C, win);
694                         else if(win->drawmethod == USER_DRAW_OVERLAP)
695                                 wm_method_draw_overlap_all(C, win);
696                         /*else if(win->drawmethod == USER_DRAW_DAMAGE)
697                                 wm_method_draw_damage(C, win);*/
698                         else // if(win->drawmethod == USER_DRAW_TRIPLE)
699                                 wm_method_draw_triple(C, win);
700
701                         win->screen->do_draw_gesture= 0;
702                         win->screen->do_draw_paintcursor= 0;
703                         win->screen->do_draw_drag= 0;
704                 
705                         wm_window_swap_buffers(win);
706
707                         CTX_wm_window_set(C, NULL);
708                 }
709         }
710 }
711
712 void wm_draw_window_clear(wmWindow *win)
713 {
714         bScreen *screen= win->screen;
715         ScrArea *sa;
716         ARegion *ar;
717
718         if(win->drawmethod == USER_DRAW_TRIPLE)
719                 wm_draw_triple_free(win);
720
721         /* clear screen swap flags */
722         if(screen) {
723                 for(sa= screen->areabase.first; sa; sa= sa->next)
724                         for(ar=sa->regionbase.first; ar; ar= ar->next)
725                                 ar->swap= WIN_NONE_OK;
726                 
727                 screen->swap= WIN_NONE_OK;
728         }
729 }
730
731 void wm_draw_region_clear(wmWindow *win, ARegion *ar)
732 {
733         if(win->drawmethod == USER_DRAW_OVERLAP)
734                 wm_flush_regions_down(win->screen, &ar->winrct);
735
736         win->screen->do_draw= 1;
737 }
738