Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/CMakeLists.txt1
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c284
-rw-r--r--source/blender/windowmanager/intern/wm_files.c4
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c43
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c534
-rw-r--r--source/blender/windowmanager/intern/wm_window.c27
-rw-r--r--source/blender/windowmanager/wm.h7
-rw-r--r--source/blender/windowmanager/wm_draw.h21
9 files changed, 873 insertions, 49 deletions
diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt
index 78b5d499644..86f5fff4aef 100644
--- a/source/blender/windowmanager/CMakeLists.txt
+++ b/source/blender/windowmanager/CMakeLists.txt
@@ -64,6 +64,7 @@ set(SRC
intern/wm_operators.c
intern/wm_subwindow.c
intern/wm_window.c
+ intern/wm_stereo.c
WM_api.h
WM_keymap.h
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index e64d08f38e1..dbeea80ba82 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -103,6 +103,7 @@ void WM_window_open_temp (struct bContext *C, struct rcti *position, int type);
/* returns true if draw method is triple buffer */
bool WM_is_draw_triple(struct wmWindow *win);
+bool WM_stereo3d_enabled(struct wmWindow *win, bool only_fullscreen_test);
/* files */
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 7440570f4a0..16fe9ca5142 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -48,9 +48,11 @@
#include "BIF_gl.h"
#include "BKE_context.h"
+#include "BKE_image.h"
#include "GHOST_C-api.h"
+#include "ED_node.h"
#include "ED_view3d.h"
#include "ED_screen.h"
@@ -165,6 +167,7 @@ static void wm_method_draw_full(bContext *C, wmWindow *win)
if (ar->swinid) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
}
@@ -175,12 +178,14 @@ static void wm_method_draw_full(bContext *C, wmWindow *win)
}
ED_screen_draw(win);
+ win->screen->do_draw = false;
/* draw overlapping regions */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
if (ar->swinid) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_menu_set(C, NULL);
}
}
@@ -278,6 +283,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
if (ar->do_draw) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
@@ -288,6 +294,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
if (ar->swap == WIN_FRONT_OK) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
wm_paintcursor_draw(C, ar);
CTX_wm_region_set(C, NULL);
@@ -300,7 +307,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
}
}
}
-
+
wm_area_mark_invalid_backbuf(sa);
CTX_wm_area_set(C, NULL);
}
@@ -308,6 +315,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
/* after area regions so we can do area 'overlay' drawing */
if (screen->do_draw) {
ED_screen_draw(win);
+ win->screen->do_draw = false;
if (exchange)
screen->swap = WIN_FRONT_OK;
@@ -315,6 +323,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
else if (exchange) {
if (screen->swap == WIN_FRONT_OK) {
ED_screen_draw(win);
+ win->screen->do_draw = false;
screen->swap = WIN_BOTH_OK;
}
else if (screen->swap == WIN_BACK_OK)
@@ -328,6 +337,7 @@ static void wm_method_draw_overlap_all(bContext *C, wmWindow *win, int exchange)
if (ar->swinid && ar->do_draw) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_menu_set(C, NULL);
}
}
@@ -360,15 +370,6 @@ static void wm_method_draw_damage(bContext *C, wmWindow *win)
/* 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 void split_width(int x, int n, int *splitx, int *nx)
{
int a, newnx, waste;
@@ -405,16 +406,13 @@ static void split_width(int x, int n, int *splitx, int *nx)
}
}
-static void wm_draw_triple_free(wmWindow *win)
+static void wm_draw_triple_free(wmDrawTriple *triple)
{
- if (win->drawdata) {
- wmDrawTriple *triple = win->drawdata;
+ if (triple) {
glDeleteTextures(triple->nx * triple->ny, triple->bind);
MEM_freeN(triple);
-
- win->drawdata = NULL;
}
}
@@ -499,7 +497,7 @@ static int wm_triple_gen_textures(wmWindow *win, wmDrawTriple *triple)
return 1;
}
-static void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
+void wm_triple_draw_textures(wmWindow *win, wmDrawTriple *triple, float alpha)
{
const int winsize_x = WM_window_pixels_x(win);
const int winsize_y = WM_window_pixels_y(win);
@@ -571,7 +569,7 @@ static void wm_triple_copy_textures(wmWindow *win, wmDrawTriple *triple)
glBindTexture(triple->target, 0);
}
-static void wm_draw_region_blend(wmWindow *win, ARegion *ar)
+static void wm_draw_region_blend(wmWindow *win, ARegion *ar, wmDrawTriple *triple)
{
float fac = ED_region_blend_factor(ar);
@@ -580,7 +578,7 @@ static void wm_draw_region_blend(wmWindow *win, ARegion *ar)
wmSubWindowScissorSet(win, win->screen->mainwin, &ar->winrct, true);
glEnable(GL_BLEND);
- wm_triple_draw_textures(win, win->drawdata, 1.0f - fac);
+ wm_triple_draw_textures(win, triple, 1.0f - fac);
glDisable(GL_BLEND);
}
}
@@ -589,29 +587,46 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
{
wmWindowManager *wm = CTX_wm_manager(C);
wmDrawTriple *triple;
+ wmDrawData *dd, *dd_next, *drawdata = win->drawdata.first;
bScreen *screen = win->screen;
ScrArea *sa;
ARegion *ar;
- int copytex = 0;
+ int copytex = false;
- if (win->drawdata) {
+ if (drawdata && drawdata->triple) {
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, 1.0f);
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
}
else {
- win->drawdata = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
+ /* we run it when we start OR when we turn stereo on */
+ if (drawdata == NULL) {
+ drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData");
+ BLI_addhead(&win->drawdata, drawdata);
+ }
+
+ drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
- if (!wm_triple_gen_textures(win, win->drawdata)) {
+ if (!wm_triple_gen_textures(win, drawdata->triple)) {
wm_draw_triple_fail(C, win);
return;
}
}
- triple = win->drawdata;
+ /* it means stereo was just turned off */
+ /* note: we are removing all drawdatas that are not the first */
+ for (dd = drawdata->next; dd; dd = dd_next) {
+ dd_next = dd->next;
+
+ BLI_remlink(&win->drawdata, dd);
+ wm_draw_triple_free(dd->triple);
+ MEM_freeN(dd);
+ }
+
+ triple = drawdata->triple;
/* draw marked area regions */
for (sa = screen->areabase.first; sa; sa = sa->next) {
@@ -619,16 +634,17 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid && ar->do_draw) {
-
- if (ar->overlap == 0) {
+
+ if (ar->overlap == false) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_region_set(C, NULL);
- copytex = 1;
+ copytex = true;
}
}
}
-
+
wm_area_mark_invalid_backbuf(sa);
CTX_wm_area_set(C, NULL);
}
@@ -662,14 +678,15 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* draw overlapping area regions (always like popups) */
for (sa = screen->areabase.first; sa; sa = sa->next) {
CTX_wm_area_set(C, sa);
-
+
for (ar = sa->regionbase.first; ar; ar = ar->next) {
if (ar->swinid && ar->overlap) {
CTX_wm_region_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_region_set(C, NULL);
-
- wm_draw_region_blend(win, ar);
+
+ wm_draw_region_blend(win, ar, triple);
}
}
@@ -678,12 +695,14 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* after area regions so we can do area 'overlay' drawing */
ED_screen_draw(win);
+ win->screen->do_draw = false;
/* draw floating regions (menus) */
for (ar = screen->regionbase.first; ar; ar = ar->next) {
if (ar->swinid) {
CTX_wm_menu_set(C, ar);
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
CTX_wm_menu_set(C, NULL);
}
}
@@ -691,13 +710,188 @@ static void wm_method_draw_triple(bContext *C, wmWindow *win)
/* always draw, not only when screen tagged */
if (win->gesture.first)
wm_gesture_draw(win);
-
+
/* needs pixel coords in screen */
if (wm->drags.first) {
wm_drags_draw(C, win, NULL);
}
}
+static void wm_method_draw_triple_multiview(bContext *C, wmWindow *win, StereoViews sview)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmDrawData *drawdata;
+ wmDrawTriple *triple_data, *triple_all;
+ bScreen *screen = win->screen;
+ ScrArea *sa;
+ ARegion *ar;
+ int copytex = false;
+ int id;
+
+ /* we store the triple_data in sequence to triple_all */
+ for (id = 0; id < 2; id++) {
+ drawdata = BLI_findlink(&win->drawdata, (sview * 2) + id);
+
+ if (drawdata && drawdata->triple) {
+ if (id == 0) {
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ wmSubWindowSet(win, screen->mainwin);
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+ }
+ }
+ else {
+ /* we run it when we start OR when we turn stereo on */
+ if (drawdata == NULL) {
+ drawdata = MEM_callocN(sizeof(wmDrawData), "wmDrawData");
+ BLI_addtail(&win->drawdata, drawdata);
+ }
+
+ drawdata->triple = MEM_callocN(sizeof(wmDrawTriple), "wmDrawTriple");
+
+ if (!wm_triple_gen_textures(win, drawdata->triple)) {
+ wm_draw_triple_fail(C, win);
+ return;
+ }
+ }
+ }
+
+ triple_data = ((wmDrawData *) BLI_findlink(&win->drawdata, sview * 2))->triple;
+ triple_all = ((wmDrawData *) BLI_findlink(&win->drawdata, (sview * 2) + 1))->triple;
+
+ /* draw marked area regions */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ CTX_wm_area_set(C, sa);
+
+ switch (sa->spacetype) {
+ case SPACE_IMAGE:
+ {
+ SpaceImage *sima = sa->spacedata.first;
+ sima->iuser.multiview_eye = sview;
+ break;
+ }
+ case SPACE_VIEW3D:
+ {
+ View3D *v3d = sa->spacedata.first;
+ BGpic *bgpic = v3d->bgpicbase.first;
+ v3d->multiview_eye = sview;
+ if (bgpic) bgpic->iuser.multiview_eye = sview;
+ break;
+ }
+ case SPACE_NODE:
+ {
+ SpaceNode *snode = sa->spacedata.first;
+ if ((snode->flag & SNODE_BACKDRAW) && ED_node_is_compositor(snode)) {
+ Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
+ ima->eye = sview;
+ }
+ break;
+ }
+ case SPACE_SEQ:
+ {
+ SpaceSeq *sseq = sa->spacedata.first;
+ sseq->multiview_eye = sview;
+ break;
+ }
+ }
+
+ /* draw marked area regions */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid && ar->do_draw) {
+
+ if (ar->overlap == false) {
+ CTX_wm_region_set(C, ar);
+ ED_region_do_draw(C, ar);
+
+ if (sview == STEREO_RIGHT_ID)
+ ar->do_draw = false;
+
+ CTX_wm_region_set(C, NULL);
+ copytex = true;
+ }
+ }
+ }
+
+ wm_area_mark_invalid_backbuf(sa);
+ CTX_wm_area_set(C, NULL);
+ }
+
+ if (copytex) {
+ wmSubWindowSet(win, screen->mainwin);
+
+ wm_triple_copy_textures(win, triple_data);
+ }
+
+ if (wm->paintcursors.first) {
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid && ar->swinid == screen->subwinactive) {
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ /* make region ready for draw, scissor, pixelspace */
+ ED_region_set(C, ar);
+ wm_paintcursor_draw(C, ar);
+
+ CTX_wm_region_set(C, NULL);
+ CTX_wm_area_set(C, NULL);
+ }
+ }
+ }
+
+ wmSubWindowSet(win, screen->mainwin);
+ }
+
+ /* draw overlapping area regions (always like popups) */
+ for (sa = screen->areabase.first; sa; sa = sa->next) {
+ CTX_wm_area_set(C, sa);
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid && ar->overlap) {
+ CTX_wm_region_set(C, ar);
+ ED_region_do_draw(C, ar);
+ if (sview == STEREO_RIGHT_ID)
+ ar->do_draw = false;
+ CTX_wm_region_set(C, NULL);
+
+ wm_draw_region_blend(win, ar, triple_data);
+ }
+ }
+
+ CTX_wm_area_set(C, NULL);
+ }
+
+ /* after area regions so we can do area 'overlay' drawing */
+ ED_screen_draw(win);
+ if (sview == STEREO_RIGHT_ID)
+ win->screen->do_draw = false;
+
+ /* draw floating regions (menus) */
+ for (ar = screen->regionbase.first; ar; ar = ar->next) {
+ if (ar->swinid) {
+ CTX_wm_menu_set(C, ar);
+ ED_region_do_draw(C, ar);
+ if (sview == STEREO_RIGHT_ID)
+ ar->do_draw = false;
+ CTX_wm_menu_set(C, NULL);
+ }
+ }
+
+ /* always draw, not only when screen tagged */
+ if (win->gesture.first)
+ wm_gesture_draw(win);
+
+ /* needs pixel coords in screen */
+ if (wm->drags.first) {
+ wm_drags_draw(C, win, NULL);
+ }
+
+ /* copy the ui + overlays */
+ wmSubWindowSet(win, screen->mainwin);
+ wm_triple_copy_textures(win, triple_all);
+}
/****************** main update call **********************/
@@ -848,8 +1042,16 @@ void wm_draw_update(bContext *C)
wm_method_draw_overlap_all(C, win, 0);
else if (drawmethod == USER_DRAW_OVERLAP_FLIP)
wm_method_draw_overlap_all(C, win, 1);
- else // if (drawmethod == USER_DRAW_TRIPLE)
- wm_method_draw_triple(C, win);
+ else { /* USER_DRAW_TRIPLE */
+ if ((WM_stereo3d_enabled(win, false)) == false) {
+ wm_method_draw_triple(C, win);
+ }
+ else {
+ wm_method_draw_triple_multiview(C, win, STEREO_LEFT_ID);
+ wm_method_draw_triple_multiview(C, win, STEREO_RIGHT_ID);
+ wm_method_draw_stereo3d(C, win);
+ }
+ }
win->screen->do_draw_gesture = false;
win->screen->do_draw_paintcursor = false;
@@ -862,15 +1064,23 @@ void wm_draw_update(bContext *C)
}
}
+void wm_draw_data_free(wmWindow *win)
+{
+ wmDrawData *dd;
+
+ for (dd = win->drawdata.first; dd; dd = dd->next) {
+ wm_draw_triple_free(dd->triple);
+ }
+ BLI_freelistN(&win->drawdata);
+}
+
void wm_draw_window_clear(wmWindow *win)
{
bScreen *screen = win->screen;
ScrArea *sa;
ARegion *ar;
- int drawmethod = wm_automatic_draw_method(win);
- if (drawmethod == USER_DRAW_TRIPLE)
- wm_draw_triple_free(win);
+ wm_draw_data_free(win);
/* clear screen swap flags */
if (screen) {
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 3fd1fe427c9..f3e9c416e7b 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -846,11 +846,11 @@ static ImBuf *blend_file_thumb(Scene *scene, bScreen *screen, int **thumb_pt)
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(scene, scene->camera,
BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, err_out);
+ IB_rect, OB_SOLID, false, false, false, R_ALPHAPREMUL, NULL, err_out);
}
else {
ibuf = ED_view3d_draw_offscreen_imbuf(scene, v3d, ar, BLEN_THUMB_SIZE * 2, BLEN_THUMB_SIZE * 2,
- IB_rect, false, R_ALPHAPREMUL, err_out);
+ IB_rect, false, R_ALPHAPREMUL, NULL, err_out);
}
if (ibuf) {
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index c2cd96165f3..499adf5704d 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -1268,6 +1268,13 @@ void WM_operator_properties_filesel(wmOperatorType *ot, int filter, short type,
if (flag & WM_FILESEL_RELPATH)
RNA_def_boolean(ot->srna, "relative_path", true, "Relative Path", "Select the file relative to the blend file");
+ if ((filter & FILE_TYPE_IMAGE) || (filter & FILE_TYPE_MOVIE)) {
+ prop = RNA_def_boolean(ot->srna, "show_multiview", 0, "Enable Multi-View", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_multiview", 0, "Use Multi-View", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
prop = RNA_def_enum(ot->srna, "display_type", file_display_items, display, "Display Type", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
@@ -4592,8 +4599,10 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
for (a = 0; a < iter; a++) {
if (type == 0) {
- if (ar)
+ if (ar) {
ED_region_do_draw(C, ar);
+ ar->do_draw = false;
+ }
}
else if (type == 1) {
wmWindow *win = CTX_wm_window(C);
@@ -4621,6 +4630,7 @@ static int redraw_timer_exec(bContext *C, wmOperator *op)
if (ar_iter->swinid) {
CTX_wm_region_set(C, ar_iter);
ED_region_do_draw(C, ar_iter);
+ ar->do_draw = false;
}
}
}
@@ -4832,6 +4842,36 @@ static void operatortype_ghash_free_cb(wmOperatorType *ot)
}
/* ******************************************************* */
+/* toggle 3D for current window, turning it fullscreen if needed */
+static void WM_OT_stereo3d_set(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ ot->name = "Set Stereo 3D";
+ ot->idname = "WM_OT_set_stereo_3d";
+ ot->description = "Toggle 3D stereo support for current window (or change the display mode)";
+
+ ot->exec = wm_stereo3d_set_exec;
+ ot->invoke = wm_stereo3d_set_invoke;
+ ot->poll = WM_operator_winactive;
+ ot->ui = wm_stereo3d_set_draw;
+ ot->cancel = wm_stereo3d_set_cancel;
+
+ prop = RNA_def_enum(ot->srna, "display_mode", stereo3d_display_items, S3D_DISPLAY_ANAGLYPH, "Display Mode", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna, "anaglyph_type", stereo3d_anaglyph_type_items, S3D_ANAGLYPH_REDCYAN, "Anaglyph Type", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_enum(ot->srna, "interlace_type", stereo3d_interlace_type_items, S3D_INTERLACE_ROW, "Interlace Type", "");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_interlace_swap", false, "Swap Left/Right",
+ "Swap left and right stereo channels");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "use_sidebyside_crosseyed", false, "Cross-Eyed",
+ "Right eye should see left image and vice-versa");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/* ******************************************************* */
/* called on initialize WM_exit() */
void wm_operatortype_free(void)
{
@@ -4873,6 +4913,7 @@ void wm_operatortype_init(void)
WM_operatortype_append(WM_OT_call_menu);
WM_operatortype_append(WM_OT_call_menu_pie);
WM_operatortype_append(WM_OT_radial_control);
+ WM_operatortype_append(WM_OT_stereo3d_set);
#if defined(WIN32)
WM_operatortype_append(WM_OT_console_toggle);
#endif
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
new file mode 100644
index 00000000000..5d7b11272c6
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -0,0 +1,534 @@
+/*
+ * ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2015 by Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/windowmanager/intern/wm_stereo.c
+ * \ingroup wm
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "DNA_listBase.h"
+
+#include "RNA_access.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_utildefines.h"
+
+#include "BIF_gl.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_report.h"
+
+#include "GHOST_C-api.h"
+
+#include "ED_screen.h"
+
+#include "GPU_glew.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm.h"
+#include "wm_draw.h" /* wmDrawTriple */
+#include "wm_window.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+static void wm_method_draw_stereo3d_pageflip(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ int view;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+
+ if (view == STEREO_LEFT_ID)
+ glDrawBuffer(GL_BACK_LEFT);
+ else //STEREO_RIGHT_ID
+ glDrawBuffer(GL_BACK_RIGHT);
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+ }
+}
+
+static GLuint left_interlace_mask[32];
+static GLuint right_interlace_mask[32];
+static enum eStereo3dInterlaceType interlace_prev_type = -1;
+static char interlace_prev_swap = -1;
+
+static void wm_interlace_masks_create(wmWindow *win)
+{
+ GLuint pattern;
+ char i;
+ bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0;
+ enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type;
+
+ if (interlace_prev_type == interlace_type && interlace_prev_swap == swap)
+ return;
+
+ switch (interlace_type) {
+ case S3D_INTERLACE_ROW:
+ pattern = 0x00000000;
+ pattern = swap ? ~pattern : pattern;
+ for (i = 0; i < 32; i += 2) {
+ left_interlace_mask[i] = pattern;
+ right_interlace_mask[i] = ~pattern;
+ }
+ for (i = 1; i < 32; i += 2) {
+ left_interlace_mask[i] = ~pattern;
+ right_interlace_mask[i] = pattern;
+ }
+ break;
+ case S3D_INTERLACE_COLUMN:
+ pattern = 0x55555555;
+ pattern = swap ? ~pattern : pattern;
+ for (i = 0; i < 32; i++) {
+ left_interlace_mask[i] = pattern;
+ right_interlace_mask[i] = ~pattern;
+ }
+ break;
+ case S3D_INTERLACE_CHECKERBOARD:
+ default:
+ pattern = 0x55555555;
+ pattern = swap ? ~pattern : pattern;
+ for (i = 0; i < 32; i += 2) {
+ left_interlace_mask[i] = pattern;
+ right_interlace_mask[i] = ~pattern;
+ }
+ for (i = 1; i < 32; i += 2) {
+ left_interlace_mask[i] = ~pattern;
+ right_interlace_mask[i] = pattern;
+ }
+ break;
+ }
+ interlace_prev_type = interlace_type;
+ interlace_prev_swap = swap;
+}
+
+static void wm_method_draw_stereo3d_interlace(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ int view;
+
+ wm_interlace_masks_create(win);
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+
+ glEnable(GL_POLYGON_STIPPLE);
+ glPolygonStipple(view ? (GLubyte *) right_interlace_mask : (GLubyte *) left_interlace_mask);
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+ glDisable(GL_POLYGON_STIPPLE);
+ }
+}
+
+static void wm_method_draw_stereo3d_anaglyph(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ int view, bit;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+
+ bit = view + 1;
+ switch (win->stereo3d_format->anaglyph_type) {
+ case S3D_ANAGLYPH_REDCYAN:
+ glColorMask((1&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ GL_FALSE);
+ break;
+ case S3D_ANAGLYPH_GREENMAGENTA:
+ glColorMask((2&bit) ? GL_TRUE : GL_FALSE,
+ (1&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ GL_FALSE);
+ break;
+ case S3D_ANAGLYPH_YELLOWBLUE:
+ glColorMask((1&bit) ? GL_TRUE : GL_FALSE,
+ (1&bit) ? GL_TRUE : GL_FALSE,
+ (2&bit) ? GL_TRUE : GL_FALSE,
+ GL_FALSE);
+ break;
+ }
+
+ wm_triple_draw_textures(win, drawdata->triple, 1.0f);
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+static void wm_method_draw_stereo3d_sidebyside(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ wmDrawTriple *triple;
+ float halfx, halfy, ratiox, ratioy;
+ int x, y, offx, offy;
+ float alpha = 1.0f;
+ int view;
+ int soffx;
+ bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+ triple = drawdata->triple;
+
+ soffx = WM_window_pixels_x(win) * 0.5f;
+ if (view == STEREO_LEFT_ID) {
+ if (!cross_eyed)
+ soffx = 0;
+ }
+ else { //RIGHT_LEFT_ID
+ if (cross_eyed)
+ soffx = 0;
+ }
+
+ 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++) {
+ const int sizex = triple->x[x];
+ const int sizey = triple->y[y];
+
+ /* wmOrtho for the screen has this same offset */
+ ratiox = sizex;
+ ratioy = sizey;
+ halfx = GLA_PIXEL_OFS;
+ halfy = GLA_PIXEL_OFS;
+
+ /* 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]);
+
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glBegin(GL_QUADS);
+ glTexCoord2f(halfx, halfy);
+ glVertex2f(soffx + (offx * 0.5f), offy);
+
+ glTexCoord2f(ratiox + halfx, halfy);
+ glVertex2f(soffx + ((offx + sizex) * 0.5f), offy);
+
+ glTexCoord2f(ratiox + halfx, ratioy + halfy);
+ glVertex2f(soffx + ((offx + sizex) * 0.5f), offy + sizey);
+
+ glTexCoord2f(halfx, ratioy + halfy);
+ glVertex2f(soffx + (offx * 0.5f), offy + sizey);
+ glEnd();
+ }
+ }
+
+ glBindTexture(triple->target, 0);
+ glDisable(triple->target);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+static void wm_method_draw_stereo3d_topbottom(wmWindow *win)
+{
+ wmDrawData *drawdata;
+ wmDrawTriple *triple;
+ float halfx, halfy, ratiox, ratioy;
+ int x, y, offx, offy;
+ float alpha = 1.0f;
+ int view;
+ int soffy;
+
+ for (view = 0; view < 2; view ++) {
+ drawdata = BLI_findlink(&win->drawdata, (view * 2) + 1);
+ triple = drawdata->triple;
+
+ if (view == STEREO_LEFT_ID) {
+ soffy = WM_window_pixels_y(win) * 0.5f;
+ }
+ else { /* STEREO_RIGHT_ID */
+ soffy = 0;
+ }
+
+ 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++) {
+ const int sizex = triple->x[x];
+ const int sizey = triple->y[y];
+
+ /* wmOrtho for the screen has this same offset */
+ ratiox = sizex;
+ ratioy = sizey;
+ halfx = GLA_PIXEL_OFS;
+ halfy = GLA_PIXEL_OFS;
+
+ /* 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]);
+
+ glColor4f(1.0f, 1.0f, 1.0f, alpha);
+ glBegin(GL_QUADS);
+ glTexCoord2f(halfx, halfy);
+ glVertex2f(offx, soffy + (offy * 0.5f));
+
+ glTexCoord2f(ratiox + halfx, halfy);
+ glVertex2f(offx + sizex, soffy + (offy * 0.5f));
+
+ glTexCoord2f(ratiox + halfx, ratioy + halfy);
+ glVertex2f(offx + sizex, soffy + ((offy + sizey) * 0.5f));
+
+ glTexCoord2f(halfx, ratioy + halfy);
+ glVertex2f(offx, soffy + ((offy + sizey) * 0.5f));
+ glEnd();
+ }
+ }
+
+ glBindTexture(triple->target, 0);
+ glDisable(triple->target);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+}
+
+void wm_method_draw_stereo3d(const bContext *UNUSED(C), wmWindow *win)
+{
+ switch (win->stereo3d_format->display_mode) {
+ case S3D_DISPLAY_ANAGLYPH:
+ wm_method_draw_stereo3d_anaglyph(win);
+ break;
+ case S3D_DISPLAY_INTERLACE:
+ wm_method_draw_stereo3d_interlace(win);
+ break;
+ case S3D_DISPLAY_PAGEFLIP:
+ wm_method_draw_stereo3d_pageflip(win);
+ break;
+ case S3D_DISPLAY_SIDEBYSIDE:
+ wm_method_draw_stereo3d_sidebyside(win);
+ break;
+ case S3D_DISPLAY_TOPBOTTOM:
+ wm_method_draw_stereo3d_topbottom(win);
+ break;
+ default:
+ break;
+ }
+}
+
+static bool wm_stereo3d_is_fullscreen_required(eStereoDisplayMode stereo_display)
+{
+ return ELEM(stereo_display,
+ S3D_DISPLAY_SIDEBYSIDE,
+ S3D_DISPLAY_TOPBOTTOM,
+ S3D_DISPLAY_PAGEFLIP);
+}
+
+bool WM_stereo3d_enabled(wmWindow *win, bool skip_stereo3d_check)
+{
+ bScreen *screen = win->screen;
+
+ if ((skip_stereo3d_check == false) && (ED_screen_stereo3d_required(screen) == false))
+ return false;
+
+ if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode))
+ return WM_window_is_fullscreen(win);
+
+ return true;
+}
+
+/************************** Stereo 3D operator **********************************/
+typedef struct Stereo3dData {
+ Stereo3dFormat stereo3d_format;
+} Stereo3dData;
+
+static bool wm_stereo3d_set_properties(bContext *C, wmOperator *op)
+{
+ wmWindow *win = CTX_wm_window(C);
+ Stereo3dFormat *s3d = win->stereo3d_format;
+ PropertyRNA *prop;
+ bool is_set = false;
+
+ prop = RNA_struct_find_property(op->ptr, "display_mode");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ s3d->display_mode = RNA_property_enum_get(op->ptr, prop);
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "anaglyph_type");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ s3d->anaglyph_type = RNA_property_enum_get(op->ptr, prop);
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "interlace_type");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ s3d->interlace_type = RNA_property_enum_get(op->ptr, prop);
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_interlace_swap");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop))
+ s3d->flag |= S3D_INTERLACE_SWAP;
+ else
+ s3d->flag &= ~S3D_INTERLACE_SWAP;
+ is_set = true;
+ }
+
+ prop = RNA_struct_find_property(op->ptr, "use_sidebyside_crosseyed");
+ if (RNA_property_is_set(op->ptr, prop)) {
+ if (RNA_property_boolean_get(op->ptr, prop))
+ s3d->flag |= S3D_SIDEBYSIDE_CROSSEYED;
+ else
+ s3d->flag &= ~S3D_SIDEBYSIDE_CROSSEYED;
+ is_set = true;
+ }
+
+ return is_set;
+}
+
+static void wm_stereo3d_set_init(bContext *C, wmOperator *op)
+{
+ Stereo3dData *s3dd;
+ wmWindow *win = CTX_wm_window(C);
+
+ op->customdata = s3dd = MEM_callocN(sizeof(Stereo3dData), __func__);
+
+ /* store the original win stereo 3d settings in case of cancel */
+ s3dd->stereo3d_format = *win->stereo3d_format;
+}
+
+int wm_stereo3d_set_exec(bContext *C, wmOperator *op)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
+ const bool is_fullscreen = WM_window_is_fullscreen(win);
+
+ if (G.background)
+ return OPERATOR_CANCELLED;
+
+ /* pagelfip requires a new window to be created with the proper OS flags */
+ if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP) {
+ if (wm_window_duplicate_exec(C, op) == OPERATOR_FINISHED) {
+ wm_window_close(C, wm, win);
+ win = wm->windows.last;
+ }
+ else {
+ BKE_reportf(op->reports, RPT_ERROR,
+ "Fail to create a window compatible with time sequential (page-flip) display method");
+ return OPERATOR_CANCELLED;
+ }
+ }
+
+ if (wm_stereo3d_is_fullscreen_required(win->stereo3d_format->display_mode)) {
+ if (!is_fullscreen) {
+ wm_window_fullscreen_toggle_exec(C, op);
+ }
+ }
+
+ if (op->customdata) {
+ MEM_freeN(op->customdata);
+ }
+
+ WM_event_add_notifier(C, NC_WINDOW, NULL);
+ return OPERATOR_FINISHED;
+}
+
+int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ wm_stereo3d_set_init(C, op);
+
+ if (wm_stereo3d_set_properties(C, op))
+ return wm_stereo3d_set_exec(C, op);
+ else
+ return WM_operator_props_dialog_popup(C, op, 250, 100);
+}
+
+void wm_stereo3d_set_draw(bContext *C, wmOperator *op)
+{
+ wmWindow *win = CTX_wm_window(C);
+ Stereo3dFormat *stereo3d_format;
+ PointerRNA stereo3d_format_ptr;
+ uiLayout *layout = op->layout;
+ uiLayout *col;
+
+ stereo3d_format = win->stereo3d_format;
+ RNA_pointer_create(NULL, &RNA_Stereo3dDisplay, stereo3d_format, &stereo3d_format_ptr);
+
+ col = uiLayoutColumn(layout, false);
+ uiItemR(col, &stereo3d_format_ptr, "display_mode", 0, NULL, ICON_NONE);
+
+ switch (stereo3d_format->display_mode) {
+ case S3D_DISPLAY_ANAGLYPH:
+ {
+ uiItemR(col, &stereo3d_format_ptr, "anaglyph_type", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_INTERLACE:
+ {
+ uiItemR(col, &stereo3d_format_ptr, "interlace_type", 0, NULL, ICON_NONE);
+ uiItemR(col, &stereo3d_format_ptr, "use_interlace_swap", 0, NULL, ICON_NONE);
+ break;
+ }
+ case S3D_DISPLAY_SIDEBYSIDE:
+ {
+ uiItemR(col, &stereo3d_format_ptr, "use_sidebyside_crosseyed", 0, NULL, ICON_NONE);
+ /* fall-through */
+ }
+ case S3D_DISPLAY_PAGEFLIP:
+ case S3D_DISPLAY_TOPBOTTOM:
+ default:
+ {
+ break;
+ }
+ }
+}
+
+void wm_stereo3d_set_cancel(bContext *C, wmOperator *op)
+{
+ Stereo3dData *s3dd = op->customdata;
+ wmWindow *win = CTX_wm_window(C);
+
+ /* roll back to the original */
+ if (win) {
+ *win->stereo3d_format = s3dd->stereo3d_format;
+ }
+
+ MEM_freeN(op->customdata);
+ op->customdata = NULL;
+}
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 1af20e6036d..4b98f8bf71d 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -206,12 +206,13 @@ void wm_window_free(bContext *C, wmWindowManager *wm, wmWindow *win)
wm_event_free_all(win);
wm_subwindows_free(win);
-
- if (win->drawdata)
- MEM_freeN(win->drawdata);
-
+
+ wm_draw_data_free(win);
+
wm_ghostwindow_destroy(win);
-
+
+ MEM_freeN(win->stereo3d_format);
+
MEM_freeN(win);
}
@@ -236,6 +237,8 @@ wmWindow *wm_window_new(bContext *C)
BLI_addtail(&wm->windows, win);
win->winid = find_free_winid(wm);
+ win->stereo3d_format = MEM_callocN(sizeof(Stereo3dFormat), "Stereo 3D Format (window)");
+
return win;
}
@@ -259,8 +262,11 @@ wmWindow *wm_window_copy(bContext *C, wmWindow *winorig)
win->screen->do_draw = true;
win->drawmethod = U.wmdrawmethod;
- win->drawdata = NULL;
-
+
+ BLI_listbase_clear(&win->drawdata);
+
+ *win->stereo3d_format = *winorig->stereo3d_format;
+
return win;
}
@@ -367,6 +373,10 @@ static void wm_window_add_ghostwindow(wmWindowManager *wm, const char *title, wm
glSettings.numOfAASamples = multisamples;
+ /* a new window is created when pageflip mode is required for a window */
+ if (win->stereo3d_format->display_mode == S3D_DISPLAY_PAGEFLIP)
+ glSettings.flags |= GHOST_glStereoVisual;
+
if (!(U.uiflag2 & USER_OPENGL_NO_WARN_SUPPORT))
glSettings.flags |= GHOST_glWarnSupport;
@@ -519,8 +529,7 @@ wmWindow *WM_window_open(bContext *C, const rcti *rect)
win->sizey = BLI_rcti_size_y(rect);
win->drawmethod = U.wmdrawmethod;
- win->drawdata = NULL;
-
+
WM_check(C);
return win;
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index de04129a0ef..bc777b74b51 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -76,6 +76,13 @@ void wm_autosave_delete(void);
void wm_autosave_read(bContext *C, struct ReportList *reports);
void wm_autosave_location(char *filepath);
+/* wm_stereo.c */
+void wm_method_draw_stereo3d(const bContext *C, wmWindow *win);
+int wm_stereo3d_set_exec(bContext *C, wmOperator *op);
+int wm_stereo3d_set_invoke(bContext *C, wmOperator *op, const wmEvent *event);
+void wm_stereo3d_set_draw(bContext *C, wmOperator *op);
+void wm_stereo3d_set_cancel(bContext *C, wmOperator *op);
+
/* init operator properties */
void wm_open_init_load_ui(wmOperator *op, bool use_prefs);
void wm_open_init_use_scripts(wmOperator *op, bool use_prefs);
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
index 3d72fe17c79..5dc52b2e4fb 100644
--- a/source/blender/windowmanager/wm_draw.h
+++ b/source/blender/windowmanager/wm_draw.h
@@ -32,6 +32,23 @@
#ifndef __WM_DRAW_H__
#define __WM_DRAW_H__
+#include "GPU_glew.h"
+
+
+#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;
+
+typedef struct wmDrawData {
+ struct wmDrawData *next, *prev;
+ wmDrawTriple *triple;
+} wmDrawData;
+
struct bContext;
struct wmWindow;
struct ARegion;
@@ -43,5 +60,9 @@ void wm_draw_region_clear (struct wmWindow *win, struct ARegion *ar);
void wm_tag_redraw_overlay (struct wmWindow *win, struct ARegion *ar);
+void wm_triple_draw_textures (struct wmWindow *win, struct wmDrawTriple *triple, float alpha);
+
+void wm_draw_data_free (struct wmWindow *win);
+
#endif /* __WM_DRAW_H__ */