2.5: WM Compositing
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 23 Jan 2009 03:52:52 +0000 (03:52 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 23 Jan 2009 03:52:52 +0000 (03:52 +0000)
* Triple Buffer is now more complete:
  - Proper handling of window resize, duplicate, etc.
  - It now uses 3x3 textures (or less) if the power of two sizes
    do not match well. That still has a worst case wast of 23.4%,
    but better than 300%.
  - It can also use the ARB/NV/EXT_texture_rectangle extension
    now, which may be supported on hardware that does not support
    ARB_texture_non_power_of_two.
  - Gesture, menu and brushe redraws now require no redraws at all
    from the area regions. So even on a high poly scene just moving
    the paint cursor or opening a menu should be fast.

* Testing can be done by setting the "Window Draw Method" in the
  User Preferences in the outliner. "Overlap" is still default,
  since "Triple Buffer" has not been tested on computers other than
  mine, would like to avoid crashing Blender on startup in case
  there is a common bug, but it's ready for testing now.

  - For reference "Full" draws the full window each time.
  - "Triple Buffer" should work for both swap copy and swap exchange
    systems, the latter still need the -E command line option for
    "Overlap".
  - Resizing and going fullscreen still gives flicker here but no
    more than "Full" drawing.

* Partial Redraw was added. ED_region_tag_redraw_partial takes a
  rect in window coordinates to define a subarea of the region.
  On region draw it will then set glScissor to a smaller area, and
  ar->drawrct will always be set to either the partial or full
  window rect. The latter can then be used for clipping in the 3D
  view or clipping interface drawing. Neither is implemented yet.

18 files changed:
source/blender/blenloader/intern/readfile.c
source/blender/editors/include/ED_screen.h
source/blender/editors/interface/interface_regions.c
source/blender/editors/screen/area.c
source/blender/makesdna/DNA_screen_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/intern/rna_userdef.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_draw.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_gesture.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/intern/wm_subwindow.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm_draw.h [new file with mode: 0644]
source/blender/windowmanager/wm_event_system.h

index 54ccc66e5143481ccdb05b5f49b81037f56899c8..0d1eba2048bb00deab517554849a7c5d00d1e92c 100644 (file)
@@ -4007,8 +4007,9 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
                win->handlers.first= win->handlers.last= NULL;
                win->subwindows.first= win->subwindows.last= NULL;
 
-               win->drawtex= 0;
-               win->drawmethod= 0;
+               win->drawdata= NULL;
+               win->drawmethod= -1;
+               win->drawfail= 0;
        }
        
        wm->operators.first= wm->operators.last= NULL;
@@ -4459,6 +4460,8 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
        ar->swinid= 0;
        ar->type= NULL;
        ar->swap= 0;
+       ar->do_draw= 0;
+       memset(&ar->drawrct, 0, sizeof(ar->drawrct));
 }
 
 /* for the saved 2.50 files without regiondata */
@@ -4497,6 +4500,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
        sc->context= NULL;
 
        sc->mainwin= sc->subwinactive= 0;       /* indices */
+       sc->swap= 0;
        
        /* hacky patch... but people have been saving files with the verse-blender,
           causing the handler to keep running for ever, with no means to disable it */
index 809e7378edc66071fab9285b8b472124bfd17c12..1f5f83c852b053c1a88f4b35f2032ff104cf08f9 100644 (file)
@@ -41,6 +41,7 @@ struct bContext;
 struct SpaceType;
 struct AreagionType;
 struct uiBlock;
+struct rcti;
 
 /* regions */
 void   ED_region_do_listen(ARegion *ar, struct wmNotifier *note);
@@ -49,6 +50,7 @@ void  ED_region_exit(struct bContext *C, struct ARegion *ar);
 void   ED_region_pixelspace(struct ARegion *ar);
 void   ED_region_init(struct bContext *C, struct ARegion *ar);
 void   ED_region_tag_redraw(struct ARegion *ar);
+void   ED_region_tag_redraw_partial(struct ARegion *ar, struct rcti *rct);
 
 /* spaces */
 void   ED_spacetypes_init(void);
index e5443b81fa422341e7b9f46c380142794e22e396..de4cf47696758fddaa536004d4488b1f8804900d 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "WM_api.h"
 #include "WM_types.h"
+#include "wm_draw.h"
 #include "wm_subwindow.h"
 #include "wm_window.h"
 
@@ -237,6 +238,8 @@ ARegion *ui_add_temporary_region(bScreen *sc)
 
 void ui_remove_temporary_region(bContext *C, bScreen *sc, ARegion *ar)
 {
+       ar->regiondata= NULL;
+       wm_draw_region_clear(CTX_wm_window(C), ar);
        ED_region_exit(C, ar);
        BKE_area_region_free(NULL, ar);         /* NULL: no spacetype */
        BLI_freelinkN(&sc->regionbase, ar);
@@ -393,8 +396,6 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
 void ui_tooltip_free(bContext *C, ARegion *ar)
 {
        ui_remove_temporary_region(C, CTX_wm_screen(C), ar);
-
-       WM_event_add_notifier(C, NC_WINDOW, NULL);      // XXX provide rect for window
 }
 
 /************************* Creating Menu Blocks **********************/
@@ -711,8 +712,6 @@ void ui_menu_block_free(bContext *C, uiMenuBlockHandle *handle)
 {
        ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region);
        MEM_freeN(handle);
-
-       WM_event_add_notifier(C, NC_WINDOW, NULL);      // XXX provide rect for window
 }
 
 /***************************** Menu Button ***************************/
index cddc7d391c8da2445c035a4c06c50407d2b740d8..3f1d82b193685451c2f9ed08e7e7aeceab366a6e 100644 (file)
@@ -192,9 +192,19 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
        wmWindow *win= CTX_wm_window(C);
        ScrArea *sa= CTX_wm_area(C);
        ARegionType *at= ar->type;
