mirror of
https://github.com/brl/mutter.git
synced 2024-12-22 19:12:04 +00:00
2007-01-23 Matthew Allum <mallum@openedhand.com>
* Makefile.am: * clutter.pc.in: * clutter/Makefile.am: * clutter/clutter-backend-glx.c: * clutter/clutter-backend-glx.h: * clutter/clutter-event.c: * clutter/clutter-feature.c: * clutter/clutter-group.c: * clutter/clutter-main.c: * clutter/clutter-main.h: * clutter/clutter-private.h: * clutter/clutter-stage-glx.c: * clutter/clutter-stage-glx.h: * clutter/clutter-stage.c: * clutter/clutter-stage.h: * clutter/clutter-util.c: * clutter/clutter-util.h: * clutter/pango/pangoclutter-render.c: * configure.ac: * examples/Makefile.am: Initial work in supporting different GL backends (ie. GLX/EGL/DirectFB etc). Currently just GLX supported and now mostly self contained. * TODO: Add a note about caching glenables
This commit is contained in:
parent
685c583d51
commit
244cacd14b
28
ChangeLog
28
ChangeLog
@ -1,3 +1,31 @@
|
|||||||
|
2007-01-23 Matthew Allum <mallum@openedhand.com>
|
||||||
|
|
||||||
|
* Makefile.am:
|
||||||
|
* clutter.pc.in:
|
||||||
|
* clutter/Makefile.am:
|
||||||
|
* clutter/clutter-backend-glx.c:
|
||||||
|
* clutter/clutter-backend-glx.h:
|
||||||
|
* clutter/clutter-event.c:
|
||||||
|
* clutter/clutter-feature.c:
|
||||||
|
* clutter/clutter-group.c:
|
||||||
|
* clutter/clutter-main.c:
|
||||||
|
* clutter/clutter-main.h:
|
||||||
|
* clutter/clutter-private.h:
|
||||||
|
* clutter/clutter-stage-glx.c:
|
||||||
|
* clutter/clutter-stage-glx.h:
|
||||||
|
* clutter/clutter-stage.c:
|
||||||
|
* clutter/clutter-stage.h:
|
||||||
|
* clutter/clutter-util.c:
|
||||||
|
* clutter/clutter-util.h:
|
||||||
|
* clutter/pango/pangoclutter-render.c:
|
||||||
|
* configure.ac:
|
||||||
|
* examples/Makefile.am:
|
||||||
|
Initial work in supporting different GL backends (ie. GLX/EGL/DirectFB etc).
|
||||||
|
Currently just GLX supported and now mostly self contained.
|
||||||
|
|
||||||
|
* TODO:
|
||||||
|
Add a note about caching glenables
|
||||||
|
|
||||||
2007-01-23 Tomas Frydrych <tf@openedhand.com>
|
2007-01-23 Tomas Frydrych <tf@openedhand.com>
|
||||||
|
|
||||||
* clutter/clutter-fixed.c:
|
* clutter/clutter-fixed.c:
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
SUBDIRS=clutter doc examples
|
SUBDIRS=clutter doc examples
|
||||||
|
|
||||||
pcfiles = clutter-@CLUTTER_MAJORMINOR@.pc
|
pcfiles = clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.pc
|
||||||
|
|
||||||
%-@CLUTTER_MAJORMINOR@.pc: %.pc
|
%-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.pc: %.pc
|
||||||
cp $< $@
|
cp $< $@
|
||||||
|
|
||||||
pkgconfig_DATA = $(pcfiles)
|
pkgconfig_DATA = $(pcfiles)
|
||||||
|
2
TODO
2
TODO
@ -19,6 +19,8 @@ Optimisations
|
|||||||
- Display lists.
|
- Display lists.
|
||||||
- Custom source rather than idle handler for paints ?
|
- Custom source rather than idle handler for paints ?
|
||||||
- General oprofiling.
|
- General oprofiling.
|
||||||
|
- GL state cache - avoid so much expensive glenable/disable calling
|
||||||
|
during paint (Also GL does not check if a state is already set)
|
||||||
|
|
||||||
Other
|
Other
|
||||||
==
|
==
|
||||||
|
@ -3,9 +3,9 @@ exec_prefix=${prefix}
|
|||||||
libdir=${exec_prefix}/lib
|
libdir=${exec_prefix}/lib
|
||||||
includedir=${prefix}/include
|
includedir=${prefix}/include
|
||||||
|
|
||||||
Name: clutter-@CLUTTER_MAJORMINOR@
|
Name: clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@
|
||||||
Description: Clutter library
|
Description: Clutter library
|
||||||
Version: @VERSION@
|
Version: @VERSION@
|
||||||
Libs: -L${libdir} -lclutter-@CLUTTER_MAJORMINOR@
|
Libs: -L${libdir} -lclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@
|
||||||
Cflags: -I${includedir}/clutter-@CLUTTER_MAJORMINOR@
|
Cflags: -I${includedir}/clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@
|
||||||
Requires: pangoft2 glib-2.0 >= 2.8 gthread-2.0 gdk-pixbuf-2.0 gdk-pixbuf-xlib-2.0
|
Requires: pangoft2 glib-2.0 >= 2.8 gthread-2.0 gdk-pixbuf-2.0 gdk-pixbuf-xlib-2.0
|
||||||
|
@ -32,6 +32,10 @@ source_h = \
|
|||||||
$(srcdir)/clutter-version.h \
|
$(srcdir)/clutter-version.h \
|
||||||
$(srcdir)/clutter-main.h
|
$(srcdir)/clutter-main.h
|
||||||
|
|
||||||
|
backend_h = \
|
||||||
|
$(srcdir)/clutter-stage-glx.h \
|
||||||
|
$(srcdir)/clutter-backend-glx.h
|
||||||
|
|
||||||
clutter-marshal.h: stamp-clutter-marshal.h
|
clutter-marshal.h: stamp-clutter-marshal.h
|
||||||
@true
|
@true
|
||||||
stamp-clutter-marshal.h: clutter-marshal.list
|
stamp-clutter-marshal.h: clutter-marshal.list
|
||||||
@ -113,11 +117,18 @@ source_c = clutter-main.c \
|
|||||||
clutter-media.c \
|
clutter-media.c \
|
||||||
clutter-enum-types.c
|
clutter-enum-types.c
|
||||||
|
|
||||||
|
backend_c = \
|
||||||
|
$(srcdir)/clutter-stage-glx.c \
|
||||||
|
$(srcdir)/clutter-backend-glx.c
|
||||||
|
|
||||||
source_h_priv = clutter-debug.h clutter-private.h
|
source_h_priv = clutter-debug.h clutter-private.h
|
||||||
|
|
||||||
libclutter_@CLUTTER_MAJORMINOR@_la_SOURCES = $(MARSHALFILES) \
|
libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_SOURCES = \
|
||||||
|
$(MARSHALFILES) \
|
||||||
$(source_c) \
|
$(source_c) \
|
||||||
$(source_h) \
|
$(source_h) \
|
||||||
|
$(backend_c) \
|
||||||
|
$(backend_h) \
|
||||||
$(source_h_priv)
|
$(source_h_priv)
|
||||||
|
|
||||||
INCLUDES = \
|
INCLUDES = \
|
||||||
@ -130,17 +141,23 @@ INCLUDES = \
|
|||||||
-DG_LOG_DOMAIN=\"Clutter\" \
|
-DG_LOG_DOMAIN=\"Clutter\" \
|
||||||
$(GCC_FLAGS) \
|
$(GCC_FLAGS) \
|
||||||
$(CLUTTER_CFLAGS) \
|
$(CLUTTER_CFLAGS) \
|
||||||
$(CLUTTER_DEBUG_CFLAGS)
|
$(CLUTTER_DEBUG_CFLAGS) \
|
||||||
|
-DCLUTTER_BACKEND_GLX
|
||||||
|
|
||||||
lib_LTLIBRARIES = libclutter-@CLUTTER_MAJORMINOR@.la
|
lib_LTLIBRARIES = libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
||||||
|
|
||||||
libclutter_@CLUTTER_MAJORMINOR@_la_LIBADD = \
|
libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_LIBADD = \
|
||||||
@CLUTTER_LIBS@ $(top_builddir)/clutter/pango/libpangoclutter.la
|
@CLUTTER_LIBS@ $(top_builddir)/clutter/pango/libpangoclutter.la
|
||||||
libclutter_@CLUTTER_MAJORMINOR@_la_LDFLAGS = @CLUTTER_LT_LDFLAGS@
|
|
||||||
libclutter_@CLUTTER_MAJORMINOR@_la_DEPENDENCIES = \
|
libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_LDFLAGS = \
|
||||||
|
@CLUTTER_LT_LDFLAGS@
|
||||||
|
|
||||||
|
libclutter_@CLUTTER_FLAVOUR@_@CLUTTER_MAJORMINOR@_la_DEPENDENCIES = \
|
||||||
$(top_builddir)/clutter/pango/libpangoclutter.la
|
$(top_builddir)/clutter/pango/libpangoclutter.la
|
||||||
|
|
||||||
clutterheadersdir = $(includedir)/clutter-@CLUTTER_MAJORMINOR@/clutter
|
clutterheadersdir = \
|
||||||
|
$(includedir)/clutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@/clutter
|
||||||
|
|
||||||
clutterheaders_HEADERS = $(source_h) \
|
clutterheaders_HEADERS = $(source_h) \
|
||||||
clutter-marshal.h \
|
clutter-marshal.h \
|
||||||
clutter-enum-types.h \
|
clutter-enum-types.h \
|
||||||
|
173
clutter/clutter-backend-glx.c
Normal file
173
clutter/clutter-backend-glx.c
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
#include "clutter-main.h"
|
||||||
|
|
||||||
|
static Display *_xdpy = NULL;
|
||||||
|
static Window _xwin_root;
|
||||||
|
static int _xscreen;
|
||||||
|
|
||||||
|
static gchar *clutter_display_name = NULL;
|
||||||
|
static int clutter_screen = 0;
|
||||||
|
|
||||||
|
static int TrappedErrorCode = 0;
|
||||||
|
static int (*old_error_handler) (Display *, XErrorEvent *);
|
||||||
|
|
||||||
|
static int
|
||||||
|
error_handler(Display *xdpy,
|
||||||
|
XErrorEvent *error)
|
||||||
|
{
|
||||||
|
TrappedErrorCode = error->error_code;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_util_trap_x_errors:
|
||||||
|
*
|
||||||
|
* Trap X errors so they don't cause an abort.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_glx_trap_x_errors(void)
|
||||||
|
{
|
||||||
|
TrappedErrorCode = 0;
|
||||||
|
old_error_handler = XSetErrorHandler(error_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_util_untrap_x_errors:
|
||||||
|
*
|
||||||
|
* Stop trapping X errors.
|
||||||
|
*
|
||||||
|
* Return value: 0 if there was no error, or the last X error that occurred.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clutter_glx_untrap_x_errors(void)
|
||||||
|
{
|
||||||
|
XSetErrorHandler(old_error_handler);
|
||||||
|
return TrappedErrorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_glx_display:
|
||||||
|
*
|
||||||
|
* Retrieves the X display that Clutter is using
|
||||||
|
*
|
||||||
|
* Return value: A pointer to an X Display structure.
|
||||||
|
*/
|
||||||
|
Display*
|
||||||
|
clutter_glx_display (void)
|
||||||
|
{
|
||||||
|
return _xdpy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_glx_screen:
|
||||||
|
*
|
||||||
|
* Retrieves the X screen that Clutter is using.
|
||||||
|
*
|
||||||
|
* Return value: the X screen ID
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
clutter_glx_screen (void)
|
||||||
|
{
|
||||||
|
return _xscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_glx_root_window:
|
||||||
|
*
|
||||||
|
* FIXME
|
||||||
|
*
|
||||||
|
* Return value: FIXME
|
||||||
|
*/
|
||||||
|
Window
|
||||||
|
clutter_glx_root_window (void)
|
||||||
|
{
|
||||||
|
return _xwin_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GOptionEntry clutter_glx_args[] = {
|
||||||
|
{ "display", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &clutter_display_name,
|
||||||
|
"X display to use", "DISPLAY" },
|
||||||
|
{ "screen", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT, &clutter_screen,
|
||||||
|
"X screen to use", "SCREEN" },
|
||||||
|
{ NULL, }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
pre_parse_hook (GOptionContext *context,
|
||||||
|
GOptionGroup *group,
|
||||||
|
gpointer data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
const char *env_string;
|
||||||
|
|
||||||
|
env_string = g_getenv ("DISPLAY");
|
||||||
|
if (env_string)
|
||||||
|
{
|
||||||
|
clutter_display_name = g_strdup (env_string);
|
||||||
|
env_string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
post_parse_hook (GOptionContext *context,
|
||||||
|
GOptionGroup *group,
|
||||||
|
gpointer data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
_xdpy = XOpenDisplay (clutter_display_name);
|
||||||
|
|
||||||
|
if (_xdpy)
|
||||||
|
{
|
||||||
|
if (clutter_screen == 0)
|
||||||
|
_xscreen = DefaultScreen (_xdpy);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Screen *xscreen;
|
||||||
|
|
||||||
|
xscreen = ScreenOfDisplay (_xdpy, clutter_screen);
|
||||||
|
_xscreen = XScreenNumberOfScreen (xscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
_xwin_root = RootWindow (_xdpy, _xscreen);
|
||||||
|
|
||||||
|
/* we don't need it anymore */
|
||||||
|
g_free (clutter_display_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_set_error (error,
|
||||||
|
clutter_init_error_quark (),
|
||||||
|
CLUTTER_INIT_ERROR_BACKEND,
|
||||||
|
"Unable to connect to X Server DISPLAY.");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_backend_init (GOptionContext *context)
|
||||||
|
{
|
||||||
|
GOptionGroup *group;
|
||||||
|
|
||||||
|
group = g_option_group_new ("clutter-glx",
|
||||||
|
"Clutter GLX Options",
|
||||||
|
"Show Clutter GLX Options",
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_option_group_set_parse_hooks (group, pre_parse_hook, post_parse_hook);
|
||||||
|
g_option_group_add_entries (group, clutter_glx_args);
|
||||||
|
g_option_context_add_group (context, group);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
54
clutter/clutter-backend-glx.h
Normal file
54
clutter/clutter-backend-glx.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HAVE_CLUTTER_GLX_H
|
||||||
|
#define _HAVE_CLUTTER_GLX_H
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_backend_init (GOptionContext *context) G_GNUC_INTERNAL;
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_glx_trap_x_errors(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
clutter_glx_untrap_x_errors(void);
|
||||||
|
|
||||||
|
Display*
|
||||||
|
clutter_glx_display (void);
|
||||||
|
|
||||||
|
int
|
||||||
|
clutter_glx_screen (void);
|
||||||
|
|
||||||
|
Window
|
||||||
|
clutter_glx_root_window (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -29,9 +29,6 @@
|
|||||||
|
|
||||||
#include "clutter-event.h"
|
#include "clutter-event.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xatom.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_event_type:
|
* clutter_event_type:
|
||||||
* @event: a #ClutterEvent
|
* @event: a #ClutterEvent
|
||||||
|
@ -249,15 +249,15 @@ clutter_feature_init (void)
|
|||||||
__features->features_set = FALSE; /* don't rely on zero-ing */
|
__features->features_set = FALSE; /* don't rely on zero-ing */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clutter_xdisplay ())
|
if (!clutter_glx_display ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (__features->features_set)
|
if (__features->features_set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
|
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
|
||||||
glx_extensions = glXQueryExtensionsString (clutter_xdisplay (),
|
glx_extensions = glXQueryExtensionsString (clutter_glx_display (),
|
||||||
clutter_xscreen ());
|
clutter_glx_screen ());
|
||||||
|
|
||||||
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions)
|
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions)
|
||||||
|| check_gl_extension ("GL_EXT_texture_rectangle", gl_extensions))
|
|| check_gl_extension ("GL_EXT_texture_rectangle", gl_extensions))
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "clutter-group.h"
|
#include "clutter-group.h"
|
||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
#include "clutter-marshal.h"
|
#include "clutter-marshal.h"
|
||||||
#include "clutter-enum-types.h"
|
#include "clutter-enum-types.h"
|
||||||
|
|
||||||
|
@ -43,12 +43,16 @@
|
|||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-debug.h"
|
#include "clutter-debug.h"
|
||||||
|
|
||||||
|
#ifdef CLUTTER_BACKEND_GLX
|
||||||
|
#include <clutter/clutter-backend-glx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static ClutterMainContext *ClutterCntx = NULL;
|
||||||
|
|
||||||
static gboolean clutter_is_initialized = FALSE;
|
static gboolean clutter_is_initialized = FALSE;
|
||||||
static gboolean clutter_show_fps = FALSE;
|
static gboolean clutter_show_fps = FALSE;
|
||||||
static gboolean clutter_fatal_warnings = FALSE;
|
static gboolean clutter_fatal_warnings = FALSE;
|
||||||
static gchar *clutter_display_name = NULL;
|
|
||||||
static gchar *clutter_vblank_name = NULL;
|
static gchar *clutter_vblank_name = NULL;
|
||||||
static int clutter_screen = 0;
|
|
||||||
|
|
||||||
guint clutter_debug_flags = 0; /* global clutter debug flag */
|
guint clutter_debug_flags = 0; /* global clutter debug flag */
|
||||||
|
|
||||||
@ -66,210 +70,8 @@ static const GDebugKey clutter_debug_keys[] = {
|
|||||||
};
|
};
|
||||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
GSource source;
|
|
||||||
Display *display;
|
|
||||||
GPollFD event_poll_fd;
|
|
||||||
}
|
|
||||||
ClutterXEventSource;
|
|
||||||
|
|
||||||
typedef void (*ClutterXEventFunc) (XEvent *xev, gpointer user_data);
|
gboolean
|
||||||
|
|
||||||
static ClutterMainContext *ClutterCntx = NULL;
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
x_event_prepare (GSource *source,
|
|
||||||
gint *timeout)
|
|
||||||
{
|
|
||||||
Display *display = ((ClutterXEventSource*)source)->display;
|
|
||||||
|
|
||||||
*timeout = -1;
|
|
||||||
|
|
||||||
return XPending (display);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
x_event_check (GSource *source)
|
|
||||||
{
|
|
||||||
ClutterXEventSource *display_source = (ClutterXEventSource*)source;
|
|
||||||
gboolean retval;
|
|
||||||
|
|
||||||
if (display_source->event_poll_fd.revents & G_IO_IN)
|
|
||||||
retval = XPending (display_source->display);
|
|
||||||
else
|
|
||||||
retval = FALSE;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
x_event_dispatch (GSource *source,
|
|
||||||
GSourceFunc callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
Display *display = ((ClutterXEventSource*)source)->display;
|
|
||||||
ClutterXEventFunc event_func = (ClutterXEventFunc) callback;
|
|
||||||
|
|
||||||
XEvent xev;
|
|
||||||
|
|
||||||
if (XPending (display))
|
|
||||||
{
|
|
||||||
XNextEvent (display, &xev);
|
|
||||||
|
|
||||||
if (event_func)
|
|
||||||
(*event_func) (&xev, user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const GSourceFuncs x_event_funcs = {
|
|
||||||
x_event_prepare,
|
|
||||||
x_event_check,
|
|
||||||
x_event_dispatch,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
translate_key_event (ClutterKeyEvent *event,
|
|
||||||
XEvent *xevent)
|
|
||||||
{
|
|
||||||
event->type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS
|
|
||||||
: CLUTTER_KEY_RELEASE;
|
|
||||||
event->time = xevent->xkey.time;
|
|
||||||
event->modifier_state = xevent->xkey.state; /* FIXME: handle modifiers */
|
|
||||||
event->hardware_keycode = xevent->xkey.keycode;
|
|
||||||
event->keyval = XKeycodeToKeysym(xevent->xkey.display,
|
|
||||||
xevent->xkey.keycode,
|
|
||||||
0 ); /* FIXME: index with modifiers */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
translate_button_event (ClutterButtonEvent *event,
|
|
||||||
XEvent *xevent)
|
|
||||||
{
|
|
||||||
/* FIXME: catch double click */
|
|
||||||
CLUTTER_NOTE (EVENT, " button event at %ix%i",
|
|
||||||
xevent->xbutton.x,
|
|
||||||
xevent->xbutton.y);
|
|
||||||
|
|
||||||
event->type = xevent->xany.type == ButtonPress ? CLUTTER_BUTTON_PRESS
|
|
||||||
: CLUTTER_BUTTON_RELEASE;
|
|
||||||
event->time = xevent->xbutton.time;
|
|
||||||
event->x = xevent->xbutton.x;
|
|
||||||
event->y = xevent->xbutton.y;
|
|
||||||
event->modifier_state = xevent->xbutton.state; /* includes button masks */
|
|
||||||
event->button = xevent->xbutton.button;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
translate_motion_event (ClutterMotionEvent *event,
|
|
||||||
XEvent *xevent)
|
|
||||||
{
|
|
||||||
event->type = CLUTTER_MOTION;
|
|
||||||
event->time = xevent->xbutton.time;
|
|
||||||
event->x = xevent->xmotion.x;
|
|
||||||
event->y = xevent->xmotion.y;
|
|
||||||
event->modifier_state = xevent->xmotion.state;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_dispatch_x_event (XEvent *xevent,
|
|
||||||
gpointer data)
|
|
||||||
{
|
|
||||||
ClutterMainContext *ctx = CLUTTER_CONTEXT ();
|
|
||||||
ClutterEvent event;
|
|
||||||
ClutterStage *stage = ctx->stage;
|
|
||||||
gboolean emit_input_event = FALSE;
|
|
||||||
|
|
||||||
switch (xevent->type)
|
|
||||||
{
|
|
||||||
case Expose:
|
|
||||||
{
|
|
||||||
XEvent foo_xev;
|
|
||||||
|
|
||||||
/* Cheap compress */
|
|
||||||
while (XCheckTypedWindowEvent(ctx->xdpy,
|
|
||||||
xevent->xexpose.window,
|
|
||||||
Expose,
|
|
||||||
&foo_xev));
|
|
||||||
|
|
||||||
/* FIXME: need to make stage an 'actor' so can que
|
|
||||||
* a paint direct from there rather than hack here...
|
|
||||||
*/
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KeyPress:
|
|
||||||
translate_key_event ((ClutterKeyEvent *) &event, xevent);
|
|
||||||
g_signal_emit_by_name (stage, "key-press-event", &event);
|
|
||||||
emit_input_event = TRUE;
|
|
||||||
break;
|
|
||||||
case KeyRelease:
|
|
||||||
translate_key_event ((ClutterKeyEvent *) &event, xevent);
|
|
||||||
g_signal_emit_by_name (stage, "key-release-event", &event);
|
|
||||||
emit_input_event = TRUE;
|
|
||||||
break;
|
|
||||||
case ButtonPress:
|
|
||||||
translate_button_event ((ClutterButtonEvent *) &event, xevent);
|
|
||||||
g_signal_emit_by_name (stage, "button-press-event", &event);
|
|
||||||
emit_input_event = TRUE;
|
|
||||||
break;
|
|
||||||
case ButtonRelease:
|
|
||||||
translate_button_event ((ClutterButtonEvent *) &event, xevent);
|
|
||||||
g_signal_emit_by_name (stage, "button-release-event", &event);
|
|
||||||
emit_input_event = TRUE;
|
|
||||||
break;
|
|
||||||
case MotionNotify:
|
|
||||||
translate_motion_event ((ClutterMotionEvent *) &event, xevent);
|
|
||||||
g_signal_emit_by_name (stage, "motion-event", &event);
|
|
||||||
emit_input_event = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (emit_input_event)
|
|
||||||
g_signal_emit_by_name (stage, "input-event", &event);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
events_init()
|
|
||||||
{
|
|
||||||
ClutterMainContext *clutter_context;
|
|
||||||
GMainContext *gmain_context;
|
|
||||||
int connection_number;
|
|
||||||
GSource *source;
|
|
||||||
ClutterXEventSource *display_source;
|
|
||||||
|
|
||||||
clutter_context = clutter_context_get_default ();
|
|
||||||
gmain_context = g_main_context_default ();
|
|
||||||
|
|
||||||
g_main_context_ref (gmain_context);
|
|
||||||
|
|
||||||
connection_number = ConnectionNumber (clutter_context->xdpy);
|
|
||||||
|
|
||||||
source = g_source_new ((GSourceFuncs *)&x_event_funcs,
|
|
||||||
sizeof (ClutterXEventSource));
|
|
||||||
|
|
||||||
display_source = (ClutterXEventSource *)source;
|
|
||||||
|
|
||||||
display_source->event_poll_fd.fd = connection_number;
|
|
||||||
display_source->event_poll_fd.events = G_IO_IN;
|
|
||||||
display_source->display = clutter_context->xdpy;
|
|
||||||
|
|
||||||
g_source_add_poll (source, &display_source->event_poll_fd);
|
|
||||||
g_source_set_can_recurse (source, TRUE);
|
|
||||||
|
|
||||||
g_source_set_callback (source,
|
|
||||||
(GSourceFunc) clutter_dispatch_x_event,
|
|
||||||
NULL /* no userdata */, NULL);
|
|
||||||
|
|
||||||
g_source_attach (source, gmain_context);
|
|
||||||
g_source_unref (source);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_want_fps (void)
|
clutter_want_fps (void)
|
||||||
{
|
{
|
||||||
return clutter_show_fps;
|
return clutter_show_fps;
|
||||||
@ -291,60 +93,8 @@ clutter_redraw (void)
|
|||||||
{
|
{
|
||||||
ClutterMainContext *ctx = CLUTTER_CONTEXT();
|
ClutterMainContext *ctx = CLUTTER_CONTEXT();
|
||||||
ClutterStage *stage = ctx->stage;
|
ClutterStage *stage = ctx->stage;
|
||||||
ClutterColor stage_color;
|
|
||||||
|
|
||||||
static GTimer *timer = NULL;
|
clutter_actor_paint (CLUTTER_ACTOR(stage));
|
||||||
static guint timer_n_frames = 0;
|
|
||||||
|
|
||||||
/* FIXME: Should move all this into stage...
|
|
||||||
*/
|
|
||||||
|
|
||||||
CLUTTER_NOTE (PAINT, " Redraw enter");
|
|
||||||
|
|
||||||
if (clutter_want_fps ())
|
|
||||||
{
|
|
||||||
if (!timer)
|
|
||||||
timer = g_timer_new ();
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_stage_get_color (stage, &stage_color);
|
|
||||||
|
|
||||||
glClearColor(((float) stage_color.red / 0xff * 1.0),
|
|
||||||
((float) stage_color.green / 0xff * 1.0),
|
|
||||||
((float) stage_color.blue / 0xff * 1.0),
|
|
||||||
0.0);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
|
||||||
|
|
||||||
glDisable(GL_LIGHTING);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
clutter_actor_paint (CLUTTER_ACTOR (stage));
|
|
||||||
|
|
||||||
if (clutter_stage_get_xwindow (stage))
|
|
||||||
{
|
|
||||||
clutter_feature_wait_for_vblank ();
|
|
||||||
glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glXWaitGL();
|
|
||||||
CLUTTER_GLERR();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (clutter_want_fps ())
|
|
||||||
{
|
|
||||||
timer_n_frames++;
|
|
||||||
|
|
||||||
if (g_timer_elapsed (timer, NULL) >= 1.0)
|
|
||||||
{
|
|
||||||
g_print ("*** FPS: %i ***\n", timer_n_frames);
|
|
||||||
timer_n_frames = 0;
|
|
||||||
g_timer_start (timer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (PAINT, "Redraw leave");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -444,50 +194,6 @@ clutter_threads_leave (void)
|
|||||||
g_mutex_unlock (context->gl_lock);
|
g_mutex_unlock (context->gl_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_xdisplay:
|
|
||||||
*
|
|
||||||
* Retrieves the X display that Clutter is using
|
|
||||||
*
|
|
||||||
* Return value: A pointer to an X Display structure.
|
|
||||||
*/
|
|
||||||
Display*
|
|
||||||
clutter_xdisplay (void)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
|
||||||
|
|
||||||
return context->xdpy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_xscreen:
|
|
||||||
*
|
|
||||||
* Retrieves the X screen that Clutter is using.
|
|
||||||
*
|
|
||||||
* Return value: the X screen ID
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clutter_xscreen (void)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
|
||||||
|
|
||||||
return context->xscreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_root_xwindow:
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Return value: FIXME
|
|
||||||
*/
|
|
||||||
Window
|
|
||||||
clutter_root_xwindow (void)
|
|
||||||
{
|
|
||||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
|
||||||
|
|
||||||
return context->xwin_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_want_debug:
|
* clutter_want_debug:
|
||||||
@ -572,10 +278,6 @@ clutter_arg_no_debug_cb (const char *key,
|
|||||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||||
|
|
||||||
static GOptionEntry clutter_args[] = {
|
static GOptionEntry clutter_args[] = {
|
||||||
{ "display", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_STRING, &clutter_display_name,
|
|
||||||
"X display to use", "DISPLAY" },
|
|
||||||
{ "screen", 0, G_OPTION_FLAG_IN_MAIN, G_OPTION_ARG_INT, &clutter_screen,
|
|
||||||
"X screen to use", "SCREEN" },
|
|
||||||
{ "clutter-show-fps", 0, 0, G_OPTION_ARG_NONE, &clutter_show_fps,
|
{ "clutter-show-fps", 0, 0, G_OPTION_ARG_NONE, &clutter_show_fps,
|
||||||
"Show frames per second", NULL },
|
"Show frames per second", NULL },
|
||||||
{ "clutter-vblank", 0, 0, G_OPTION_ARG_STRING, &clutter_vblank_name,
|
{ "clutter-vblank", 0, 0, G_OPTION_ARG_STRING, &clutter_vblank_name,
|
||||||
@ -606,18 +308,6 @@ pre_parse_hook (GOptionContext *context,
|
|||||||
if (clutter_is_initialized)
|
if (clutter_is_initialized)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* XXX - this shows a warning with newer releases of GLib,
|
|
||||||
* as we use GOption in order to get here, and GOption uses
|
|
||||||
* the slice allocator and other GLib stuff. so, either we
|
|
||||||
* move the thread init inside clutter_init() directly or
|
|
||||||
* we remove this call altogether, and let the applications
|
|
||||||
* deal with threading, as they are supposed to do anyway.
|
|
||||||
*/
|
|
||||||
if (!g_thread_supported ())
|
|
||||||
g_thread_init (NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
g_type_init ();
|
g_type_init ();
|
||||||
|
|
||||||
#ifdef CLUTTER_ENABLE_DEBUG
|
#ifdef CLUTTER_ENABLE_DEBUG
|
||||||
@ -643,13 +333,6 @@ pre_parse_hook (GOptionContext *context,
|
|||||||
if (env_string)
|
if (env_string)
|
||||||
clutter_show_fps = TRUE;
|
clutter_show_fps = TRUE;
|
||||||
|
|
||||||
env_string = g_getenv ("DISPLAY");
|
|
||||||
if (env_string)
|
|
||||||
{
|
|
||||||
clutter_display_name = g_strdup (env_string);
|
|
||||||
env_string = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,32 +363,6 @@ post_parse_hook (GOptionContext *context,
|
|||||||
clutter_context->main_loops = NULL;
|
clutter_context->main_loops = NULL;
|
||||||
clutter_context->main_loop_level = 0;
|
clutter_context->main_loop_level = 0;
|
||||||
|
|
||||||
/* either we got this with the DISPLAY envvar or via the
|
|
||||||
* --display command line switch; if both failed, then
|
|
||||||
* we'll fail later when we return in clutter_init()
|
|
||||||
*/
|
|
||||||
if (clutter_display_name)
|
|
||||||
clutter_context->xdpy = XOpenDisplay (clutter_display_name);
|
|
||||||
|
|
||||||
if (clutter_context->xdpy)
|
|
||||||
{
|
|
||||||
if (clutter_screen == 0)
|
|
||||||
clutter_context->xscreen = DefaultScreen (clutter_context->xdpy);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Screen *xscreen;
|
|
||||||
|
|
||||||
xscreen = ScreenOfDisplay (clutter_context->xdpy, clutter_screen);
|
|
||||||
clutter_context->xscreen = XScreenNumberOfScreen (xscreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_context->xwin_root = RootWindow (clutter_context->xdpy,
|
|
||||||
clutter_context->xscreen);
|
|
||||||
|
|
||||||
/* we don't need it anymore */
|
|
||||||
g_free (clutter_display_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
|
clutter_context->font_map = PANGO_FT2_FONT_MAP (pango_ft2_font_map_new ());
|
||||||
pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0);
|
pango_ft2_font_map_set_resolution (clutter_context->font_map, 96.0, 96.0);
|
||||||
|
|
||||||
@ -745,34 +402,6 @@ clutter_get_option_group (void)
|
|||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
clutter_parse_args (int *argc,
|
|
||||||
char ***argv)
|
|
||||||
{
|
|
||||||
GOptionContext *option_context;
|
|
||||||
GOptionGroup *clutter_group;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
if (clutter_is_initialized)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
option_context = g_option_context_new (NULL);
|
|
||||||
g_option_context_set_ignore_unknown_options (option_context, TRUE);
|
|
||||||
g_option_context_set_help_enabled (option_context, FALSE);
|
|
||||||
|
|
||||||
clutter_group = clutter_get_option_group ();
|
|
||||||
g_option_context_set_main_group (option_context, clutter_group);
|
|
||||||
if (!g_option_context_parse (option_context, argc, argv, &error))
|
|
||||||
{
|
|
||||||
g_warning ("%s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_option_context_free (option_context);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
GQuark
|
GQuark
|
||||||
clutter_init_error_quark (void)
|
clutter_init_error_quark (void)
|
||||||
{
|
{
|
||||||
@ -855,17 +484,11 @@ clutter_init_with_args (int *argc,
|
|||||||
if (!g_thread_supported ())
|
if (!g_thread_supported ())
|
||||||
g_thread_init (NULL);
|
g_thread_init (NULL);
|
||||||
|
|
||||||
if (!XInitThreads())
|
|
||||||
{
|
|
||||||
g_set_error (error, clutter_init_error_quark (),
|
|
||||||
CLUTTER_INIT_ERROR_THREADS,
|
|
||||||
"Unable to initialise the X threading");
|
|
||||||
return CLUTTER_INIT_ERROR_THREADS;
|
|
||||||
}
|
|
||||||
|
|
||||||
group = clutter_get_option_group ();
|
group = clutter_get_option_group ();
|
||||||
|
|
||||||
context = g_option_context_new (parameter_string);
|
context = g_option_context_new (parameter_string);
|
||||||
|
|
||||||
|
clutter_backend_init (context);
|
||||||
|
|
||||||
g_option_context_add_group (context, group);
|
g_option_context_add_group (context, group);
|
||||||
|
|
||||||
if (entries)
|
if (entries)
|
||||||
@ -881,15 +504,6 @@ clutter_init_with_args (int *argc,
|
|||||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||||
|
|
||||||
clutter_context = clutter_context_get_default ();
|
clutter_context = clutter_context_get_default ();
|
||||||
if (!clutter_context->xdpy)
|
|
||||||
{
|
|
||||||
g_set_error (error, clutter_init_error_quark (),
|
|
||||||
CLUTTER_INIT_ERROR_DISPLAY,
|
|
||||||
"Unable to connect to X DISPLAY. You should either "
|
|
||||||
"set the DISPLAY environment variable or use the "
|
|
||||||
"--display command line switch");
|
|
||||||
return CLUTTER_INIT_ERROR_DISPLAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
stage_error = NULL;
|
stage_error = NULL;
|
||||||
if (!clutter_stage_init (clutter_context, &stage_error))
|
if (!clutter_stage_init (clutter_context, &stage_error))
|
||||||
@ -898,18 +512,42 @@ clutter_init_with_args (int *argc,
|
|||||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At least GL 1.2 is needed for CLAMP_TO_EDGE */
|
return CLUTTER_INIT_SUCCESS;
|
||||||
if (!is_gl_version_at_least_12 ())
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_parse_args (int *argc,
|
||||||
|
char ***argv)
|
||||||
|
{
|
||||||
|
GOptionContext *option_context;
|
||||||
|
GOptionGroup *clutter_group;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
|
||||||
|
if (clutter_is_initialized)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
option_context = g_option_context_new (NULL);
|
||||||
|
g_option_context_set_ignore_unknown_options (option_context, TRUE);
|
||||||
|
g_option_context_set_help_enabled (option_context, FALSE);
|
||||||
|
|
||||||
|
/* Initiate any command line options from the backend */
|
||||||
|
clutter_backend_init (option_context);
|
||||||
|
|
||||||
|
clutter_group = clutter_get_option_group ();
|
||||||
|
|
||||||
|
g_option_context_set_main_group (option_context, clutter_group);
|
||||||
|
|
||||||
|
if (!g_option_context_parse (option_context, argc, argv, &error))
|
||||||
{
|
{
|
||||||
g_set_error (error, clutter_init_error_quark (),
|
g_warning ("%s", error->message);
|
||||||
CLUTTER_INIT_ERROR_OPENGL,
|
g_error_free (error);
|
||||||
"Clutter needs at least version 1.2 of OpenGL");
|
ret = FALSE;
|
||||||
return CLUTTER_INIT_ERROR_OPENGL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
events_init ();
|
g_option_context_free (option_context);
|
||||||
|
|
||||||
return CLUTTER_INIT_SUCCESS;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -937,20 +575,10 @@ clutter_init (int *argc,
|
|||||||
if (!g_thread_supported ())
|
if (!g_thread_supported ())
|
||||||
g_thread_init (NULL);
|
g_thread_init (NULL);
|
||||||
|
|
||||||
if (!XInitThreads())
|
if (clutter_parse_args (argc, argv) == FALSE)
|
||||||
return CLUTTER_INIT_ERROR_THREADS;
|
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||||
|
|
||||||
clutter_parse_args (argc, argv);
|
|
||||||
|
|
||||||
context = clutter_context_get_default ();
|
context = clutter_context_get_default ();
|
||||||
if (!context->xdpy)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to connect to X DISPLAY. You should either "
|
|
||||||
"set the DISPLAY environment variable or use the "
|
|
||||||
"--display command line switch");
|
|
||||||
|
|
||||||
return CLUTTER_INIT_ERROR_DISPLAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
stage_error = NULL;
|
stage_error = NULL;
|
||||||
if (!clutter_stage_init (context, &stage_error))
|
if (!clutter_stage_init (context, &stage_error))
|
||||||
@ -960,14 +588,15 @@ clutter_init (int *argc,
|
|||||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* FIXME: move to backend */
|
||||||
/* At least GL 1.2 is needed for CLAMP_TO_EDGE */
|
/* At least GL 1.2 is needed for CLAMP_TO_EDGE */
|
||||||
if (!is_gl_version_at_least_12 ())
|
if (!is_gl_version_at_least_12 ())
|
||||||
{
|
{
|
||||||
g_critical ("Clutter needs at least version 1.2 of OpenGL");
|
g_critical ("Clutter needs at least version 1.2 of OpenGL");
|
||||||
return CLUTTER_INIT_ERROR_OPENGL;
|
return CLUTTER_INIT_ERROR_OPENGL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
events_init ();
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,6 @@
|
|||||||
#include <clutter/clutter-actor.h>
|
#include <clutter/clutter-actor.h>
|
||||||
#include <clutter/clutter-stage.h>
|
#include <clutter/clutter-stage.h>
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
#include <GL/glx.h>
|
|
||||||
#include <GL/gl.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define CLUTTER_INIT_ERROR (clutter_init_error_quark ())
|
#define CLUTTER_INIT_ERROR (clutter_init_error_quark ())
|
||||||
@ -42,7 +37,7 @@ typedef enum {
|
|||||||
CLUTTER_INIT_SUCCESS = 1,
|
CLUTTER_INIT_SUCCESS = 1,
|
||||||
CLUTTER_INIT_ERROR_UNKOWN = 0,
|
CLUTTER_INIT_ERROR_UNKOWN = 0,
|
||||||
CLUTTER_INIT_ERROR_THREADS = -1,
|
CLUTTER_INIT_ERROR_THREADS = -1,
|
||||||
CLUTTER_INIT_ERROR_DISPLAY = -2,
|
CLUTTER_INIT_ERROR_BACKEND = -2,
|
||||||
CLUTTER_INIT_ERROR_INTERNAL = -3,
|
CLUTTER_INIT_ERROR_INTERNAL = -3,
|
||||||
CLUTTER_INIT_ERROR_OPENGL = -4
|
CLUTTER_INIT_ERROR_OPENGL = -4
|
||||||
} ClutterInitError;
|
} ClutterInitError;
|
||||||
@ -64,10 +59,8 @@ void clutter_main (void);
|
|||||||
void clutter_main_quit (void);
|
void clutter_main_quit (void);
|
||||||
gint clutter_main_level (void);
|
gint clutter_main_level (void);
|
||||||
void clutter_redraw (void);
|
void clutter_redraw (void);
|
||||||
Display * clutter_xdisplay (void);
|
|
||||||
gint clutter_xscreen (void);
|
|
||||||
Window clutter_root_xwindow (void);
|
|
||||||
gboolean clutter_want_debug (void);
|
gboolean clutter_want_debug (void);
|
||||||
|
gboolean clutter_want_fps (void);
|
||||||
void clutter_threads_enter (void);
|
void clutter_threads_enter (void);
|
||||||
void clutter_threads_leave (void);
|
void clutter_threads_leave (void);
|
||||||
|
|
||||||
|
@ -32,12 +32,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <GL/gl.h> /* Togo */
|
||||||
#include <X11/Xatom.h>
|
|
||||||
#include <X11/keysym.h>
|
|
||||||
|
|
||||||
#include <GL/glx.h>
|
|
||||||
#include <GL/gl.h>
|
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
@ -49,11 +44,6 @@ typedef struct _ClutterMainContext ClutterMainContext;
|
|||||||
|
|
||||||
struct _ClutterMainContext
|
struct _ClutterMainContext
|
||||||
{
|
{
|
||||||
Display *xdpy;
|
|
||||||
Window xwin_root;
|
|
||||||
int xscreen;
|
|
||||||
GC xgc;
|
|
||||||
|
|
||||||
PangoFT2FontMap *font_map;
|
PangoFT2FontMap *font_map;
|
||||||
|
|
||||||
GMutex *gl_lock;
|
GMutex *gl_lock;
|
||||||
|
898
clutter/clutter-stage-glx.c
Normal file
898
clutter/clutter-stage-glx.c
Normal file
@ -0,0 +1,898 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:clutter-stage
|
||||||
|
* @short_description: Top level visual element to which actors are placed.
|
||||||
|
*
|
||||||
|
* #ClutterStage is a top level 'window' on which child actors are placed
|
||||||
|
* and manipulated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "clutter-stage.h"
|
||||||
|
#include "clutter-main.h"
|
||||||
|
#include "clutter-feature.h"
|
||||||
|
#include "clutter-color.h"
|
||||||
|
#include "clutter-util.h"
|
||||||
|
#include "clutter-marshal.h"
|
||||||
|
#include "clutter-enum-types.h"
|
||||||
|
#include "clutter-private.h"
|
||||||
|
#include "clutter-debug.h"
|
||||||
|
|
||||||
|
#include "clutter-stage-glx.h"
|
||||||
|
#include "clutter-backend-glx.h"
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
||||||
|
|
||||||
|
struct _ClutterStageBackend
|
||||||
|
{
|
||||||
|
XVisualInfo *xvisinfo;
|
||||||
|
Window xwin;
|
||||||
|
Pixmap xpixmap;
|
||||||
|
gint xwin_width, xwin_height; /* FIXME target_width / height */
|
||||||
|
GLXPixmap glxpixmap;
|
||||||
|
GLXContext gl_context;
|
||||||
|
gboolean is_foreign_xwin;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GSource source;
|
||||||
|
Display *display;
|
||||||
|
GPollFD event_poll_fd;
|
||||||
|
}
|
||||||
|
ClutterXEventSource;
|
||||||
|
|
||||||
|
typedef void (*ClutterXEventFunc) (XEvent *xev, gpointer user_data);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
x_event_prepare (GSource *source,
|
||||||
|
gint *timeout)
|
||||||
|
{
|
||||||
|
Display *display = ((ClutterXEventSource*)source)->display;
|
||||||
|
|
||||||
|
*timeout = -1;
|
||||||
|
|
||||||
|
return XPending (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
x_event_check (GSource *source)
|
||||||
|
{
|
||||||
|
ClutterXEventSource *display_source = (ClutterXEventSource*)source;
|
||||||
|
gboolean retval;
|
||||||
|
|
||||||
|
if (display_source->event_poll_fd.revents & G_IO_IN)
|
||||||
|
retval = XPending (display_source->display);
|
||||||
|
else
|
||||||
|
retval = FALSE;
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
x_event_dispatch (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
Display *display = ((ClutterXEventSource*)source)->display;
|
||||||
|
ClutterXEventFunc event_func = (ClutterXEventFunc) callback;
|
||||||
|
|
||||||
|
XEvent xev;
|
||||||
|
|
||||||
|
if (XPending (display))
|
||||||
|
{
|
||||||
|
XNextEvent (display, &xev);
|
||||||
|
|
||||||
|
if (event_func)
|
||||||
|
(*event_func) (&xev, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const GSourceFuncs x_event_funcs = {
|
||||||
|
x_event_prepare,
|
||||||
|
x_event_check,
|
||||||
|
x_event_dispatch,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
translate_key_event (ClutterKeyEvent *event,
|
||||||
|
XEvent *xevent)
|
||||||
|
{
|
||||||
|
event->type = xevent->xany.type == KeyPress ? CLUTTER_KEY_PRESS
|
||||||
|
: CLUTTER_KEY_RELEASE;
|
||||||
|
event->time = xevent->xkey.time;
|
||||||
|
event->modifier_state = xevent->xkey.state; /* FIXME: handle modifiers */
|
||||||
|
event->hardware_keycode = xevent->xkey.keycode;
|
||||||
|
event->keyval = XKeycodeToKeysym(xevent->xkey.display,
|
||||||
|
xevent->xkey.keycode,
|
||||||
|
0 ); /* FIXME: index with modifiers */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
translate_button_event (ClutterButtonEvent *event,
|
||||||
|
XEvent *xevent)
|
||||||
|
{
|
||||||
|
/* FIXME: catch double click */
|
||||||
|
CLUTTER_NOTE (EVENT, " button event at %ix%i",
|
||||||
|
xevent->xbutton.x,
|
||||||
|
xevent->xbutton.y);
|
||||||
|
|
||||||
|
event->type = xevent->xany.type == ButtonPress ? CLUTTER_BUTTON_PRESS
|
||||||
|
: CLUTTER_BUTTON_RELEASE;
|
||||||
|
event->time = xevent->xbutton.time;
|
||||||
|
event->x = xevent->xbutton.x;
|
||||||
|
event->y = xevent->xbutton.y;
|
||||||
|
event->modifier_state = xevent->xbutton.state; /* includes button masks */
|
||||||
|
event->button = xevent->xbutton.button;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
translate_motion_event (ClutterMotionEvent *event,
|
||||||
|
XEvent *xevent)
|
||||||
|
{
|
||||||
|
event->type = CLUTTER_MOTION;
|
||||||
|
event->time = xevent->xbutton.time;
|
||||||
|
event->x = xevent->xmotion.x;
|
||||||
|
event->y = xevent->xmotion.y;
|
||||||
|
event->modifier_state = xevent->xmotion.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_dispatch_x_event (XEvent *xevent,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
ClutterMainContext *ctx = CLUTTER_CONTEXT ();
|
||||||
|
ClutterEvent event;
|
||||||
|
ClutterStage *stage = ctx->stage;
|
||||||
|
gboolean emit_input_event = FALSE;
|
||||||
|
|
||||||
|
switch (xevent->type)
|
||||||
|
{
|
||||||
|
case Expose:
|
||||||
|
{
|
||||||
|
XEvent foo_xev;
|
||||||
|
|
||||||
|
/* Cheap compress */
|
||||||
|
while (XCheckTypedWindowEvent(clutter_glx_display(),
|
||||||
|
xevent->xexpose.window,
|
||||||
|
Expose,
|
||||||
|
&foo_xev));
|
||||||
|
|
||||||
|
/* FIXME: need to make stage an 'actor' so can que
|
||||||
|
* a paint direct from there rather than hack here...
|
||||||
|
*/
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KeyPress:
|
||||||
|
translate_key_event ((ClutterKeyEvent *) &event, xevent);
|
||||||
|
g_signal_emit_by_name (stage, "key-press-event", &event);
|
||||||
|
emit_input_event = TRUE;
|
||||||
|
break;
|
||||||
|
case KeyRelease:
|
||||||
|
translate_key_event ((ClutterKeyEvent *) &event, xevent);
|
||||||
|
g_signal_emit_by_name (stage, "key-release-event", &event);
|
||||||
|
emit_input_event = TRUE;
|
||||||
|
break;
|
||||||
|
case ButtonPress:
|
||||||
|
translate_button_event ((ClutterButtonEvent *) &event, xevent);
|
||||||
|
g_signal_emit_by_name (stage, "button-press-event", &event);
|
||||||
|
emit_input_event = TRUE;
|
||||||
|
break;
|
||||||
|
case ButtonRelease:
|
||||||
|
translate_button_event ((ClutterButtonEvent *) &event, xevent);
|
||||||
|
g_signal_emit_by_name (stage, "button-release-event", &event);
|
||||||
|
emit_input_event = TRUE;
|
||||||
|
break;
|
||||||
|
case MotionNotify:
|
||||||
|
translate_motion_event ((ClutterMotionEvent *) &event, xevent);
|
||||||
|
g_signal_emit_by_name (stage, "motion-event", &event);
|
||||||
|
emit_input_event = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emit_input_event)
|
||||||
|
g_signal_emit_by_name (stage, "input-event", &event);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
events_init()
|
||||||
|
{
|
||||||
|
ClutterMainContext *clutter_context;
|
||||||
|
GMainContext *gmain_context;
|
||||||
|
int connection_number;
|
||||||
|
GSource *source;
|
||||||
|
ClutterXEventSource *display_source;
|
||||||
|
|
||||||
|
clutter_context = clutter_context_get_default ();
|
||||||
|
gmain_context = g_main_context_default ();
|
||||||
|
|
||||||
|
g_main_context_ref (gmain_context);
|
||||||
|
|
||||||
|
connection_number = ConnectionNumber (clutter_glx_display());
|
||||||
|
|
||||||
|
source = g_source_new ((GSourceFuncs *)&x_event_funcs,
|
||||||
|
sizeof (ClutterXEventSource));
|
||||||
|
|
||||||
|
display_source = (ClutterXEventSource *)source;
|
||||||
|
|
||||||
|
display_source->event_poll_fd.fd = connection_number;
|
||||||
|
display_source->event_poll_fd.events = G_IO_IN;
|
||||||
|
display_source->display = clutter_glx_display();
|
||||||
|
|
||||||
|
g_source_add_poll (source, &display_source->event_poll_fd);
|
||||||
|
g_source_set_can_recurse (source, TRUE);
|
||||||
|
|
||||||
|
g_source_set_callback (source,
|
||||||
|
(GSourceFunc) clutter_dispatch_x_event,
|
||||||
|
NULL /* no userdata */, NULL);
|
||||||
|
|
||||||
|
g_source_attach (source, gmain_context);
|
||||||
|
g_source_unref (source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sync_fullscreen (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN;
|
||||||
|
gboolean want_fullscreen;
|
||||||
|
|
||||||
|
atom_WINDOW_STATE
|
||||||
|
= XInternAtom(clutter_glx_display(), "_NET_WM_STATE", False);
|
||||||
|
atom_WINDOW_STATE_FULLSCREEN
|
||||||
|
= XInternAtom(clutter_glx_display(), "_NET_WM_STATE_FULLSCREEN",False);
|
||||||
|
|
||||||
|
g_object_get (stage, "fullscreen", &want_fullscreen, NULL);
|
||||||
|
|
||||||
|
if (want_fullscreen)
|
||||||
|
{
|
||||||
|
clutter_actor_set_size (CLUTTER_ACTOR(stage),
|
||||||
|
DisplayWidth(clutter_glx_display(),
|
||||||
|
clutter_glx_screen()),
|
||||||
|
DisplayHeight(clutter_glx_display(),
|
||||||
|
clutter_glx_screen()));
|
||||||
|
|
||||||
|
if (stage->backend->xwin != None)
|
||||||
|
XChangeProperty(clutter_glx_display(), stage->backend->xwin,
|
||||||
|
atom_WINDOW_STATE, XA_ATOM, 32,
|
||||||
|
PropModeReplace,
|
||||||
|
(unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (stage->backend->xwin != None)
|
||||||
|
XDeleteProperty(clutter_glx_display(),
|
||||||
|
stage->backend->xwin, atom_WINDOW_STATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sync_cursor (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
gboolean hide_cursor;
|
||||||
|
|
||||||
|
if (stage->backend->xwin == None)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_object_get (stage, "hide-cursor", &hide_cursor, NULL);
|
||||||
|
|
||||||
|
/* FIXME: Use XFixesHideCursor */
|
||||||
|
|
||||||
|
if (hide_cursor)
|
||||||
|
{
|
||||||
|
XColor col;
|
||||||
|
Pixmap pix;
|
||||||
|
Cursor curs;
|
||||||
|
|
||||||
|
pix = XCreatePixmap (clutter_glx_display(),
|
||||||
|
stage->backend->xwin, 1, 1, 1);
|
||||||
|
memset (&col, 0, sizeof (col));
|
||||||
|
curs = XCreatePixmapCursor (clutter_glx_display(),
|
||||||
|
pix, pix, &col, &col, 1, 1);
|
||||||
|
XFreePixmap (clutter_glx_display(), pix);
|
||||||
|
XDefineCursor(clutter_glx_display(), stage->backend->xwin, curs);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XUndefineCursor(clutter_glx_display(), stage->backend->xwin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME -> CGL */
|
||||||
|
static void
|
||||||
|
frustum (GLfloat left,
|
||||||
|
GLfloat right,
|
||||||
|
GLfloat bottom,
|
||||||
|
GLfloat top,
|
||||||
|
GLfloat nearval,
|
||||||
|
GLfloat farval)
|
||||||
|
{
|
||||||
|
GLfloat x, y, a, b, c, d;
|
||||||
|
GLfloat m[16];
|
||||||
|
|
||||||
|
x = (2.0 * nearval) / (right - left);
|
||||||
|
y = (2.0 * nearval) / (top - bottom);
|
||||||
|
a = (right + left) / (right - left);
|
||||||
|
b = (top + bottom) / (top - bottom);
|
||||||
|
c = -(farval + nearval) / ( farval - nearval);
|
||||||
|
d = -(2.0 * farval * nearval) / (farval - nearval);
|
||||||
|
|
||||||
|
#define M(row,col) m[col*4+row]
|
||||||
|
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
|
||||||
|
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
|
||||||
|
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
|
||||||
|
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
|
||||||
|
#undef M
|
||||||
|
|
||||||
|
glMultMatrixf (m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
perspective (GLfloat fovy,
|
||||||
|
GLfloat aspect,
|
||||||
|
GLfloat zNear,
|
||||||
|
GLfloat zFar)
|
||||||
|
{
|
||||||
|
GLfloat xmin, xmax, ymin, ymax;
|
||||||
|
|
||||||
|
ymax = zNear * tan (fovy * M_PI / 360.0);
|
||||||
|
ymin = -ymax;
|
||||||
|
xmin = ymin * aspect;
|
||||||
|
xmax = ymax * aspect;
|
||||||
|
|
||||||
|
frustum (xmin, xmax, ymin, ymax, zNear, zFar);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
sync_viewport (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
glViewport (0, 0, stage->backend->xwin_width, stage->backend->xwin_height);
|
||||||
|
glMatrixMode (GL_PROJECTION);
|
||||||
|
glLoadIdentity ();
|
||||||
|
perspective (60.0f, 1.0f, 0.1f, 100.0f);
|
||||||
|
glMatrixMode (GL_MODELVIEW);
|
||||||
|
glLoadIdentity ();
|
||||||
|
|
||||||
|
/* Then for 2D like transform */
|
||||||
|
|
||||||
|
/* camera distance from screen, 0.5 * tan (FOV) */
|
||||||
|
#define DEFAULT_Z_CAMERA 0.866025404f
|
||||||
|
|
||||||
|
glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
|
||||||
|
glScalef (1.0f / stage->backend->xwin_width,
|
||||||
|
-1.0f / stage->backend->xwin_height,
|
||||||
|
1.0f / stage->backend->xwin_width);
|
||||||
|
glTranslatef (0.0f, -stage->backend->xwin_height, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_show (ClutterActor *self)
|
||||||
|
{
|
||||||
|
if (clutter_stage_glx_window (CLUTTER_STAGE(self)))
|
||||||
|
XMapWindow (clutter_glx_display(),
|
||||||
|
clutter_stage_glx_window (CLUTTER_STAGE(self)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_hide (ClutterActor *self)
|
||||||
|
{
|
||||||
|
if (clutter_stage_glx_window (CLUTTER_STAGE(self)))
|
||||||
|
XUnmapWindow (clutter_glx_display(),
|
||||||
|
clutter_stage_glx_window (CLUTTER_STAGE(self)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterStage *stage;
|
||||||
|
ClutterStagePrivate *priv;
|
||||||
|
ClutterStageBackend *backend;
|
||||||
|
gboolean want_offscreen;
|
||||||
|
|
||||||
|
stage = CLUTTER_STAGE(actor);
|
||||||
|
priv = stage->priv;
|
||||||
|
backend = stage->backend;
|
||||||
|
|
||||||
|
CLUTTER_MARK();
|
||||||
|
|
||||||
|
g_object_get (stage, "offscreen", &want_offscreen, NULL);
|
||||||
|
|
||||||
|
if (want_offscreen)
|
||||||
|
{
|
||||||
|
if (backend->glxpixmap)
|
||||||
|
{
|
||||||
|
glXDestroyGLXPixmap (clutter_glx_display(), backend->glxpixmap);
|
||||||
|
backend->glxpixmap = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend->xpixmap)
|
||||||
|
{
|
||||||
|
XFreePixmap (clutter_glx_display(), backend->xpixmap);
|
||||||
|
backend->xpixmap = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!backend->is_foreign_xwin && backend->xwin != None)
|
||||||
|
{
|
||||||
|
XDestroyWindow (clutter_glx_display(), backend->xwin);
|
||||||
|
backend->xwin = None;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
backend->xwin = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
glXMakeCurrent(clutter_glx_display(), None, NULL);
|
||||||
|
if (backend->gl_context != None)
|
||||||
|
{
|
||||||
|
glXDestroyContext (clutter_glx_display(), backend->gl_context);
|
||||||
|
backend->gl_context = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_realize (ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ClutterStage *stage;
|
||||||
|
ClutterStagePrivate *priv;
|
||||||
|
ClutterStageBackend *backend;
|
||||||
|
gboolean want_offscreen;
|
||||||
|
|
||||||
|
stage = CLUTTER_STAGE(actor);
|
||||||
|
|
||||||
|
priv = stage->priv;
|
||||||
|
backend = stage->backend;
|
||||||
|
|
||||||
|
CLUTTER_MARK();
|
||||||
|
|
||||||
|
g_object_get (stage, "offscreen", &want_offscreen, NULL);
|
||||||
|
|
||||||
|
if (want_offscreen)
|
||||||
|
{
|
||||||
|
int gl_attributes[] = {
|
||||||
|
GLX_RGBA,
|
||||||
|
GLX_RED_SIZE, 1,
|
||||||
|
GLX_GREEN_SIZE, 1,
|
||||||
|
GLX_BLUE_SIZE, 1,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (backend->xvisinfo)
|
||||||
|
XFree(backend->xvisinfo);
|
||||||
|
|
||||||
|
backend->xvisinfo = glXChooseVisual (clutter_glx_display(),
|
||||||
|
clutter_glx_screen(),
|
||||||
|
gl_attributes);
|
||||||
|
if (!backend->xvisinfo)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to find suitable GL visual.");
|
||||||
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend->gl_context)
|
||||||
|
glXDestroyContext (clutter_glx_display(), backend->gl_context);
|
||||||
|
|
||||||
|
backend->xpixmap = XCreatePixmap (clutter_glx_display(),
|
||||||
|
clutter_glx_root_window(),
|
||||||
|
backend->xwin_width,
|
||||||
|
backend->xwin_height,
|
||||||
|
backend->xvisinfo->depth);
|
||||||
|
|
||||||
|
backend->glxpixmap = glXCreateGLXPixmap(clutter_glx_display(),
|
||||||
|
backend->xvisinfo,
|
||||||
|
backend->xpixmap);
|
||||||
|
sync_fullscreen (stage);
|
||||||
|
|
||||||
|
/* indirect */
|
||||||
|
backend->gl_context = glXCreateContext (clutter_glx_display(),
|
||||||
|
backend->xvisinfo,
|
||||||
|
0,
|
||||||
|
False);
|
||||||
|
|
||||||
|
glXMakeCurrent(clutter_glx_display(),
|
||||||
|
backend->glxpixmap, backend->gl_context);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Debug code for monitoring a off screen pixmap via window */
|
||||||
|
{
|
||||||
|
Colormap cmap;
|
||||||
|
XSetWindowAttributes swa;
|
||||||
|
|
||||||
|
cmap = XCreateColormap(clutter_glx_display(),
|
||||||
|
clutter_glx_root_window(),
|
||||||
|
backend->xvisinfo->visual, AllocNone);
|
||||||
|
|
||||||
|
/* create a window */
|
||||||
|
swa.colormap = cmap;
|
||||||
|
|
||||||
|
foo_win = XCreateWindow(clutter_glx_display(),
|
||||||
|
clutter_glx_root_window(),
|
||||||
|
0, 0,
|
||||||
|
backend->xwin_width, backend->xwin_height,
|
||||||
|
0,
|
||||||
|
backend->xvisinfo->depth,
|
||||||
|
InputOutput,
|
||||||
|
backend->xvisinfo->visual,
|
||||||
|
CWColormap, &swa);
|
||||||
|
|
||||||
|
XMapWindow(clutter_glx_display(), foo_win);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int gl_attributes[] =
|
||||||
|
{
|
||||||
|
GLX_RGBA,
|
||||||
|
GLX_DOUBLEBUFFER,
|
||||||
|
GLX_RED_SIZE, 1,
|
||||||
|
GLX_GREEN_SIZE, 1,
|
||||||
|
GLX_BLUE_SIZE, 1,
|
||||||
|
GLX_STENCIL_SIZE, 1,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
if (backend->xvisinfo)
|
||||||
|
XFree(backend->xvisinfo);
|
||||||
|
|
||||||
|
if (backend->xvisinfo == None)
|
||||||
|
backend->xvisinfo = glXChooseVisual (clutter_glx_display(),
|
||||||
|
clutter_glx_screen(),
|
||||||
|
gl_attributes);
|
||||||
|
if (!backend->xvisinfo)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to find suitable GL visual.");
|
||||||
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend->xwin == None)
|
||||||
|
backend->xwin = XCreateSimpleWindow(clutter_glx_display(),
|
||||||
|
clutter_glx_root_window(),
|
||||||
|
0, 0,
|
||||||
|
backend->xwin_width, backend->xwin_height,
|
||||||
|
0, 0,
|
||||||
|
WhitePixel(clutter_glx_display(),
|
||||||
|
clutter_glx_screen()));
|
||||||
|
XSelectInput(clutter_glx_display(),
|
||||||
|
backend->xwin,
|
||||||
|
StructureNotifyMask
|
||||||
|
|ExposureMask
|
||||||
|
/* FIXME: we may want to eplicity enable MotionMask */
|
||||||
|
|PointerMotionMask
|
||||||
|
|KeyPressMask
|
||||||
|
|KeyReleaseMask
|
||||||
|
|ButtonPressMask
|
||||||
|
|ButtonReleaseMask
|
||||||
|
|PropertyChangeMask);
|
||||||
|
|
||||||
|
sync_fullscreen (stage);
|
||||||
|
sync_cursor (stage);
|
||||||
|
|
||||||
|
if (backend->gl_context)
|
||||||
|
glXDestroyContext (clutter_glx_display(), backend->gl_context);
|
||||||
|
|
||||||
|
backend->gl_context = glXCreateContext (clutter_glx_display(),
|
||||||
|
backend->xvisinfo,
|
||||||
|
0,
|
||||||
|
True);
|
||||||
|
|
||||||
|
if (backend->gl_context == None)
|
||||||
|
{
|
||||||
|
g_critical ("Unable to create suitable GL context.");
|
||||||
|
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glXMakeCurrent(clutter_glx_display(), backend->xwin, backend->gl_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_NOTE (GL,
|
||||||
|
"\n"
|
||||||
|
"===========================================\n"
|
||||||
|
"GL_VENDOR: %s\n"
|
||||||
|
"GL_RENDERER: %s\n"
|
||||||
|
"GL_VERSION: %s\n"
|
||||||
|
"GL_EXTENSIONS: %s\n"
|
||||||
|
"Is direct: %s\n"
|
||||||
|
"===========================================\n",
|
||||||
|
glGetString (GL_VENDOR),
|
||||||
|
glGetString (GL_RENDERER),
|
||||||
|
glGetString (GL_VERSION),
|
||||||
|
glGetString (GL_EXTENSIONS),
|
||||||
|
glXIsDirect(clutter_glx_display(), backend->gl_context) ? "yes" : "no"
|
||||||
|
);
|
||||||
|
|
||||||
|
sync_viewport (stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_paint (ClutterActor *self)
|
||||||
|
{
|
||||||
|
ClutterStage *stage = CLUTTER_STAGE(self);
|
||||||
|
ClutterColor stage_color;
|
||||||
|
static GTimer *timer = NULL;
|
||||||
|
static guint timer_n_frames = 0;
|
||||||
|
|
||||||
|
static ClutterActorClass *parent_class = NULL;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (PAINT, " Redraw enter");
|
||||||
|
|
||||||
|
if (parent_class == NULL)
|
||||||
|
parent_class = g_type_class_peek_parent (CLUTTER_STAGE_GET_CLASS(stage));
|
||||||
|
|
||||||
|
if (clutter_want_fps ())
|
||||||
|
{
|
||||||
|
if (!timer)
|
||||||
|
timer = g_timer_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
clutter_stage_get_color (stage, &stage_color);
|
||||||
|
|
||||||
|
glClearColor(((float) stage_color.red / 0xff * 1.0),
|
||||||
|
((float) stage_color.green / 0xff * 1.0),
|
||||||
|
((float) stage_color.blue / 0xff * 1.0),
|
||||||
|
0.0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
parent_class->paint (self);
|
||||||
|
|
||||||
|
if (clutter_stage_glx_window (stage))
|
||||||
|
{
|
||||||
|
clutter_feature_wait_for_vblank ();
|
||||||
|
glXSwapBuffers(clutter_glx_display(), clutter_stage_glx_window (stage));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glXWaitGL();
|
||||||
|
CLUTTER_GLERR();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clutter_want_fps ())
|
||||||
|
{
|
||||||
|
timer_n_frames++;
|
||||||
|
|
||||||
|
if (g_timer_elapsed (timer, NULL) >= 1.0)
|
||||||
|
{
|
||||||
|
g_print ("*** FPS: %i ***\n", timer_n_frames);
|
||||||
|
timer_n_frames = 0;
|
||||||
|
g_timer_start (timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_NOTE (PAINT, " Redraw leave");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_allocate_coords (ClutterActor *self,
|
||||||
|
ClutterActorBox *box)
|
||||||
|
{
|
||||||
|
/* Do nothing, just stop group_allocate getting called */
|
||||||
|
|
||||||
|
/* TODO: sync up with any configure events from WM ?? */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_request_coords (ClutterActor *self,
|
||||||
|
ClutterActorBox *box)
|
||||||
|
{
|
||||||
|
ClutterStage *stage;
|
||||||
|
ClutterStageBackend *backend;
|
||||||
|
gint new_width, new_height;
|
||||||
|
|
||||||
|
stage = CLUTTER_STAGE (self);
|
||||||
|
backend = stage->backend;
|
||||||
|
|
||||||
|
/* FIXME: some how have X configure_notfiys call this ?
|
||||||
|
*/
|
||||||
|
|
||||||
|
new_width = ABS(box->x2 - box->x1);
|
||||||
|
new_height = ABS(box->y2 - box->y1);
|
||||||
|
|
||||||
|
if (new_width != backend->xwin_width || new_height != backend->xwin_height)
|
||||||
|
{
|
||||||
|
backend->xwin_width = new_width;
|
||||||
|
backend->xwin_height = new_height;
|
||||||
|
|
||||||
|
if (backend->xwin != None)
|
||||||
|
XResizeWindow (clutter_glx_display(),
|
||||||
|
backend->xwin,
|
||||||
|
backend->xwin_width,
|
||||||
|
backend->xwin_height);
|
||||||
|
|
||||||
|
if (backend->xpixmap != None)
|
||||||
|
{
|
||||||
|
/* Need to recreate to resize */
|
||||||
|
clutter_actor_unrealize(self);
|
||||||
|
clutter_actor_realize(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_viewport (stage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backend->xwin != None) /* Do we want to bother ? */
|
||||||
|
XMoveWindow (clutter_glx_display(),
|
||||||
|
backend->xwin,
|
||||||
|
box->x1,
|
||||||
|
box->y1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
ClutterStage *self = CLUTTER_STAGE (object);
|
||||||
|
|
||||||
|
if (self->backend->xwin)
|
||||||
|
clutter_actor_unrealize (CLUTTER_ACTOR (self));
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (clutter_stage_parent_class)->dispose (object);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_stage_glx_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_stage_backend_init_vtable (ClutterStageVTable *vtable)
|
||||||
|
{
|
||||||
|
vtable->show = clutter_stage_glx_show;
|
||||||
|
vtable->hide = clutter_stage_glx_hide;
|
||||||
|
vtable->realize = clutter_stage_glx_realize;
|
||||||
|
vtable->unrealize = clutter_stage_glx_unrealize;
|
||||||
|
vtable->paint = clutter_stage_glx_paint;
|
||||||
|
vtable->request_coords = clutter_stage_glx_request_coords;
|
||||||
|
vtable->allocate_coords = clutter_stage_glx_allocate_coords;
|
||||||
|
|
||||||
|
vtable->sync_fullscreen = sync_fullscreen;
|
||||||
|
vtable->sync_cursor = sync_cursor;
|
||||||
|
vtable->sync_viewport = sync_viewport;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterStageBackend*
|
||||||
|
clutter_stage_backend_init (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
ClutterStageBackend *backend;
|
||||||
|
|
||||||
|
backend = g_new0(ClutterStageBackend, 1);
|
||||||
|
|
||||||
|
backend->xwin_width = 100;
|
||||||
|
backend->xwin_height = 100;
|
||||||
|
|
||||||
|
/* Maybe better somewhere else */
|
||||||
|
events_init ();
|
||||||
|
|
||||||
|
return backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_stage_glx_get_xwindow
|
||||||
|
* @stage: A #ClutterStage
|
||||||
|
*
|
||||||
|
* Get the stage's underlying x window ID.
|
||||||
|
*
|
||||||
|
* Return Value: Stage X Window XID
|
||||||
|
*
|
||||||
|
* Since: 0.3
|
||||||
|
**/
|
||||||
|
Window
|
||||||
|
clutter_stage_glx_window (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
return stage->backend->xwin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_stage_set_xwindow_foreign
|
||||||
|
* @stage: A #ClutterStage
|
||||||
|
* @xid: A preexisting X Window ID
|
||||||
|
*
|
||||||
|
* Target the #ClutterStage to use an existing external X Window.
|
||||||
|
*
|
||||||
|
* Return Value: TRUE if foreign window valid, FALSE otherwise
|
||||||
|
*
|
||||||
|
* Since: 0.3
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
clutter_stage_glx_set_window_foreign (ClutterStage *stage,
|
||||||
|
Window xid)
|
||||||
|
{
|
||||||
|
/* For screensavers via XSCREENSAVER_WINDOW env var.
|
||||||
|
* Also for toolkit binding.
|
||||||
|
*/
|
||||||
|
gint x,y;
|
||||||
|
guint width, height, border, depth;
|
||||||
|
Window root_return;
|
||||||
|
Status status;
|
||||||
|
ClutterGeometry geom;
|
||||||
|
|
||||||
|
clutter_glx_trap_x_errors();
|
||||||
|
|
||||||
|
status = XGetGeometry (clutter_glx_display(),
|
||||||
|
xid,
|
||||||
|
&root_return,
|
||||||
|
&x,
|
||||||
|
&y,
|
||||||
|
&width,
|
||||||
|
&height,
|
||||||
|
&border,
|
||||||
|
&depth);
|
||||||
|
|
||||||
|
if (clutter_glx_untrap_x_errors() || !status
|
||||||
|
|| width == 0 || height == 0 || depth != stage->backend->xvisinfo->depth)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
clutter_actor_unrealize (CLUTTER_ACTOR(stage));
|
||||||
|
|
||||||
|
stage->backend->xwin = xid;
|
||||||
|
|
||||||
|
geom.x = x;
|
||||||
|
geom.y = y;
|
||||||
|
|
||||||
|
geom.width = stage->backend->xwin_width = width;
|
||||||
|
geom.height = stage->backend->xwin_height = height;
|
||||||
|
|
||||||
|
clutter_actor_set_geometry (CLUTTER_ACTOR(stage), &geom);
|
||||||
|
|
||||||
|
clutter_actor_realize (CLUTTER_ACTOR(stage));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_stage_glx_get_xvisual
|
||||||
|
* @stage: A #ClutterStage
|
||||||
|
*
|
||||||
|
* Get the stage's XVisualInfo.
|
||||||
|
*
|
||||||
|
* Return Value: The stage's XVisualInfo
|
||||||
|
*
|
||||||
|
* Since: 0.3
|
||||||
|
**/
|
||||||
|
const XVisualInfo*
|
||||||
|
clutter_stage_glx_get_visual (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
return stage->backend->xvisinfo;
|
||||||
|
}
|
58
clutter/clutter-stage-glx.h
Normal file
58
clutter/clutter-stage-glx.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Clutter.
|
||||||
|
*
|
||||||
|
* An OpenGL based 'interactive canvas' library.
|
||||||
|
*
|
||||||
|
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006 OpenedHand
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HAVE_CLUTTER_STAGE_GLX_H
|
||||||
|
#define _HAVE_CLUTTER_STAGE_GLX_H
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
#include <clutter/clutter-stage.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_stage_backend_init_vtable (ClutterStageVTable *vtable) G_GNUC_INTERNAL;
|
||||||
|
|
||||||
|
ClutterStageBackend*
|
||||||
|
clutter_stage_backend_init (ClutterStage *stage) G_GNUC_INTERNAL;
|
||||||
|
|
||||||
|
Window
|
||||||
|
clutter_stage_glx_window (ClutterStage *stage);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
clutter_stage_glx_set_window_foreign (ClutterStage *stage,
|
||||||
|
Window xid);
|
||||||
|
|
||||||
|
const XVisualInfo*
|
||||||
|
clutter_stage_glx_get_xvisual (ClutterStage *stage);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
@ -42,14 +42,22 @@
|
|||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-debug.h"
|
#include "clutter-debug.h"
|
||||||
|
|
||||||
#include <GL/glx.h>
|
#ifdef CLUTTER_BACKEND_GLX
|
||||||
#include <GL/gl.h>
|
#include <clutter/clutter-stage-glx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CLUTTER_BACKEND_EGL
|
||||||
|
#include <clutter/clutter-stage-egl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
|
||||||
|
|
||||||
/* the stage is a singleton instance */
|
/* the stage is a singleton instance */
|
||||||
static ClutterStage *stage_singleton = NULL;
|
static ClutterStage *stage_singleton = NULL;
|
||||||
|
|
||||||
|
/* Backend hooks */
|
||||||
|
static ClutterStageVTable _vtable;
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
|
G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
|
||||||
|
|
||||||
#define CLUTTER_STAGE_GET_PRIVATE(obj) \
|
#define CLUTTER_STAGE_GET_PRIVATE(obj) \
|
||||||
@ -57,21 +65,11 @@ G_DEFINE_TYPE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP);
|
|||||||
|
|
||||||
struct _ClutterStagePrivate
|
struct _ClutterStagePrivate
|
||||||
{
|
{
|
||||||
XVisualInfo *xvisinfo;
|
|
||||||
Window xwin;
|
|
||||||
Pixmap xpixmap;
|
|
||||||
gint xwin_width, xwin_height; /* FIXME target_width / height */
|
|
||||||
|
|
||||||
GLXPixmap glxpixmap;
|
|
||||||
GLXContext gl_context;
|
|
||||||
|
|
||||||
|
|
||||||
ClutterColor color;
|
ClutterColor color;
|
||||||
|
|
||||||
guint want_fullscreen : 1;
|
guint want_fullscreen : 1;
|
||||||
guint want_offscreen : 1;
|
guint want_offscreen : 1;
|
||||||
guint hide_cursor : 1;
|
guint hide_cursor : 1;
|
||||||
guint is_foreign_xwin : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -100,511 +98,6 @@ static guint stage_signals[LAST_SIGNAL] = { 0 };
|
|||||||
|
|
||||||
static ClutterActorClass *parent_class = NULL;
|
static ClutterActorClass *parent_class = NULL;
|
||||||
|
|
||||||
static void
|
|
||||||
sync_fullscreen (ClutterStage *stage)
|
|
||||||
{
|
|
||||||
Atom atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN;
|
|
||||||
|
|
||||||
atom_WINDOW_STATE
|
|
||||||
= XInternAtom(clutter_xdisplay(), "_NET_WM_STATE", False);
|
|
||||||
atom_WINDOW_STATE_FULLSCREEN
|
|
||||||
= XInternAtom(clutter_xdisplay(), "_NET_WM_STATE_FULLSCREEN",False);
|
|
||||||
|
|
||||||
if (stage->priv->want_fullscreen)
|
|
||||||
{
|
|
||||||
clutter_actor_set_size (CLUTTER_ACTOR(stage),
|
|
||||||
DisplayWidth(clutter_xdisplay(),
|
|
||||||
clutter_xscreen()),
|
|
||||||
DisplayHeight(clutter_xdisplay(),
|
|
||||||
clutter_xscreen()));
|
|
||||||
|
|
||||||
if (stage->priv->xwin != None)
|
|
||||||
XChangeProperty(clutter_xdisplay(), stage->priv->xwin,
|
|
||||||
atom_WINDOW_STATE, XA_ATOM, 32,
|
|
||||||
PropModeReplace,
|
|
||||||
(unsigned char *)&atom_WINDOW_STATE_FULLSCREEN, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (stage->priv->xwin != None)
|
|
||||||
XDeleteProperty(clutter_xdisplay(),
|
|
||||||
stage->priv->xwin, atom_WINDOW_STATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sync_cursor_visible (ClutterStage *stage)
|
|
||||||
{
|
|
||||||
if (stage->priv->xwin == None)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (stage->priv->hide_cursor)
|
|
||||||
{
|
|
||||||
XColor col;
|
|
||||||
Pixmap pix;
|
|
||||||
Cursor curs;
|
|
||||||
|
|
||||||
pix = XCreatePixmap (clutter_xdisplay(),
|
|
||||||
stage->priv->xwin, 1, 1, 1);
|
|
||||||
memset (&col, 0, sizeof (col));
|
|
||||||
curs = XCreatePixmapCursor (clutter_xdisplay(),
|
|
||||||
pix, pix, &col, &col, 1, 1);
|
|
||||||
XFreePixmap (clutter_xdisplay(), pix);
|
|
||||||
XDefineCursor(clutter_xdisplay(), stage->priv->xwin, curs);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XUndefineCursor(clutter_xdisplay(), stage->priv->xwin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
frustum (GLfloat left,
|
|
||||||
GLfloat right,
|
|
||||||
GLfloat bottom,
|
|
||||||
GLfloat top,
|
|
||||||
GLfloat nearval,
|
|
||||||
GLfloat farval)
|
|
||||||
{
|
|
||||||
GLfloat x, y, a, b, c, d;
|
|
||||||
GLfloat m[16];
|
|
||||||
|
|
||||||
x = (2.0 * nearval) / (right - left);
|
|
||||||
y = (2.0 * nearval) / (top - bottom);
|
|
||||||
a = (right + left) / (right - left);
|
|
||||||
b = (top + bottom) / (top - bottom);
|
|
||||||
c = -(farval + nearval) / ( farval - nearval);
|
|
||||||
d = -(2.0 * farval * nearval) / (farval - nearval);
|
|
||||||
|
|
||||||
#define M(row,col) m[col*4+row]
|
|
||||||
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
|
|
||||||
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
|
|
||||||
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
|
|
||||||
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
|
|
||||||
#undef M
|
|
||||||
|
|
||||||
glMultMatrixf (m);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
perspective (GLfloat fovy,
|
|
||||||
GLfloat aspect,
|
|
||||||
GLfloat zNear,
|
|
||||||
GLfloat zFar)
|
|
||||||
{
|
|
||||||
GLfloat xmin, xmax, ymin, ymax;
|
|
||||||
|
|
||||||
ymax = zNear * tan (fovy * M_PI / 360.0);
|
|
||||||
ymin = -ymax;
|
|
||||||
xmin = ymin * aspect;
|
|
||||||
xmax = ymax * aspect;
|
|
||||||
|
|
||||||
frustum (xmin, xmax, ymin, ymax, zNear, zFar);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
sync_gl_viewport (ClutterStage *stage)
|
|
||||||
{
|
|
||||||
/* Set For 2D */
|
|
||||||
#if 0
|
|
||||||
glViewport (0, 0, stage->priv->xwin_width, stage->priv->xwin_height);
|
|
||||||
glMatrixMode (GL_PROJECTION);
|
|
||||||
glLoadIdentity ();
|
|
||||||
glOrtho (0, stage->priv->xwin_width, stage->priv->xwin_height, 0, -1, 1);
|
|
||||||
glMatrixMode (GL_MODELVIEW);
|
|
||||||
glLoadIdentity ();
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/* For 3D */
|
|
||||||
|
|
||||||
glViewport (0, 0, stage->priv->xwin_width, stage->priv->xwin_height);
|
|
||||||
glMatrixMode (GL_PROJECTION);
|
|
||||||
glLoadIdentity ();
|
|
||||||
perspective (60.0f, 1.0f, 0.1f, 100.0f);
|
|
||||||
glMatrixMode (GL_MODELVIEW);
|
|
||||||
glLoadIdentity ();
|
|
||||||
|
|
||||||
/* Then for 2D like transform */
|
|
||||||
|
|
||||||
/* camera distance from screen, 0.5 * tan (FOV) */
|
|
||||||
#define DEFAULT_Z_CAMERA 0.866025404f
|
|
||||||
|
|
||||||
glTranslatef (-0.5f, -0.5f, -DEFAULT_Z_CAMERA);
|
|
||||||
glScalef (1.0f / stage->priv->xwin_width,
|
|
||||||
-1.0f / stage->priv->xwin_height, 1.0f / stage->priv->xwin_width);
|
|
||||||
glTranslatef (0.0f, -stage->priv->xwin_height, 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_show (ClutterActor *self)
|
|
||||||
{
|
|
||||||
ClutterActorClass *parent_class;
|
|
||||||
|
|
||||||
parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
|
||||||
if (parent_class->show)
|
|
||||||
parent_class->show (self);
|
|
||||||
|
|
||||||
if (clutter_stage_get_xwindow (CLUTTER_STAGE (self)))
|
|
||||||
XMapWindow (clutter_xdisplay (),
|
|
||||||
clutter_stage_get_xwindow (CLUTTER_STAGE (self)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_hide (ClutterActor *self)
|
|
||||||
{
|
|
||||||
ClutterActorClass *parent_class;
|
|
||||||
|
|
||||||
parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
|
||||||
if (parent_class->hide)
|
|
||||||
parent_class->hide (self);
|
|
||||||
|
|
||||||
if (clutter_stage_get_xwindow (CLUTTER_STAGE (self)))
|
|
||||||
XUnmapWindow (clutter_xdisplay (),
|
|
||||||
clutter_stage_get_xwindow (CLUTTER_STAGE (self)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_unrealize (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterStage *stage;
|
|
||||||
ClutterStagePrivate *priv;
|
|
||||||
|
|
||||||
stage = CLUTTER_STAGE(actor);
|
|
||||||
priv = stage->priv;
|
|
||||||
|
|
||||||
CLUTTER_MARK();
|
|
||||||
|
|
||||||
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 (!priv->is_foreign_xwin && priv->xwin != None)
|
|
||||||
{
|
|
||||||
XDestroyWindow (clutter_xdisplay(), priv->xwin);
|
|
||||||
priv->xwin = None;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
priv->xwin = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
glXMakeCurrent(clutter_xdisplay(), None, NULL);
|
|
||||||
if (priv->gl_context != None)
|
|
||||||
{
|
|
||||||
glXDestroyContext (clutter_xdisplay(), priv->gl_context);
|
|
||||||
priv->gl_context = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_realize (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterStage *stage;
|
|
||||||
ClutterStagePrivate *priv;
|
|
||||||
|
|
||||||
stage = CLUTTER_STAGE(actor);
|
|
||||||
|
|
||||||
priv = stage->priv;
|
|
||||||
|
|
||||||
CLUTTER_MARK();
|
|
||||||
|
|
||||||
if (priv->want_offscreen)
|
|
||||||
{
|
|
||||||
int gl_attributes[] = {
|
|
||||||
GLX_RGBA,
|
|
||||||
GLX_RED_SIZE, 1,
|
|
||||||
GLX_GREEN_SIZE, 1,
|
|
||||||
GLX_BLUE_SIZE, 1,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (priv->xvisinfo)
|
|
||||||
XFree(priv->xvisinfo);
|
|
||||||
|
|
||||||
priv->xvisinfo = glXChooseVisual (clutter_xdisplay(),
|
|
||||||
clutter_xscreen(),
|
|
||||||
gl_attributes);
|
|
||||||
if (!priv->xvisinfo)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to find suitable GL visual.");
|
|
||||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->gl_context != None)
|
|
||||||
glXDestroyContext (clutter_xdisplay(), priv->gl_context);
|
|
||||||
|
|
||||||
priv->xpixmap = XCreatePixmap (clutter_xdisplay(),
|
|
||||||
clutter_root_xwindow(),
|
|
||||||
priv->xwin_width,
|
|
||||||
priv->xwin_height,
|
|
||||||
priv->xvisinfo->depth);
|
|
||||||
|
|
||||||
priv->glxpixmap = glXCreateGLXPixmap(clutter_xdisplay(),
|
|
||||||
priv->xvisinfo,
|
|
||||||
priv->xpixmap);
|
|
||||||
sync_fullscreen (stage);
|
|
||||||
|
|
||||||
/* indirect */
|
|
||||||
priv->gl_context = glXCreateContext (clutter_xdisplay(),
|
|
||||||
priv->xvisinfo,
|
|
||||||
0,
|
|
||||||
False);
|
|
||||||
|
|
||||||
glXMakeCurrent(clutter_xdisplay(), priv->glxpixmap, priv->gl_context);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Debug code for monitoring a off screen pixmap via window */
|
|
||||||
{
|
|
||||||
Colormap cmap;
|
|
||||||
XSetWindowAttributes swa;
|
|
||||||
|
|
||||||
cmap = XCreateColormap(clutter_xdisplay(),
|
|
||||||
clutter_root_xwindow(),
|
|
||||||
priv->xvisinfo->visual, AllocNone);
|
|
||||||
|
|
||||||
/* create a window */
|
|
||||||
swa.colormap = cmap;
|
|
||||||
|
|
||||||
foo_win = XCreateWindow(clutter_xdisplay(),
|
|
||||||
clutter_root_xwindow(),
|
|
||||||
0, 0,
|
|
||||||
priv->xwin_width, priv->xwin_height,
|
|
||||||
0,
|
|
||||||
priv->xvisinfo->depth,
|
|
||||||
InputOutput,
|
|
||||||
priv->xvisinfo->visual,
|
|
||||||
CWColormap, &swa);
|
|
||||||
|
|
||||||
XMapWindow(clutter_xdisplay(), foo_win);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int gl_attributes[] =
|
|
||||||
{
|
|
||||||
GLX_RGBA,
|
|
||||||
GLX_DOUBLEBUFFER,
|
|
||||||
GLX_RED_SIZE, 1,
|
|
||||||
GLX_GREEN_SIZE, 1,
|
|
||||||
GLX_BLUE_SIZE, 1,
|
|
||||||
GLX_STENCIL_SIZE, 1,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
if (priv->xvisinfo)
|
|
||||||
{
|
|
||||||
XFree(priv->xvisinfo);
|
|
||||||
priv->xvisinfo = None;
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
/* Attempted fix at GTK 'white' textures - made no difference :( */
|
|
||||||
if (priv->is_foreign_xwin && priv->xwin != None)
|
|
||||||
{
|
|
||||||
XWindowAttributes win_attr;
|
|
||||||
XVisualInfo vis_info;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
XGetWindowAttributes (clutter_xdisplay(), priv->xwin, &win_attr);
|
|
||||||
vis_info.screen = clutter_xscreen();
|
|
||||||
vis_info.visualid = XVisualIDFromVisual (win_attr.visual);
|
|
||||||
priv->xvisinfo = XGetVisualInfo (clutter_xdisplay(),
|
|
||||||
VisualScreenMask|VisualIDMask,
|
|
||||||
&vis_info, &n);
|
|
||||||
|
|
||||||
printf("made %li\n", priv->xvisinfo);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (priv->xvisinfo == None)
|
|
||||||
priv->xvisinfo = glXChooseVisual (clutter_xdisplay(),
|
|
||||||
clutter_xscreen(),
|
|
||||||
gl_attributes);
|
|
||||||
if (!priv->xvisinfo)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to find suitable GL visual.");
|
|
||||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE(GL, "visual id's %li vs %li",
|
|
||||||
priv->xvisinfo->visualid,
|
|
||||||
XVisualIDFromVisual(DefaultVisual(clutter_xdisplay(),
|
|
||||||
clutter_xscreen())));
|
|
||||||
|
|
||||||
|
|
||||||
if (priv->xwin == None)
|
|
||||||
{
|
|
||||||
XSetWindowAttributes swa;
|
|
||||||
|
|
||||||
if (priv->xvisinfo->visualid
|
|
||||||
== XVisualIDFromVisual(DefaultVisual(clutter_xdisplay(),
|
|
||||||
clutter_xscreen())))
|
|
||||||
{
|
|
||||||
swa.colormap = DefaultColormap(clutter_xdisplay(),
|
|
||||||
clutter_xscreen());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
swa.colormap = XCreateColormap(clutter_xdisplay(),
|
|
||||||
clutter_root_xwindow(),
|
|
||||||
priv->xvisinfo->visual,
|
|
||||||
AllocNone);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->xwin = XCreateWindow(clutter_xdisplay(),
|
|
||||||
clutter_root_xwindow(),
|
|
||||||
0, 0,
|
|
||||||
priv->xwin_width, priv->xwin_height,
|
|
||||||
0,
|
|
||||||
priv->xvisinfo->depth,
|
|
||||||
InputOutput,
|
|
||||||
priv->xvisinfo->visual,
|
|
||||||
CWColormap, &swa);
|
|
||||||
}
|
|
||||||
|
|
||||||
XSelectInput(clutter_xdisplay(),
|
|
||||||
priv->xwin,
|
|
||||||
StructureNotifyMask
|
|
||||||
|ExposureMask
|
|
||||||
/* FIXME: we may want to eplicity enable MotionMask */
|
|
||||||
|PointerMotionMask
|
|
||||||
|KeyPressMask
|
|
||||||
|KeyReleaseMask
|
|
||||||
|ButtonPressMask
|
|
||||||
|ButtonReleaseMask
|
|
||||||
|PropertyChangeMask);
|
|
||||||
|
|
||||||
sync_fullscreen (stage);
|
|
||||||
sync_cursor_visible (stage);
|
|
||||||
|
|
||||||
if (priv->gl_context != None)
|
|
||||||
glXDestroyContext (clutter_xdisplay(), priv->gl_context);
|
|
||||||
|
|
||||||
priv->gl_context = glXCreateContext (clutter_xdisplay(),
|
|
||||||
priv->xvisinfo,
|
|
||||||
0,
|
|
||||||
True);
|
|
||||||
if (priv->gl_context == None)
|
|
||||||
{
|
|
||||||
g_critical ("Unable to create suitable GL context.");
|
|
||||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
glXMakeCurrent(clutter_xdisplay(), priv->xwin, priv->gl_context);
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (GL,
|
|
||||||
"\n"
|
|
||||||
"==========================================="
|
|
||||||
"GL_VENDOR: %s\n"
|
|
||||||
"GL_RENDERER: %s\n"
|
|
||||||
"GL_VERSION: %s\n"
|
|
||||||
"GL_EXTENSIONS: %s\n"
|
|
||||||
"Is direct: %s\n"
|
|
||||||
"===========================================",
|
|
||||||
glGetString (GL_VENDOR),
|
|
||||||
glGetString (GL_RENDERER),
|
|
||||||
glGetString (GL_VERSION),
|
|
||||||
glGetString (GL_EXTENSIONS),
|
|
||||||
glXIsDirect(clutter_xdisplay(), priv->gl_context) ? "yes" : "no"
|
|
||||||
);
|
|
||||||
|
|
||||||
sync_gl_viewport (stage);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_paint (ClutterActor *self)
|
|
||||||
{
|
|
||||||
parent_class->paint (self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_allocate_coords (ClutterActor *self,
|
|
||||||
ClutterActorBox *box)
|
|
||||||
{
|
|
||||||
/* Do nothing, just stop group_allocate getting called */
|
|
||||||
|
|
||||||
/* TODO: sync up with any configure events from WM ?? */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_request_coords (ClutterActor *self,
|
|
||||||
ClutterActorBox *box)
|
|
||||||
{
|
|
||||||
ClutterStage *stage;
|
|
||||||
ClutterStagePrivate *priv;
|
|
||||||
gint new_width, new_height;
|
|
||||||
|
|
||||||
stage = CLUTTER_STAGE (self);
|
|
||||||
priv = stage->priv;
|
|
||||||
|
|
||||||
/* FIXME: some how have X configure_notfiys call this ?
|
|
||||||
*/
|
|
||||||
|
|
||||||
new_width = ABS(box->x2 - box->x1);
|
|
||||||
new_height = ABS(box->y2 - box->y1);
|
|
||||||
|
|
||||||
if (new_width != priv->xwin_width || new_height != priv->xwin_height)
|
|
||||||
{
|
|
||||||
priv->xwin_width = new_width;
|
|
||||||
priv->xwin_height = new_height;
|
|
||||||
|
|
||||||
if (priv->xwin != None)
|
|
||||||
XResizeWindow (clutter_xdisplay(),
|
|
||||||
priv->xwin,
|
|
||||||
priv->xwin_width,
|
|
||||||
priv->xwin_height);
|
|
||||||
|
|
||||||
if (priv->xpixmap)
|
|
||||||
{
|
|
||||||
/* Need to recreate to resize */
|
|
||||||
clutter_actor_unrealize(self);
|
|
||||||
clutter_actor_realize(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
sync_gl_viewport (stage);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->xwin != None) /* Do we want to bother ? */
|
|
||||||
XMoveWindow (clutter_xdisplay(),
|
|
||||||
priv->xwin,
|
|
||||||
box->x1,
|
|
||||||
box->y1);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
ClutterStage *self = CLUTTER_STAGE (object);
|
|
||||||
|
|
||||||
if (self->priv->xwin != None)
|
|
||||||
clutter_stage_unrealize (CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_stage_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_stage_finalize (GObject *object)
|
|
||||||
{
|
|
||||||
G_OBJECT_CLASS (clutter_stage_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_stage_set_property (GObject *object,
|
clutter_stage_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -640,14 +133,14 @@ clutter_stage_set_property (GObject *object,
|
|||||||
if (priv->want_fullscreen != g_value_get_boolean (value))
|
if (priv->want_fullscreen != g_value_get_boolean (value))
|
||||||
{
|
{
|
||||||
priv->want_fullscreen = g_value_get_boolean (value);
|
priv->want_fullscreen = g_value_get_boolean (value);
|
||||||
sync_fullscreen (stage);
|
_vtable.sync_fullscreen (stage);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PROP_HIDE_CURSOR:
|
case PROP_HIDE_CURSOR:
|
||||||
if (priv->hide_cursor != g_value_get_boolean (value))
|
if (priv->hide_cursor != g_value_get_boolean (value))
|
||||||
{
|
{
|
||||||
priv->hide_cursor = g_value_get_boolean (value);
|
priv->hide_cursor = g_value_get_boolean (value);
|
||||||
sync_cursor_visible (stage);
|
_vtable.sync_cursor (stage);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -698,17 +191,22 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
|||||||
|
|
||||||
parent_class = g_type_class_peek_parent (klass);
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
actor_class->realize = clutter_stage_realize;
|
clutter_stage_backend_init_vtable (&_vtable);
|
||||||
actor_class->unrealize = clutter_stage_unrealize;
|
|
||||||
actor_class->show = clutter_stage_show;
|
|
||||||
actor_class->hide = clutter_stage_hide;
|
|
||||||
actor_class->paint = clutter_stage_paint;
|
|
||||||
|
|
||||||
actor_class->request_coords = clutter_stage_request_coords;
|
actor_class->realize = _vtable.realize;
|
||||||
actor_class->allocate_coords = clutter_stage_allocate_coords;
|
actor_class->unrealize = _vtable.unrealize;
|
||||||
|
actor_class->show = _vtable.show;
|
||||||
|
actor_class->hide = _vtable.hide;
|
||||||
|
actor_class->paint = _vtable.paint;
|
||||||
|
|
||||||
|
actor_class->request_coords = _vtable.request_coords;
|
||||||
|
actor_class->allocate_coords = _vtable.allocate_coords;
|
||||||
|
|
||||||
|
/*
|
||||||
|
gobject_class->dispose = _vtable.stage_dispose;
|
||||||
|
gobject_class->finalize = _vtable.stage_finalize;
|
||||||
|
*/
|
||||||
|
|
||||||
gobject_class->dispose = clutter_stage_dispose;
|
|
||||||
gobject_class->finalize = clutter_stage_finalize;
|
|
||||||
gobject_class->set_property = clutter_stage_set_property;
|
gobject_class->set_property = clutter_stage_set_property;
|
||||||
gobject_class->get_property = clutter_stage_get_property;
|
gobject_class->get_property = clutter_stage_get_property;
|
||||||
|
|
||||||
@ -867,16 +365,11 @@ clutter_stage_init (ClutterStage *self)
|
|||||||
|
|
||||||
self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self);
|
self->priv = priv = CLUTTER_STAGE_GET_PRIVATE (self);
|
||||||
|
|
||||||
|
self->backend = clutter_stage_backend_init (self);
|
||||||
|
|
||||||
priv->want_offscreen = FALSE;
|
priv->want_offscreen = FALSE;
|
||||||
priv->want_fullscreen = FALSE;
|
priv->want_fullscreen = FALSE;
|
||||||
priv->hide_cursor = FALSE;
|
priv->hide_cursor = FALSE;
|
||||||
priv->is_foreign_xwin = FALSE;
|
|
||||||
|
|
||||||
priv->xwin = None;
|
|
||||||
priv->gl_context = None;
|
|
||||||
|
|
||||||
priv->xwin_width = 100;
|
|
||||||
priv->xwin_height = 100;
|
|
||||||
|
|
||||||
priv->color.red = 0xff;
|
priv->color.red = 0xff;
|
||||||
priv->color.green = 0xff;
|
priv->color.green = 0xff;
|
||||||
@ -928,98 +421,6 @@ clutter_stage_get_default (void)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_stage_get_xwindow
|
|
||||||
* @stage: A #ClutterStage
|
|
||||||
*
|
|
||||||
* Get the stage's underlying x window ID.
|
|
||||||
*
|
|
||||||
* Return Value: Stage X Window XID
|
|
||||||
**/
|
|
||||||
Window
|
|
||||||
clutter_stage_get_xwindow (ClutterStage *stage)
|
|
||||||
{
|
|
||||||
return stage->priv->xwin;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_stage_set_xwindow_foreign
|
|
||||||
* @stage: A #ClutterStage
|
|
||||||
* @xid: A preexisting X Window ID
|
|
||||||
*
|
|
||||||
* Target the #ClutterStage to use an existing external X Window.
|
|
||||||
*
|
|
||||||
* Return value: TRUE if foreign window valid, FALSE otherwise
|
|
||||||
**/
|
|
||||||
gboolean
|
|
||||||
clutter_stage_set_xwindow_foreign (ClutterStage *stage,
|
|
||||||
Window xid)
|
|
||||||
{
|
|
||||||
/* For screensavers via XSCREENSAVER_WINDOW env var.
|
|
||||||
* Also for toolkit binding.
|
|
||||||
*/
|
|
||||||
gint x,y;
|
|
||||||
guint width, height, border, depth;
|
|
||||||
Window root_return;
|
|
||||||
Status status;
|
|
||||||
ClutterGeometry geom;
|
|
||||||
ClutterStagePrivate *priv;
|
|
||||||
|
|
||||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
|
|
||||||
g_return_val_if_fail (xid != None, FALSE);
|
|
||||||
|
|
||||||
priv = stage->priv;
|
|
||||||
|
|
||||||
clutter_util_trap_x_errors();
|
|
||||||
|
|
||||||
status = XGetGeometry (clutter_xdisplay(),
|
|
||||||
xid,
|
|
||||||
&root_return,
|
|
||||||
&x,
|
|
||||||
&y,
|
|
||||||
&width,
|
|
||||||
&height,
|
|
||||||
&border,
|
|
||||||
&depth);
|
|
||||||
|
|
||||||
if (clutter_util_untrap_x_errors() || !status ||
|
|
||||||
width == 0 || height == 0 ||
|
|
||||||
depth != priv->xvisinfo->depth)
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage));
|
|
||||||
|
|
||||||
priv->xwin = xid;
|
|
||||||
priv->is_foreign_xwin = TRUE;
|
|
||||||
|
|
||||||
geom.x = x;
|
|
||||||
geom.y = y;
|
|
||||||
geom.width = priv->xwin_width = width;
|
|
||||||
geom.height = priv->xwin_height = height;
|
|
||||||
|
|
||||||
clutter_actor_set_geometry (CLUTTER_ACTOR (stage), &geom);
|
|
||||||
|
|
||||||
clutter_actor_realize (CLUTTER_ACTOR (stage));
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_stage_get_xvisual
|
|
||||||
* @stage: A #ClutterStage
|
|
||||||
*
|
|
||||||
* Get the stage's XVisualInfo.
|
|
||||||
*
|
|
||||||
* Return Value: The stage's XVisualInfo
|
|
||||||
**/
|
|
||||||
const XVisualInfo*
|
|
||||||
clutter_stage_get_xvisual (ClutterStage *stage)
|
|
||||||
{
|
|
||||||
return stage->priv->xvisinfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_stage_set_color
|
* clutter_stage_set_color
|
||||||
* @stage: A #ClutterStage
|
* @stage: A #ClutterStage
|
||||||
@ -1072,12 +473,14 @@ clutter_stage_get_color (ClutterStage *stage,
|
|||||||
color->alpha = priv->color.alpha;
|
color->alpha = priv->color.alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static void
|
static void
|
||||||
snapshot_pixbuf_free (guchar *pixels,
|
snapshot_pixbuf_free (guchar *pixels,
|
||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
g_free(pixels);
|
g_free(pixels);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_stage_snapshot
|
* clutter_stage_snapshot
|
||||||
@ -1100,6 +503,7 @@ clutter_stage_snapshot (ClutterStage *stage,
|
|||||||
gint width,
|
gint width,
|
||||||
gint height)
|
gint height)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
guchar *data;
|
guchar *data;
|
||||||
GdkPixbuf *pixb, *fpixb;
|
GdkPixbuf *pixb, *fpixb;
|
||||||
ClutterActor *actor;
|
ClutterActor *actor;
|
||||||
@ -1158,8 +562,56 @@ clutter_stage_snapshot (ClutterStage *stage,
|
|||||||
|
|
||||||
return fpixb;
|
return fpixb;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME -> CGL */
|
||||||
|
static void
|
||||||
|
frustum (GLfloat left,
|
||||||
|
GLfloat right,
|
||||||
|
GLfloat bottom,
|
||||||
|
GLfloat top,
|
||||||
|
GLfloat nearval,
|
||||||
|
GLfloat farval)
|
||||||
|
{
|
||||||
|
GLfloat x, y, a, b, c, d;
|
||||||
|
GLfloat m[16];
|
||||||
|
|
||||||
|
x = (2.0 * nearval) / (right - left);
|
||||||
|
y = (2.0 * nearval) / (top - bottom);
|
||||||
|
a = (right + left) / (right - left);
|
||||||
|
b = (top + bottom) / (top - bottom);
|
||||||
|
c = -(farval + nearval) / ( farval - nearval);
|
||||||
|
d = -(2.0 * farval * nearval) / (farval - nearval);
|
||||||
|
|
||||||
|
#define M(row,col) m[col*4+row]
|
||||||
|
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
|
||||||
|
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
|
||||||
|
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
|
||||||
|
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
|
||||||
|
#undef M
|
||||||
|
|
||||||
|
glMultMatrixf (m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
perspective (GLfloat fovy,
|
||||||
|
GLfloat aspect,
|
||||||
|
GLfloat zNear,
|
||||||
|
GLfloat zFar)
|
||||||
|
{
|
||||||
|
GLfloat xmin, xmax, ymin, ymax;
|
||||||
|
|
||||||
|
ymax = zNear * tan (fovy * M_PI / 360.0);
|
||||||
|
ymin = -ymax;
|
||||||
|
xmin = ymin * aspect;
|
||||||
|
xmax = ymax * aspect;
|
||||||
|
|
||||||
|
frustum (xmin, xmax, ymin, ymax, zNear, zFar);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_stage_get_actor_at_pos:
|
* clutter_stage_get_actor_at_pos:
|
||||||
* @stage: a #ClutterStage
|
* @stage: a #ClutterStage
|
||||||
@ -1220,7 +672,7 @@ clutter_stage_get_actor_at_pos (ClutterStage *stage,
|
|||||||
buff[(hits-1) * 4 + 3]);
|
buff[(hits-1) * 4 + 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_gl_viewport (stage);
|
_vtable.sync_viewport (stage);
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
@ -34,10 +34,6 @@
|
|||||||
|
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/Xatom.h>
|
|
||||||
#include <GL/glx.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define CLUTTER_TYPE_STAGE (clutter_stage_get_type())
|
#define CLUTTER_TYPE_STAGE (clutter_stage_get_type())
|
||||||
@ -72,10 +68,14 @@ G_BEGIN_DECLS
|
|||||||
typedef struct _ClutterStagePrivate ClutterStagePrivate;
|
typedef struct _ClutterStagePrivate ClutterStagePrivate;
|
||||||
typedef struct _ClutterStage ClutterStage;
|
typedef struct _ClutterStage ClutterStage;
|
||||||
typedef struct _ClutterStageClass ClutterStageClass;
|
typedef struct _ClutterStageClass ClutterStageClass;
|
||||||
|
typedef struct _ClutterStageBackend ClutterStageBackend;
|
||||||
|
typedef struct _ClutterStageVTable ClutterStageVTable;
|
||||||
|
|
||||||
|
|
||||||
struct _ClutterStage
|
struct _ClutterStage
|
||||||
{
|
{
|
||||||
ClutterGroup parent;
|
ClutterGroup parent;
|
||||||
|
ClutterStageBackend *backend;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
ClutterStagePrivate *priv;
|
ClutterStagePrivate *priv;
|
||||||
@ -107,11 +107,27 @@ struct _ClutterStageClass
|
|||||||
void (*_clutter_stage6) (void);
|
void (*_clutter_stage6) (void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct _ClutterStageVTable
|
||||||
|
{
|
||||||
|
void (* show) (ClutterActor *actor);
|
||||||
|
void (* hide) (ClutterActor *actor);
|
||||||
|
void (* realize) (ClutterActor *actor);
|
||||||
|
void (* unrealize) (ClutterActor *actor);
|
||||||
|
void (* paint) (ClutterActor *actor);
|
||||||
|
void (* request_coords) (ClutterActor *actor,
|
||||||
|
ClutterActorBox *box);
|
||||||
|
void (* allocate_coords) (ClutterActor *actor,
|
||||||
|
ClutterActorBox *box);
|
||||||
|
|
||||||
|
void (* sync_fullscreen) (ClutterStage *stage);
|
||||||
|
void (* sync_cursor) (ClutterStage *stage);
|
||||||
|
void (* sync_viewport) (ClutterStage *stage);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
GType clutter_stage_get_type (void) G_GNUC_CONST;
|
GType clutter_stage_get_type (void) G_GNUC_CONST;
|
||||||
ClutterActor *clutter_stage_get_default (void);
|
ClutterActor *clutter_stage_get_default (void);
|
||||||
Window clutter_stage_get_xwindow (ClutterStage *stage);
|
|
||||||
gboolean clutter_stage_set_xwindow_foreign (ClutterStage *stage,
|
|
||||||
Window xid);
|
|
||||||
void clutter_stage_set_color (ClutterStage *stage,
|
void clutter_stage_set_color (ClutterStage *stage,
|
||||||
const ClutterColor *color);
|
const ClutterColor *color);
|
||||||
void clutter_stage_get_color (ClutterStage *stage,
|
void clutter_stage_get_color (ClutterStage *stage,
|
||||||
@ -124,7 +140,6 @@ GdkPixbuf * clutter_stage_snapshot (ClutterStage *stage,
|
|||||||
gint y,
|
gint y,
|
||||||
gint width,
|
gint width,
|
||||||
gint height);
|
gint height);
|
||||||
const XVisualInfo * clutter_stage_get_xvisual (ClutterStage *stage);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -34,43 +34,6 @@
|
|||||||
#include "clutter-util.h"
|
#include "clutter-util.h"
|
||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
|
|
||||||
static int TrappedErrorCode = 0;
|
|
||||||
static int (*old_error_handler) (Display *, XErrorEvent *);
|
|
||||||
|
|
||||||
static int
|
|
||||||
error_handler(Display *xdpy,
|
|
||||||
XErrorEvent *error)
|
|
||||||
{
|
|
||||||
TrappedErrorCode = error->error_code;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_util_trap_x_errors:
|
|
||||||
*
|
|
||||||
* Trap X errors so they don't cause an abort.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_util_trap_x_errors(void)
|
|
||||||
{
|
|
||||||
TrappedErrorCode = 0;
|
|
||||||
old_error_handler = XSetErrorHandler(error_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_util_untrap_x_errors:
|
|
||||||
*
|
|
||||||
* Stop trapping X errors.
|
|
||||||
*
|
|
||||||
* Return value: 0 if there was no error, or the last X error that occurred.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
clutter_util_untrap_x_errors(void)
|
|
||||||
{
|
|
||||||
XSetErrorHandler(old_error_handler);
|
|
||||||
return TrappedErrorCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_util_next_p2:
|
* clutter_util_next_p2:
|
||||||
* @a: Value to get the next power
|
* @a: Value to get the next power
|
||||||
|
@ -30,12 +30,6 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void
|
|
||||||
clutter_util_trap_x_errors(void);
|
|
||||||
|
|
||||||
int
|
|
||||||
clutter_util_untrap_x_errors(void);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
clutter_util_next_p2 (int a);
|
clutter_util_next_p2 (int a);
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <GL/gl.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "pangoclutter.h"
|
#include "pangoclutter.h"
|
||||||
@ -553,14 +554,15 @@ draw_begin (PangoRenderer *renderer_)
|
|||||||
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||||
glEnable (GL_BLEND);
|
glEnable (GL_BLEND);
|
||||||
#if 0
|
#if 0
|
||||||
|
/* How to handle in ES ? */
|
||||||
gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
gl_BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
||||||
GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
|
GL_ONE , GL_ONE_MINUS_SRC_ALPHA);
|
||||||
#endif
|
#endif
|
||||||
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
#if 0
|
|
||||||
glEnable (GL_ALPHA_TEST);
|
glEnable (GL_ALPHA_TEST);
|
||||||
glAlphaFunc (GL_GREATER, 0.01f);
|
glAlphaFunc (GL_GREATER, 0.01f);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -97,6 +97,9 @@ fi
|
|||||||
|
|
||||||
GLX_CFLAGS="$X11_CFLAGS"
|
GLX_CFLAGS="$X11_CFLAGS"
|
||||||
|
|
||||||
|
CLUTTER_FLAVOUR="glx"
|
||||||
|
AC_SUBST(CLUTTER_FLAVOUR)
|
||||||
|
|
||||||
dnl ========================================================================
|
dnl ========================================================================
|
||||||
|
|
||||||
pkg_modules="pangoft2 glib-2.0 >= 2.8 gthread-2.0 gdk-pixbuf-2.0 gdk-pixbuf-xlib-2.0"
|
pkg_modules="pangoft2 glib-2.0 >= 2.8 gthread-2.0 gdk-pixbuf-2.0 gdk-pixbuf-xlib-2.0"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
noinst_PROGRAMS = test super-oh behave
|
noinst_PROGRAMS = test super-oh behave
|
||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/
|
INCLUDES = -I$(top_srcdir)/
|
||||||
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_MAJORMINOR@.la
|
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
||||||
|
|
||||||
test_SOURCES = test.c
|
test_SOURCES = test.c
|
||||||
test_CFLAGS = $(CLUTTER_CFLAGS) $(GCONF_CFLAGS)
|
test_CFLAGS = $(CLUTTER_CFLAGS) $(GCONF_CFLAGS)
|
||||||
|
Loading…
Reference in New Issue
Block a user