diff --git a/ChangeLog b/ChangeLog index 3a8cfa3a5..c2c033e2d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2006-06-02 Matthew Allum + + * clutter/clutter-element.h: + Add missing _depth() declarations + + * clutter/clutter-main.c: + * clutter/clutter-main.h: + * clutter/clutter-private.h: + * clutter/clutter-stage.c: + * clutter/clutter-stage.h: + Rejig GL setup as for stage to support an offscreen property. + Offscreen support is however a little borked. + 2006-06-01 Matthew Allum * clutter/clutter-element.c: diff --git a/clutter/clutter-element.h b/clutter/clutter-element.h index 355e84d68..cfe712585 100644 --- a/clutter/clutter-element.h +++ b/clutter/clutter-element.h @@ -256,6 +256,14 @@ clutter_element_raise_top (ClutterElement *self); void clutter_element_lower_bottom (ClutterElement *self); +void +clutter_element_set_depth (ClutterElement *self, + gint depth); + +gint +clutter_element_get_depth (ClutterElement *self); + + G_END_DECLS #endif diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 2b792878f..78c4ceee0 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -233,6 +233,9 @@ clutter_redraw () static GTimer *timer = NULL; static guint timer_n_frames = 0; + /* FIXME: Should move all this into stage... + */ + CLUTTER_DBG("@@@ Redraw enter @@@"); clutter_threads_enter(); @@ -255,7 +258,14 @@ clutter_redraw () clutter_element_paint(CLUTTER_ELEMENT(stage)); - glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage)); + if (clutter_stage_get_xwindow (stage)) + { + glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage)); + } + else + { + glFlush(); + } if (clutter_want_fps()) { @@ -321,23 +331,27 @@ clutter_root_xwindow(void) return ClutterCntx.xwin_root; } +XVisualInfo* +clutter_xvisual(void) +{ + return ClutterCntx.xvinfo; +} + gboolean clutter_want_debug(void) { return __clutter_has_debug; } -GLXContext -clutter_gl_context(void) +void +clutter_gl_context_set_indirect (gboolean indirect) { - return ClutterCntx.gl_context; + } int clutter_init(int *argc, char ***argv) { - XVisualInfo *vinfo; - int gl_attributes[] = { GLX_RGBA, @@ -374,16 +388,14 @@ clutter_init(int *argc, char ***argv) ClutterCntx.xscreen = DefaultScreen(ClutterCntx.xdpy); ClutterCntx.xwin_root = RootWindow(ClutterCntx.xdpy, ClutterCntx.xscreen); - if ((vinfo = glXChooseVisual(ClutterCntx.xdpy, - ClutterCntx.xscreen, - gl_attributes)) == NULL) + if ((ClutterCntx.xvinfo = glXChooseVisual(ClutterCntx.xdpy, + ClutterCntx.xscreen, + gl_attributes)) == NULL) { g_warning("Unable to find suitable GL visual."); return -2; } - ClutterCntx.gl_context = glXCreateContext(ClutterCntx.xdpy, vinfo, 0, True); - ClutterCntx.font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ()); pango_ft2_font_map_set_resolution (ClutterCntx.font_map, 96.0, 96.0); diff --git a/clutter/clutter-main.h b/clutter/clutter-main.h index 1c493d358..7d5ed1e42 100644 --- a/clutter/clutter-main.h +++ b/clutter/clutter-main.h @@ -80,8 +80,8 @@ clutter_xscreen (void); Window clutter_root_xwindow (void); -GLXContext -clutter_gl_context (void); +XVisualInfo* +clutter_xvisual(void); gboolean clutter_want_debug (void); diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index 5ebea0b01..3d93e9906 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -52,8 +52,8 @@ typedef struct ClutterMainContext Window xwin_root; int xscreen; GC xgc; + XVisualInfo *xvinfo; PangoFT2FontMap *font_map; - GLXContext gl_context; GMutex *gl_lock; guint update_idle; ClutterStage *stage; diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index fd2e7b4a1..b59f10960 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -38,9 +38,13 @@ static ClutterElementClass *parent_class; struct ClutterStagePrivate { Window xwin; - gint xwin_width, xwin_height; + Pixmap xpixmap; + GLXPixmap glxpixmap; + gint xwin_width, xwin_height; /* FIXME target_width / height */ gboolean want_fullscreen; + gboolean want_offscreen; gboolean hide_cursor; + GLXContext gl_context; ClutterColor color; }; @@ -48,6 +52,7 @@ enum { PROP_0, PROP_FULLSCREEN, + PROP_OFFSCREEN, PROP_HIDE_CURSOR }; @@ -198,15 +203,17 @@ sync_gl_viewport (ClutterStage *stage) static void clutter_stage_show (ClutterElement *self) { - XMapWindow (clutter_xdisplay(), - clutter_stage_get_xwindow (CLUTTER_STAGE(self))); + if (clutter_stage_get_xwindow (CLUTTER_STAGE(self))) + XMapWindow (clutter_xdisplay(), + clutter_stage_get_xwindow (CLUTTER_STAGE(self))); } static void clutter_stage_hide (ClutterElement *self) { - XUnmapWindow (clutter_xdisplay(), - clutter_stage_get_xwindow (CLUTTER_STAGE(self))); + if (clutter_stage_get_xwindow (CLUTTER_STAGE(self))) + XUnmapWindow (clutter_xdisplay(), + clutter_stage_get_xwindow (CLUTTER_STAGE(self))); } static void @@ -218,8 +225,28 @@ clutter_stage_unrealize (ClutterElement *element) stage = CLUTTER_STAGE(element); priv = stage->priv; - XDestroyWindow (clutter_xdisplay(), priv->xwin); - priv->xwin = None; + if (priv->want_offscreen) + { + if (priv->glxpixmap) + { + glXDestroyGLXPixmap (clutter_xdisplay(), priv->glxpixmap); + priv->glxpixmap = None; + } + + if (priv->xpixmap) + { + XFreePixmap (clutter_xdisplay(), priv->xpixmap); + priv->xpixmap = None; + } + } + else + { + if (clutter_stage_get_xwindow (CLUTTER_STAGE(element))) + { + XDestroyWindow (clutter_xdisplay(), priv->xwin); + priv->xwin = None; + } + } } static void @@ -232,28 +259,63 @@ clutter_stage_realize (ClutterElement *element) priv = stage->priv; - priv->xwin = XCreateSimpleWindow(clutter_xdisplay(), - clutter_root_xwindow(), - 0, 0, - priv->xwin_width, priv->xwin_height, - 0, 0, - WhitePixel(clutter_xdisplay(), - clutter_xscreen())); + if (priv->want_offscreen) + { + priv->xpixmap = XCreatePixmap (clutter_xdisplay(), + clutter_root_xwindow(), + priv->xwin_width, priv->xwin_height, + clutter_xvisual()->depth); - XSelectInput(clutter_xdisplay(), - priv->xwin, - StructureNotifyMask - |ExposureMask - |KeyPressMask - |KeyReleaseMask - |ButtonPressMask /* FIXME: Make optional ? */ - |ButtonReleaseMask - |PropertyChangeMask); + priv->glxpixmap = glXCreateGLXPixmap(clutter_xdisplay(), + clutter_xvisual(), + priv->xpixmap); + sync_fullscreen (stage); - sync_fullscreen (stage); - sync_cursor_visible (stage); + if (priv->gl_context) + glXDestroyContext (clutter_xdisplay(), priv->gl_context); + + /* indirect */ + priv->gl_context = glXCreateContext (clutter_xdisplay(), + clutter_xvisual(), + 0, + False); + + glXMakeCurrent(clutter_xdisplay(), priv->glxpixmap, priv->gl_context); + } + else + { + priv->xwin = XCreateSimpleWindow(clutter_xdisplay(), + clutter_root_xwindow(), + 0, 0, + priv->xwin_width, priv->xwin_height, + 0, 0, + WhitePixel(clutter_xdisplay(), + clutter_xscreen())); + + XSelectInput(clutter_xdisplay(), + priv->xwin, + StructureNotifyMask + |ExposureMask + |KeyPressMask + |KeyReleaseMask + |ButtonPressMask + |ButtonReleaseMask + |PropertyChangeMask); + + sync_fullscreen (stage); + sync_cursor_visible (stage); + + if (priv->gl_context) + glXDestroyContext (clutter_xdisplay(), priv->gl_context); + + priv->gl_context = glXCreateContext (clutter_xdisplay(), + clutter_xvisual(), + 0, + True); + + glXMakeCurrent(clutter_xdisplay(), priv->xwin, priv->gl_context); + } - glXMakeCurrent(clutter_xdisplay(), priv->xwin, clutter_gl_context()); sync_gl_viewport (stage); } @@ -298,6 +360,14 @@ clutter_stage_request_coords (ClutterElement *self, priv->xwin, priv->xwin_width, priv->xwin_height); + + if (priv->xpixmap) + { + /* Need to recreate to resize */ + clutter_element_unrealize(self); + clutter_element_realize(self); + } + sync_gl_viewport (stage); } @@ -351,6 +421,14 @@ clutter_stage_set_property (GObject *object, switch (prop_id) { + case PROP_OFFSCREEN: + if (priv->want_offscreen != g_value_get_boolean (value)) + { + clutter_element_unrealize(CLUTTER_ELEMENT(stage)); + priv->want_offscreen = g_value_get_boolean (value); + clutter_element_realize(CLUTTER_ELEMENT(stage)); + } + break; case PROP_FULLSCREEN: if (priv->want_fullscreen != g_value_get_boolean (value)) { @@ -385,6 +463,9 @@ clutter_stage_get_property (GObject *object, switch (prop_id) { + case PROP_OFFSCREEN: + g_value_set_boolean (value, priv->want_offscreen); + break; case PROP_FULLSCREEN: g_value_set_boolean (value, priv->want_fullscreen); break; @@ -432,6 +513,15 @@ clutter_stage_class_init (ClutterStageClass *klass) FALSE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); + g_object_class_install_property + (gobject_class, PROP_OFFSCREEN, + g_param_spec_boolean ("offscreen", + "Offscreen", + "Make Clutter stage offscreen", + FALSE, + G_PARAM_CONSTRUCT | G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_HIDE_CURSOR, g_param_spec_boolean ("hide-cursor", @@ -573,7 +663,7 @@ clutter_stage_pick (ClutterStage *stage, gint x, gint y) { ClutterElement *found = NULL; GLuint buff[64] = {0}; - GLint hits, view[4], i; + GLint hits, view[4]; glSelectBuffer(64, buff); glGetIntegerv(GL_VIEWPORT, view); @@ -606,6 +696,8 @@ clutter_stage_pick (ClutterStage *stage, gint x, gint y) if (hits != 0) { /* + int i; + for (i=0; i