+
+       /* if no partial draw rect set, full rect */
+       if(ar->drawrct.xmin == ar->drawrct.xmax)
+               ar->drawrct= ar->winrct;
+       
+       /* extra clip for safety */
+       ar->drawrct.xmin= MAX2(ar->winrct.xmin, ar->drawrct.xmin);
+       ar->drawrct.ymin= MAX2(ar->winrct.ymin, ar->drawrct.ymin);
+       ar->drawrct.xmax= MIN2(ar->winrct.xmax, ar->drawrct.xmax);
+       ar->drawrct.ymax= MIN2(ar->winrct.ymax, ar->drawrct.ymax);
        
        /* note; this sets state, so we can use wmOrtho and friends */
-       wmSubWindowSet(win, ar->swinid);
+       wmSubWindowScissorSet(win, ar->swinid, &ar->drawrct);
        
        /* optional header info instead? */
        if(ar->headerstr) {
@@ -223,6 +233,7 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
        ED_region_pixelspace(ar);
        
        ar->do_draw= 0;
+       memset(&ar->drawrct, 0, sizeof(ar->drawrct));
 }
 
 /* **********************************
@@ -232,8 +243,29 @@ void ED_region_do_draw(bContext *C, ARegion *ar)
 
 void ED_region_tag_redraw(ARegion *ar)
 {
-       if(ar)
+       if(ar) {
+               /* zero region means full region redraw */
                ar->do_draw= 1;
+               memset(&ar->drawrct, 0, sizeof(ar->drawrct));
+       }
+}
+
+void ED_region_tag_redraw_partial(ARegion *ar, rcti *rct)
+{
+       if(ar) {
+               if(!ar->do_draw) {
+                       /* no redraw set yet, set partial region */
+                       ar->do_draw= 1;
+                       ar->drawrct= *rct;
+               }
+               else if(ar->drawrct.xmin != ar->drawrct.xmax) {
+                       /* partial redraw already set, expand region */
+                       ar->drawrct.xmin= MIN2(ar->drawrct.xmin, rct->xmin);
+                       ar->drawrct.ymin= MIN2(ar->drawrct.ymin, rct->ymin);
+                       ar->drawrct.xmax= MAX2(ar->drawrct.xmax, rct->xmax);
+                       ar->drawrct.ymax= MAX2(ar->drawrct.ymax, rct->ymax);
+               }
+       }
 }
 
 void ED_area_tag_redraw(ScrArea *sa)
@@ -242,7 +274,7 @@ void ED_area_tag_redraw(ScrArea *sa)
        
        if(sa)
                for(ar= sa->regionbase.first; ar; ar= ar->next)
-                       ar->do_draw= 1;
+                       ED_region_tag_redraw(ar);
 }
 
 void ED_area_tag_refresh(ScrArea *sa)
index 0c561536d32882981d4200dba45f9cf667300363..24b397b0b823f1aeae149cd19be720710ba13799 100644 (file)
@@ -54,9 +54,10 @@ typedef struct bScreen {
        short full, winid;                                      /* winid from WM, starts with 1 */
        short do_draw;                                          /* notifier for drawing edges */
        short do_refresh;                                       /* notifier for scale screen, changed screen, etc */
-       short do_gesture;                                       /* notifier for gesture draw. */
+       short do_draw_gesture;                          /* notifier for gesture draw. */
+       short do_draw_paintcursor;                      /* notifier for paint cursor draw. */
        short swap;                                                     /* indicator to survive swap-exchange systems */
-       short pad[2];
+       short pad;
        
        short mainwin;                                          /* screensize subwindow, for screenedges and global menus */
        short subwinactive;                                     /* active subwindow */
@@ -127,6 +128,7 @@ typedef struct ARegion {
        
        View2D v2d;                                     /* 2D-View scrolling/zoom info (most regions are 2d anyways) */
        rcti winrct;                            /* coordinates of region */
+       rcti drawrct;                           /* runtime for partial redraw, same or smaller than winrct */
        short winx, winy;                       /* size */
        
        short swinid;
index 85a8520bfd768c7ebcb48a90550eb74b52d3f5c7..f2cc1f8017c3ff08b465d0cf777b0bd02fd5145c 100644 (file)
@@ -215,6 +215,8 @@ typedef struct UserDef {
        
        short autokey_mode;             /* autokeying mode */
        short autokey_flag;             /* flags for autokeying */
+
+       int wmdrawmethod, pad;
        
        struct ColorBand coba_weight;   /* from texture.h */
 } UserDef;
@@ -325,6 +327,11 @@ extern UserDef U; /* from blenkernel blender.c */
 #define USER_VRML_AUTOSCALE            2
 #define USER_VRML_TWOSIDED             4
 
+/* wm draw method */
+#define USER_DRAW_OVERLAP              0
+#define USER_DRAW_TRIPLE               1
+#define USER_DRAW_FULL                 2
+
 /* tw_flag (transform widget) */
 
 /* gp_settings (Grease Pencil Settings) */
index b0cc98c1a6ee904e222f1d651d8dd90436b94e95..c974fb92978648bbbb14ce085c0ab71db5e0dd8b 100644 (file)
@@ -99,9 +99,8 @@ typedef struct wmWindow {
        
        struct wmSubWindow *curswin;    /* internal for wm_subwindow.c only */
 
-       unsigned int drawtex;           /* internal for wm_draw.c only */
-       int drawtexw, drawtexh;         /* internal for wm_draw.c only */
-       int drawmethod;                         /* internal for wm_draw.c only */
+       int drawmethod, drawfail;       /* internal for wm_draw.c only */
+       void *drawdata;                         /* internal for wm_draw.c only */
        
        ListBase timers;
        
index 64db4a5f191f2d52376241c33a8fcdc4751588d5..24f5df4dbcfb14235e93860ed6ab9d2039d3e602 100644 (file)
@@ -1513,6 +1513,12 @@ static void rna_def_userdef_system(StructRNA *srna)
                {2048, "AUDIO_SAMPLES_2048", "2048", "Set audio mixing buffer size to 2048 samples"},
                {0, NULL, NULL, NULL}};
 
+       static EnumPropertyItem draw_method_items[] = {
+               {USER_DRAW_TRIPLE, "TRIPLE_BUFFER", "Triple Buffer", "Use a third buffer for minimal redraws at the cost of more memory."},
+               {USER_DRAW_OVERLAP, "OVERLAP", "Overlap", "Redraw all overlapping regions, minimal memory usage but more redraws."},
+               {USER_DRAW_FULL, "FULL", "Full", "Do a full redraw each time, slow, only use for reference or when all else fails."},
+               {0, NULL, NULL, NULL}};
+
        /* System & OpenGL */
 
        prop= RNA_def_property(srna, "solid_lights", PROP_COLLECTION, PROP_NONE);
@@ -1592,6 +1598,11 @@ static void rna_def_userdef_system(StructRNA *srna)
        RNA_def_property_range(prop, 1, 3600);
        RNA_def_property_ui_text(prop, "Texture Collection Rate", "Number of seconds between each run of the GL texture garbage collector.");
 
+       prop= RNA_def_property(srna, "window_draw_method", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "wmdrawmethod");
+       RNA_def_property_enum_items(prop, draw_method_items);
+       RNA_def_property_ui_text(prop, "Window Draw Method", "Drawing method used by the window manager.");
+
        prop= RNA_def_property(srna, "audio_mixing_buffer", PROP_ENUM, PROP_NONE);
        RNA_def_property_enum_sdna(prop, NULL, "mixbufsize");
        RNA_def_property_enum_items(prop, audio_mixing_samples_items);
index 9584751a77558991bd87f4fb01ce2f17715d9ee9..7921ad8c608ac0106dcb82433429c59e3cd6a6bc 100644 (file)
@@ -155,7 +155,8 @@ struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int
 void           WM_gesture_end(struct bContext *C, struct wmGesture *gesture);
 
                        /* OpenGL wrappers, mimicking opengl syntax */
-void           wmSubWindowSet          (struct wmWindow *win, int swinid);
+void           wmSubWindowSet                  (struct wmWindow *win, int swinid);
+void           wmSubWindowScissorSet   (struct wmWindow *win, int swinid, struct rcti *srct);
 
 void           wmLoadMatrix            (float mat[][4]);
 void           wmGetMatrix                     (float mat[][4]);
index f76bfb511b389470f5c99065c2d6e985562b49cd..164a49ac63dc46e8d55d0fbf23d61c5496664cee 100644 (file)
@@ -44,6 +44,7 @@
 #include "wm_window.h"
 #include "wm_event_system.h"
 #include "wm_event_types.h"
+#include "wm_draw.h"
 #include "wm.h"
 
 #include "ED_screen.h"
index 8537c7453032ed680995805c0d924cefd316125d..643a1370f80a7803d1e929a20b8c5a6fb52c855c 100644 (file)
@@ -47,6 +47,7 @@
 #include "WM_api.h"
 #include "WM_types.h"
 #include "wm.h"
+#include "wm_draw.h"
 #include "wm_window.h"
 #include "wm_event_system.h"
 
 #define WIN_FRONT_OK    2
 #define WIN_BOTH_OK            3
 
-/* draw method */
-#define USER_DRAW_ALL                  0
-#define USER_DRAW_OVERLAP_ALL  1
-#define USER_DRAW_OVERLAP              2
-#define USER_DRAW_TRIPLE               3
-
 /* ********************* drawing, swap ****************** */
 
-static void wm_paintcursor_draw(bContext *C)
+static void wm_paintcursor_draw(bContext *C, ARegion *ar)
 {
        wmWindowManager *wm= CTX_wm_manager(C);
        
        if(wm->paintcursors.first) {
                wmWindow *win= CTX_wm_window(C);
+               bScreen *screen= win->screen;
                wmPaintCursor *pc;
-               
-               for(pc= wm->paintcursors.first; pc; pc= pc->next) {
-                       if(pc->poll(C)) {
-                               ARegion *ar= CTX_wm_region(C);
-                               pc->draw(C, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin);
+
+               if(screen->subwinactive == ar->swinid) {
+                       for(pc= wm->paintcursors.first; pc; pc= pc->next) {
+                               if(pc->poll(C)) {
+                                       ARegion *ar= CTX_wm_region(C);
+                                       pc->draw(C, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin);
+                               }
                        }
                }
        }
@@ -84,7 +82,7 @@ static void wm_paintcursor_draw(bContext *C)
 /********************** draw all **************************/
 /* - reference method, draw all each time                 */
 
-static void wm_method_draw_all(bContext *C, wmWindow *win)
+static void wm_method_draw_full(bContext *C, wmWindow *win)
 {
        bScreen *screen= win->screen;
        ScrArea *sa;
@@ -98,8 +96,7 @@ static void wm_method_draw_all(bContext *C, wmWindow *win)
                        if(ar->swinid) {
                                CTX_wm_region_set(C, ar);
                                ED_region_do_draw(C, ar);
-                               if(screen->subwinactive==ar->swinid)
-                                       wm_paintcursor_draw(C);
+                               wm_paintcursor_draw(C, ar);
                                ED_area_overdraw_flush(C, sa, ar);
                                CTX_wm_region_set(C, NULL);
                        }
@@ -120,7 +117,7 @@ static void wm_method_draw_all(bContext *C, wmWindow *win)
                }
        }
 
-       if(screen->do_gesture)
+       if(screen->do_draw_gesture)
                wm_gesture_draw(win);
 }
 
@@ -129,12 +126,9 @@ static void wm_method_draw_all(bContext *C, wmWindow *win)
 /* - it also handles swap exchange optionally, assuming   */
 /*   that on swap no clearing happens and we get back the */
 /*   same buffer as we swapped to the front               */
-/* - TODO for swap exchange in full screen mode, and then */
-/*   switching to another window seems to invalidate the  */
-/*   swap flags, probably best to clear then?             */
 
 /* mark area-regions to redraw if overlapped with rect */
-static void wm_overlap_regions_down(bScreen *screen, rcti *dirty)
+static void wm_flush_regions_down(bScreen *screen, rcti *dirty)
 {
        ScrArea *sa;
        ARegion *ar;
@@ -143,6 +137,7 @@ static void wm_overlap_regions_down(bScreen *screen, rcti *dirty)
                for(ar= sa->regionbase.first; ar; ar= ar->next) {
                        if(BLI_isect_rcti(dirty, &ar->winrct, NULL)) {
                                ar->do_draw= 1;
+                               memset(&ar->drawrct, 0, sizeof(ar->drawrct));
                                ar->swap= WIN_NONE_OK;
                        }
                }
@@ -150,13 +145,14 @@ static void wm_overlap_regions_down(bScreen *screen, rcti *dirty)
 }
 
 /* mark menu-regions to redraw if overlapped with rect */
-static void wm_overlap_regions_up(bScreen *screen, rcti *dirty)
+static void wm_flush_regions_up(bScreen *screen, rcti *dirty)
 {
        ARegion *ar;
        
        for(ar= screen->regionbase.first; ar; ar= ar->next) {
                if(BLI_isect_rcti(dirty, &ar->winrct, NULL)) {
                        ar->do_draw= 1;
+                       memset(&ar->drawrct, 0, sizeof(ar->drawrct));
                        ar->swap= WIN_NONE_OK;
                }
        }
@@ -175,17 +171,17 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win)
                for(sa= screen->areabase.first; sa; sa= sa->next)
                        for(ar= sa->regionbase.first; ar; ar= ar->next)
                                if(ar->swinid && ar->do_draw)
-                                       wm_overlap_regions_up(screen, &ar->winrct);
+                                       wm_flush_regions_up(screen, &ar->winrct);
                
                /* flush between overlapping regions */
                for(ar= screen->regionbase.last; ar; ar= ar->prev)
                        if(ar->swinid && ar->do_draw)
-                               wm_overlap_regions_up(screen, &ar->winrct);
+                               wm_flush_regions_up(screen, &ar->winrct);
                
                /* flush redraws of overlapping regions down to area regions */
                for(ar= screen->regionbase.last; ar; ar= ar->prev)
                        if(ar->swinid && ar->do_draw)
-                               wm_overlap_regions_down(screen, &ar->winrct);
+                               wm_flush_regions_down(screen, &ar->winrct);
        }
 
        /* draw marked area regions */
@@ -197,8 +193,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win)
                                if(ar->do_draw) {
                                        CTX_wm_region_set(C, ar);
                                        ED_region_do_draw(C, ar);
-                                       if(screen->subwinactive==ar->swinid)
-                                               wm_paintcursor_draw(C);
+                                       wm_paintcursor_draw(C, ar);
                                        ED_area_overdraw_flush(C, sa, ar);
                                        CTX_wm_region_set(C, NULL);
 
@@ -209,8 +204,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win)
                                        if(ar->swap == WIN_FRONT_OK) {
                                                CTX_wm_region_set(C, ar);
                                                ED_region_do_draw(C, ar);
-                                               if(screen->subwinactive==ar->swinid)
-                                                       wm_paintcursor_draw(C);
+                                               wm_paintcursor_draw(C, ar);
                                                ED_area_overdraw_flush(C, sa, ar);
                                                CTX_wm_region_set(C, NULL);
 
@@ -257,34 +251,51 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win)
                }
        }
 
-       if(screen->do_gesture)
+       if(screen->do_draw_gesture)
                wm_gesture_draw(win);
 }
 
-/******************** draw overlap ************************/
+#if 0
+/******************** draw damage ************************/
 /* - not implemented                                      */
 
-static void wm_method_draw_overlap(bContext *C, wmWindow *win)
+static void wm_method_draw_damage(bContext *C, wmWindow *win)
 {
        wm_method_draw_all(C, win);
 }
+#endif
 
 /****************** draw triple buffer ********************/
 /* - area regions are written into a texture, without any */
 /*   of the overlapping menus, brushes, gestures. these   */
 /*   are redrawn each time.                               */
-/* - work in progress still ..                            */
-/* - TODO glDeleteTextures ..                             */
-/* - TODO handle window resize                            */
-/* - TODO avoid region redraw for brush and gestures..    */
-/* - TODO use multiple smaller textures for cards without */
-/*   non power of two support                             */
+/*                                                        */
+/* - if non-power of two textures are supported, that is  */
+/*   used. if not, multiple smaller ones are used, with   */
+/*   worst case wasted space being 23.4% for 3x3 textures */
+
+#define MAX_N_TEX 3
+
+typedef struct wmDrawTriple {
+       GLuint bind[MAX_N_TEX*MAX_N_TEX];
+       int x[MAX_N_TEX], y[MAX_N_TEX];
+       int nx, ny;
+       GLenum target;
+} wmDrawTriple;
 
 static int is_pow2(int n)
 {
        return ((n)&(n-1))==0;
 }
 
+static int smaller_pow2(int n)
+{
+    while (!is_pow2(n))
+               n= n&(n-1);
+
+       return n;
+}
+
 static int larger_pow2(int n)
 {
        if (is_pow2(n))
@@ -296,100 +307,229 @@ static int larger_pow2(int n)
        return n*2;
 }
 
-static void wm_method_draw_triple(bContext *C, wmWindow *win)
+static void split_width(int x, int n, int *splitx, int *nx)
 {
-       wmWindowManager *wm= CTX_wm_manager(C);
-       bScreen *screen= win->screen;
-       ScrArea *sa;
-       ARegion *ar;
-       float halfx, halfy, ratiox, ratioy;
-       int copytex= 0;
+       int a, newnx, waste;
 
-       if(win->drawtex) {
-               glClearColor(0, 0, 0, 0);
-               glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+       /* if already power of two just use it */
+       if(is_pow2(x)) {
+               splitx[0]= x;
+               (*nx)++;
+               return;
+       }
 
-               wmSubWindowSet(win, screen->mainwin);
+       if(n == 1) {
+               /* last part, we have to go larger */
+               splitx[0]= larger_pow2(x);
+               (*nx)++;
+       }
+       else {
+               /* two or more parts to go, use smaller part */
+               splitx[0]= smaller_pow2(x);
+               newnx= ++(*nx);
+               split_width(x-splitx[0], n-1, splitx+1, &newnx);
+
+               for(waste=0, a=0; a<n; a++)
+                       waste += splitx[a];
+
+               /* if we waste more space or use the same amount,
+                * revert deeper splits and just use larger */
+               if(waste >= larger_pow2(x)) {
+                       splitx[0]= larger_pow2(x);
+                       memset(splitx+1, 0, sizeof(int)*(n-1));
+               }
+               else
+                       *nx= newnx;
+       }
+}
 
-               /* wmOrtho for the screen has this same offset */
-               ratiox= win->sizex/(float)win->drawtexw;
-               ratioy= win->sizey/(float)win->drawtexh;
-               halfx= 0.375f/win->drawtexw;
-               halfy= 0.375f/win->drawtexh;
-
-               glBindTexture(GL_TEXTURE_2D, win->drawtex);
-               glEnable(GL_TEXTURE_2D);
-
-               glColor3f(1.0f, 1.0f, 1.0f);
-               glBegin(GL_QUADS);
-                       glTexCoord2f(halfx, halfy);
-                       glVertex2f(0.0f, 0.0f);
-                       glTexCoord2f(ratiox+halfx, halfy);
-                       glVertex2f(win->sizex, 0.0f);
-                       glTexCoord2f(ratiox+halfx, ratioy+halfy);
-                       glVertex2f(win->sizex, win->sizey);
-                       glTexCoord2f(halfx, ratioy+halfy);
-                       glVertex2f(0.0f, win->sizey);
-               glEnd();
-
-               glDisable(GL_TEXTURE_2D);
-               glBindTexture(GL_TEXTURE_2D, 0);
+static void wm_draw_triple_free(wmWindow *win)
+{
+       if(win->drawdata) {
+               wmDrawTriple *triple= win->drawdata;
+
+               glDeleteTextures(triple->nx*triple->ny, triple->bind);
+               MEM_freeN(triple);
+
+               win->drawdata= NULL;
+       }
+}
+
+static void wm_draw_triple_fail(bContext *C, wmWindow *win)
+{
+       wm_draw_window_clear(win);
+
+       win->drawfail= 1;
+       wm_method_draw_overlap_all(C, win);
+}
+
+static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
+{
+       GLint format;
+       int x, y;
+
+       /* compute texture sizes */
+       if(GLEW_ARB_texture_rectangle || GLEW_NV_texture_rectangle || GLEW_EXT_texture_rectangle) {
+               triple->target= GL_TEXTURE_RECTANGLE_ARB;
+               triple->nx= 1;
+               triple->ny= 1;
+               triple->x[0]= win->sizex;
+               triple->y[0]= win->sizey;
+       }
+       else if(GLEW_ARB_texture_non_power_of_two) {
+               triple->target= GL_TEXTURE_2D;
+               triple->nx= 1;
+               triple->ny= 1;
+               triple->x[0]= win->sizex;
+               triple->y[0]= win->sizey;
        }
        else {
-               GLint format;
+               triple->target= GL_TEXTURE_2D;
+               triple->nx= 0;
+               triple->ny= 0;
+               split_width(win->sizex, MAX_N_TEX, triple->x, &triple->nx);
+               split_width(win->sizey, MAX_N_TEX, triple->y, &triple->ny);
+       }
 
-               glGenTextures(1, (GLuint *)&win->drawtex);
+       /* generate texture names */
+       glGenTextures(triple->nx*triple->ny, triple->bind);
 
-               if(!win->drawtex) {
-                       /* not the typical failure case but we handle it anyway */
-                       win->drawmethod= USER_DRAW_OVERLAP_ALL;
-                       wm_method_draw_overlap_all(C, win);
+       if(!triple->bind[0]) {
+               /* not the typical failure case but we handle it anyway */
+               printf("WM: failed to allocate texture for triple buffer drawing (glGenTextures).\n");
+               return 0;
+       }
 
-                       printf("failed to allocate texture for triple buffer drawing (generate).\n");
-                       return;
+       for(y=0; y<triple->ny; y++) {
+               for(x=0; x<triple->nx; x++) {
+                       /* proxy texture is only guaranteed to test for the cases that
+                        * there is only one texture in use, which may not be the case */
+                       glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
+                       glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGB8, triple->x[x], triple->y[y], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+                       glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
+
+                       if(format != GL_RGB8) {
+                               glBindTexture(triple->target, 0);
+                               printf("WM: failed to allocate texture for triple buffer drawing (GL_PROXY_TEXTURE_2D).\n");
+                               return 0;
+                       }
+
+                       /* setup actual texture */
+                       glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
+                       glTexImage2D(triple->target, 0, GL_RGB8, triple->x[x], triple->y[y], 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+                       glTexParameteri(triple->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+                       glTexParameteri(triple->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+                       // glColor still used with this enabled?
+                       // glTexEnvi(triple->target, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+                       glBindTexture(triple->target, 0);
+
+                       /* not sure if this works everywhere .. */
+                       if(glGetError() == GL_OUT_OF_MEMORY) {
+                               printf("WM: failed to allocate texture for triple buffer drawing (out of memory).\n");
+                               return 0;
+                       }
                }
+       }
 
-               win->drawtexw= win->sizex;
-               win->drawtexh= win->sizey;
+       return 1;
+}
 
-               if(!GLEW_ARB_texture_non_power_of_two) {
-                       win->drawtexw= larger_pow2(win->drawtexw);
-                       win->drawtexh= larger_pow2(win->drawtexh);
+static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple)
+{
+       float halfx, halfy, ratiox, ratioy;
+       int x, y, sizex, sizey, offx, offy;
+
+       glEnable(triple->target);
+
+       for(y=0, offy=0; y<triple->ny; offy+=triple->y[y], y++) {
+               for(x=0, offx=0; x<triple->nx; offx+=triple->x[x], x++) {
+                       sizex= (x == triple->nx-1)? win->sizex-offx: triple->x[x];
+                       sizey= (y == triple->ny-1)? win->sizey-offy: triple->y[y];
+
+                       /* wmOrtho for the screen has this same offset */
+                       ratiox= sizex;
+                       ratioy= sizey;
+                       halfx= 0.375f;
+                       halfy= 0.375f;
+
+                       /* texture rectangle has unnormalized coordinates */
+                       if(triple->target == GL_TEXTURE_2D) {
+                               ratiox /= triple->x[x];
+                               ratioy /= triple->y[y];
+                               halfx /= triple->x[x];
+                               halfy /= triple->y[y];
+                       }
+
+                       glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
+
+                       glColor3f(1.0f, 1.0f, 1.0f);
+                       glBegin(GL_QUADS);
+                               glTexCoord2f(halfx, halfy);
+                               glVertex2f(offx, offy);
+
+                               glTexCoord2f(ratiox+halfx, halfy);
+                               glVertex2f(offx+sizex, offy);
+
+                               glTexCoord2f(ratiox+halfx, ratioy+halfy);
+                               glVertex2f(offx+sizex, offy+sizey);
+
+                               glTexCoord2f(halfx, ratioy+halfy);
+                               glVertex2f(offx, offy+sizey);
+                       glEnd();
                }
+       }
 
-               glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGB8, win->drawtexw, win->drawtexh, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-               glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format);
+       glBindTexture(triple->target, 0);
+       glDisable(triple->target);
+}
 
-               if(format != GL_RGB8) {
-                       /* proxy texture is only guaranteed to test for the cases that
-                        * there is only one texture in use, which may not be the case */
-                       glDeleteTextures(1, (GLuint *)&win->drawtex);
+static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
+{
+       int x, y, sizex, sizey, offx, offy;
 
-                       win->drawmethod= USER_DRAW_OVERLAP_ALL;
-                       wm_method_draw_overlap_all(C, win);
+       for(y=0, offy=0; y<triple->ny; offy+=triple->y[y], y++) {
+               for(x=0, offx=0; x<triple->nx; offx+=triple->x[x], x++) {
+                       sizex= (x == triple->nx-1)? win->sizex-offx: triple->x[x];
+                       sizey= (y == triple->ny-1)? win->sizey-offy: triple->y[y];
 
-                       printf("failed to allocate texture for triple buffer drawing (proxy test).\n");
-                       return;
+                       glBindTexture(triple->target, triple->bind[x + y*triple->nx]);
+                       glCopyTexSubImage2D(triple->target, 0, 0, 0, offx, offy, sizex, sizey);
                }
+       }
 
-               glBindTexture(GL_TEXTURE_2D, win->drawtex);
-               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, win->drawtexw, win->drawtexh, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-               glBindTexture(GL_TEXTURE_2D, 0);
+       glBindTexture(triple->target, 0);
+}
 
-               if(glGetError() == GL_OUT_OF_MEMORY) {
-                       /* not sure if this works everywhere .. */
-                       glDeleteTextures(1, (GLuint *)&win->drawtex);
+static void wm_method_draw_triple(bContext *C, wmWindow *win)
+{
+       wmWindowManager *wm= CTX_wm_manager(C);
+       wmDrawTriple *triple;
+       bScreen *screen= win->screen;
+       ScrArea *sa;
+       ARegion *ar;
+       int copytex= 0;
+
+       if(win->drawdata) {
+               glClearColor(0, 0, 0, 0);
+               glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+               wmSubWindowSet(win, screen->mainwin);
+
+               wm_triple_draw_textures(win, win->drawdata);
 
-                       win->drawmethod= USER_DRAW_OVERLAP_ALL;
-                       wm_method_draw_overlap_all(C, win);
+               triple= win->drawdata;
+       }
+       else {
+               win->drawdata= MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
 
-                       printf("failed to allocate texture for triple buffer drawing (out of memory).\n");
+               if(!wm_triple_gen_textures(win, win->drawdata)) {
+                       wm_draw_triple_fail(C, win);
                        return;
                }
        }
 
+       triple= win->drawdata;
+
        /* draw marked area regions */
        for(sa= screen->areabase.first; sa; sa= sa->next) {
                CTX_wm_area_set(C, sa);
@@ -398,6 +538,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
                        if(ar->swinid && ar->do_draw) {
                                CTX_wm_region_set(C, ar);
                                ED_region_do_draw(C, ar);
+                               ED_area_overdraw_flush(C, sa, ar);
                                CTX_wm_region_set(C, NULL);
                                copytex= 1;
                        }
@@ -410,10 +551,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
                wmSubWindowSet(win, screen->mainwin);
                ED_area_overdraw(C);
 
-               glBindTexture(GL_TEXTURE_2D, win->drawtex);
-               glReadBuffer(GL_BACK);
-               glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, win->sizex, win->sizey);
-               glBindTexture(GL_TEXTURE_2D, 0);
+               wm_triple_copy_textures(win, triple);
        }
 
        /* after area regions so we can do area 'overlay' drawing */
@@ -428,7 +566,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
                }
        }
 
-       if(win->screen->do_gesture)
+       if(win->screen->do_draw_gesture)
                wm_gesture_draw(win);
 
        if(wm->paintcursors.first) {
@@ -440,7 +578,7 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
 
                                        wmSubWindowSet(win, ar->swinid);
                                        ED_region_pixelspace(ar);
-                                       wm_paintcursor_draw(C);
+                                       wm_paintcursor_draw(C, ar);
 
                                        CTX_wm_region_set(C, NULL);
                                        CTX_wm_area_set(C, NULL);
@@ -464,7 +602,9 @@ static int wm_draw_update_test_window(wmWindow *win)
                return 1;
        if(win->screen->do_draw)
                return 1;
-       if(win->screen->do_gesture)
+       if(win->screen->do_draw_gesture)
+               return 1;
+       if(win->screen->do_draw_paintcursor)
                return 1;
        
        for(ar= win->screen->regionbase.first; ar; ar= ar->next)
@@ -485,7 +625,10 @@ void wm_draw_update(bContext *C)
        wmWindow *win;
        
        for(win= wm->windows.first; win; win= win->next) {
-               win->drawmethod= USER_DRAW_OVERLAP_ALL;
+               if(win->drawmethod != U.wmdrawmethod) {
+                       wm_draw_window_clear(win);
+                       win->drawmethod= U.wmdrawmethod;
+               }
 
                if(wm_draw_update_test_window(win)) {
                        CTX_wm_window_set(C, win);
@@ -497,14 +640,19 @@ void wm_draw_update(bContext *C)
                        if(win->screen->do_refresh)
                                ED_screen_refresh(wm, win);
 
-                       if(win->drawmethod == USER_DRAW_ALL)
-                               wm_method_draw_all(C, win);
-                       else if(win->drawmethod == USER_DRAW_OVERLAP_ALL)
+                       if(win->drawfail)
                                wm_method_draw_overlap_all(C, win);
+                       else if(win->drawmethod == USER_DRAW_FULL)
+                               wm_method_draw_full(C, win);
                        else if(win->drawmethod == USER_DRAW_OVERLAP)
-                               wm_method_draw_overlap(C, win);
-                       else if(win->drawmethod == USER_DRAW_TRIPLE)
+                               wm_method_draw_overlap_all(C, win);
+                       /*else if(win->drawmethod == USER_DRAW_DAMAGE)
+                               wm_method_draw_damage(C, win);*/
+                       else // if(win->drawmethod == USER_DRAW_TRIPLE)
                                wm_method_draw_triple(C, win);
+
+                       win->screen->do_draw_gesture= 0;
+                       win->screen->do_draw_paintcursor= 0;
                
                        wm_window_swap_buffers(win);
 
@@ -513,3 +661,30 @@ void wm_draw_update(bContext *C)
        }
 }
 
+void wm_draw_window_clear(wmWindow *win)
+{
+       bScreen *screen= win->screen;
+       ScrArea *sa;
+       ARegion *ar;
+
+       if(win->drawmethod == USER_DRAW_TRIPLE)
+               wm_draw_triple_free(win);
+
+       /* clear screen swap flags */
+       if(screen) {
+               for(sa= screen->areabase.first; sa; sa= sa->next)
+                       for(ar=sa->regionbase.first; ar; ar= ar->next)
+                               ar->swap= WIN_NONE_OK;
+               
+               screen->swap= WIN_NONE_OK;
+       }
+}
+
+void wm_draw_region_clear(wmWindow *win, ARegion *ar)
+{
+       if(win->drawmethod == USER_DRAW_OVERLAP)
+               wm_flush_regions_down(win->screen, &ar->winrct);
+
+       win->screen->do_draw= 1;
+}
+
index 6fc67242d69bae46ffff6ce1f393473523596391..6c0339f87b2f2ca679efd500c1c0c859a7c57829 100644 (file)
@@ -727,10 +727,17 @@ static ARegion *region_event_inside(bContext *C, int x, int y)
 
 static void wm_paintcursor_tag(bContext *C, wmPaintCursor *pc, ARegion *ar)
 {
-       if(ar)
-               for(; pc; pc= pc->next) 
-                       if(pc->poll(C))
-                               ED_region_tag_redraw(ar);
+       if(ar) {
+               for(; pc; pc= pc->next) {
+                       if(pc->poll(C)) {
+                               wmWindow *win= CTX_wm_window(C);
+                               win->screen->do_draw_paintcursor= 1;
+
+                               if(win->drawmethod != USER_DRAW_TRIPLE)
+                                       ED_region_tag_redraw(ar);
+                       }
+               }
+       }
 }
 
 /* called on mousemove, check updates for paintcursors */
index 5847581d32a2375c2dfdbe66a6e68a9424ec1ab7..2f4ded00de508d5c9536f596404e0604cde3b85a 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "DNA_screen_types.h"
 #include "DNA_vec_types.h"
+#include "DNA_userdef_types.h"
 #include "DNA_windowmanager_types.h"
 
 #include "MEM_guardedalloc.h"
@@ -259,11 +260,13 @@ void wm_gesture_draw(wmWindow *win)
 
 void wm_gesture_tag_redraw(bContext *C)
 {
+       wmWindow *win= CTX_wm_window(C);
        bScreen *screen= CTX_wm_screen(C);
        ARegion *ar= CTX_wm_region(C);
        
        if(screen)
-               screen->do_gesture= 1;
-       if(ar)
+               screen->do_draw_gesture= 1;
+       if(ar && win->drawmethod != USER_DRAW_TRIPLE)
                ED_region_tag_redraw(ar);
 }
+
index 58f2be809229b4e5c58338ad2271493ec4f79d9f..b9b7f83636f30ec7fad17460acf5a0beb962ba7a 100644 (file)
@@ -285,13 +285,19 @@ static void recent_filelist(char *pup)
 static int recentfile_exec(bContext *C, wmOperator *op)
 {
        int event= RNA_enum_get(op->ptr, "nr");
-       
+
+       // XXX wm in context is not set correctly after WM_read_file -> crash
+       // do it before for now, but is this correct with multiple windows?
+
        if(event>0) {
-               if (G.sce[0] && (event==1))
+               if (G.sce[0] && (event==1)) {
+                       WM_event_add_notifier(C, NC_WINDOW, NULL);
                        WM_read_file(C, G.sce, op->reports);
+               }
                else {
                        struct RecentFile *recent = BLI_findlink(&(G.recent_files), event-2);
                        if(recent) {
+                               WM_event_add_notifier(C, NC_WINDOW, NULL);
                                WM_read_file(C, recent->filename, op->reports);
                        }
                }
@@ -347,11 +353,12 @@ static int wm_mainfile_exec(bContext *C, wmOperator *op)
        char filename[FILE_MAX];
        RNA_string_get(op->ptr, "filename", filename);
        
-       WM_read_file(C, filename, op->reports);
-       
        // XXX wm in context is not set correctly after WM_read_file -> crash
-       // WM_event_add_notifier(C, NC_WINDOW, NULL);
+       // do it before for now, but is this correct with multiple windows?
+       WM_event_add_notifier(C, NC_WINDOW, NULL);
 
+       WM_read_file(C, filename, op->reports);
+       
        return 0;
 }
 
index 8431317f4d95da788bd4fd4a663ca3c0f6d3158e..255d22191e2c991a6551d20452c32e29dc68416a 100644 (file)
@@ -231,8 +231,7 @@ void wm_subwindow_position(wmWindow *win, int swinid, rcti *winrct)
 static wmWindow *_curwindow= NULL;
 static wmSubWindow *_curswin= NULL;
 
-/* enable the WM versions of opengl calls */
-void wmSubWindowSet(wmWindow *win, int swinid)
+void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct)
 {
        int width, height;
        _curswin= swin_from_swinid(win, swinid);
@@ -248,7 +247,14 @@ void wmSubWindowSet(wmWindow *win, int swinid)
        width= _curswin->winrct.xmax - _curswin->winrct.xmin + 1;
        height= _curswin->winrct.ymax - _curswin->winrct.ymin + 1;
        glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
-       glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
+
+       if(srct) {
+               width= srct->xmax - srct->xmin + 1;
+               height= srct->ymax - srct->ymin + 1;
+               glScissor(srct->xmin, srct->ymin, width, height);
+       }
+       else
+               glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height);
        
        glMatrixMode(GL_PROJECTION);
        glLoadMatrixf(&_curswin->winmat[0][0]);
@@ -256,7 +262,13 @@ void wmSubWindowSet(wmWindow *win, int swinid)
        glLoadMatrixf(&_curswin->viewmat[0][0]);
        
        glFlush();
-       
+}
+
+
+/* enable the WM versions of opengl calls */
+void wmSubWindowSet(wmWindow *win, int swinid)
+{
+       wmSubWindowScissorSet(win, swinid, NULL);
 }
 
 void wmLoadMatrix(float mat[][4])
index 73860af5f85ad02db5a3a7e2ba0b3594ba86ba67..130d72dffd83fed4cd59b7764a3d5883c94b9a38 100644 (file)
@@ -49,6 +49,7 @@
 #include "WM_api.h"
 #include "WM_types.h"
 #include "wm.h"
+#include "wm_draw.h"
 #include "wm_window.h"
 #include "wm_subwindow.h"
 #include "wm_event_system.h"
@@ -152,6 +153,9 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
        win->screen= ED_screen_duplicate(win, winorig->screen);
        win->screen->do_refresh= 1;
        win->screen->do_draw= 1;
+
+       win->drawmethod= -1;
+       win->drawdata= NULL;
        
        return win;
 }
@@ -162,6 +166,7 @@ static void wm_window_close(bContext *C, wmWindow *win)
        wmWindowManager *wm= CTX_wm_manager(C);
        BLI_remlink(&wm->windows, win);
        
+       wm_draw_window_clear(win);
        WM_event_remove_handlers(C, &win->handlers);
        ED_screen_exit(C, win, win->screen);
        wm_window_free(C, win);
@@ -274,6 +279,9 @@ wmWindow *WM_window_open(bContext *C, rcti *rect)
        win->posy= rect->ymin;
        win->sizex= rect->xmax - rect->xmin;
        win->sizey= rect->ymax - rect->ymin;
+
+       win->drawmethod= -1;
+       win->drawdata= NULL;
        
        wm_window_add_ghostwindow(wm, "Blender", win);
        
@@ -490,6 +498,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private)
                                        }
                                
                                        wm_window_make_drawable(C, win);
+                                       wm_draw_window_clear(win);
                                        WM_event_add_notifier(C, NC_SCREEN|NA_EDITED, NULL);
                                }
                                break;
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
new file mode 100644 (file)
index 0000000..4b462b1
--- /dev/null
@@ -0,0 +1,42 @@
+/**
+ * $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef WM_DRAW_H
+#define WM_DRAW_H
+
+struct bContext;
+struct wmWindow;
+struct ARegion;
+
+/* wm_draw.c */
+void           wm_draw_update                  (struct bContext *C);
+void           wm_draw_window_clear    (struct wmWindow *win);
+void           wm_draw_region_clear    (struct wmWindow *win, struct ARegion *ar);
+
+#endif /* WM_DRAW_H */
+
index 26c0b23df30a134749dca1b24f953620e42cdd07..8a5806497a395e3459802cc9b69a406f6dfe1359 100644 (file)
@@ -86,7 +86,6 @@ void          wm_event_do_handlers    (bContext *C);
 void           wm_event_add_ghostevent(wmWindow *win, int type, void *customdata);
 
 void           wm_event_do_notifiers   (bContext *C);
-void           wm_draw_update                  (bContext *C);
 
 /* wm_keymap.c */