Moves all GLX code down from Clutter to Cogl

This migrates all the GLX window system code down from the Clutter
backend code into a Cogl winsys. Moving OpenGL window system binding
code down from Clutter into Cogl is the biggest blocker to having Cogl
become a standalone 3D graphics library, so this is an important step in
that direction.
This commit is contained in:
Robert Bragg 2010-11-05 12:28:33 +00:00
parent aa1a2cb661
commit d6f110a4d2
54 changed files with 3443 additions and 1638 deletions

View File

@ -37,6 +37,11 @@ struct _ClutterBackend
{
/*< private >*/
GObject parent_instance;
CoglRenderer *cogl_renderer;
CoglDisplay *cogl_display;
CoglContext *cogl_context;
ClutterBackendPrivate *priv;
};

View File

@ -53,6 +53,7 @@
#include "clutter-version.h"
#include <cogl/cogl.h>
#include <cogl/cogl-internal.h>
G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT);

View File

@ -672,7 +672,6 @@ clutter_stage_realize (ClutterActor *self)
if (is_realized)
{
ClutterBackend *backend = clutter_get_default_backend ();
GError *error = NULL;
/* We want to select the context without calling
clutter_backend_ensure_context so that it doesn't call any
@ -680,17 +679,6 @@ clutter_stage_realize (ClutterActor *self)
before we get a chance to check whether the GL version is
valid */
_clutter_backend_ensure_context_internal (backend, CLUTTER_STAGE (self));
/* Make sure Cogl can support the driver */
if (!_cogl_check_driver_valid (&error))
{
g_critical ("The GL driver is not supported: %s",
error->message);
g_clear_error (&error);
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
}
else
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
}
else
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);

View File

@ -78,6 +78,7 @@ cogl_public_h = \
$(srcdir)/cogl-attribute.h \
$(srcdir)/cogl-primitive.h \
$(srcdir)/cogl-clip-state.h \
$(srcdir)/cogl-framebuffer.h \
$(srcdir)/cogl-clutter.h \
$(srcdir)/cogl.h \
$(NULL)
@ -114,10 +115,8 @@ endif # COGL_DRIVER_GLES
# winsys sources, common to all backends
cogl_winsys_common_sources = \
$(srcdir)/winsys/cogl-winsys-private.h \
$(srcdir)/winsys/cogl-context-winsys.h \
$(srcdir)/winsys/cogl-context-winsys.c \
$(srcdir)/winsys/cogl-winsys-feature-functions.h \
$(srcdir)/winsys/cogl-winsys-private.h \
$(srcdir)/winsys/cogl-winsys.c \
$(NULL)
# tesselator sources
@ -295,29 +294,39 @@ cogl_sources_c = \
if SUPPORT_XLIB
cogl_experimental_h += \
$(srcdir)/winsys/cogl-texture-pixmap-x11.h
$(srcdir)/winsys/cogl-texture-pixmap-x11.h \
$(srcdir)/cogl-xlib.h
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-xlib.h \
$(srcdir)/winsys/cogl-winsys-xlib.c \
$(srcdir)/winsys/cogl-texture-pixmap-x11.c \
$(srcdir)/winsys/cogl-texture-pixmap-x11-private.h
$(srcdir)/cogl-renderer-x11-private.h \
$(srcdir)/cogl-renderer-xlib-private.h \
$(srcdir)/cogl-renderer-xlib.c \
$(srcdir)/cogl-display-xlib-private.h \
$(srcdir)/cogl-xlib.c \
$(srcdir)/winsys/cogl-texture-pixmap-x11.c \
$(srcdir)/winsys/cogl-texture-pixmap-x11-private.h
endif
if SUPPORT_GLX
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-glx.c
$(srcdir)/cogl-renderer-glx-private.h \
$(srcdir)/cogl-display-glx-private.h \
$(srcdir)/winsys/cogl-winsys-glx-feature-functions.h \
$(srcdir)/winsys/cogl-winsys-glx.c
endif
if SUPPORT_EGL_PLATFORM_POWERVR_X11
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-egl.c
$(srcdir)/winsys/cogl-winsys-egl.c \
$(srcdir)/winsys/cogl-winsys-stub.c
endif
if SUPPORT_EGL_PLATFORM_POWERVR_NULL
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-egl.c
$(srcdir)/winsys/cogl-winsys-egl.c \
$(srcdir)/winsys/cogl-winsys-stub.c
endif
if SUPPORT_EGL_PLATFORM_POWERVR_GDL
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-egl.c
$(srcdir)/winsys/cogl-winsys-egl.c \
$(srcdir)/winsys/cogl-winsys-stub.c
endif
if SUPPORT_EGL_PLATFORM_FRUITY
cogl_sources_c += \
@ -325,15 +334,18 @@ cogl_sources_c += \
endif
if SUPPORT_EGL_PLATFORM_DRM_SURFACELESS
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-egl.c
$(srcdir)/winsys/cogl-winsys-egl.c \
$(srcdir)/winsys/cogl-winsys-stub.c
endif
if SUPPORT_WIN32
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-win32.c
$(srcdir)/winsys/cogl-winsys-win32.c \
$(srcdir)/winsys/cogl-winsys-stub.c
endif
if SUPPORT_OSX
cogl_sources_c += \
$(srcdir)/winsys/cogl-winsys-osx.c
$(srcdir)/winsys/cogl-winsys-osx.c \
$(srcdir)/winsys/cogl-winsys-stub.c
endif
EXTRA_DIST += stb_image.c

View File

@ -43,6 +43,12 @@ cogl_clutter_check_extension (const char *name, const char *ext)
return _cogl_check_extension (name, ext);
}
gboolean
cogl_clutter_winsys_has_feature (CoglWinsysFeature feature)
{
return _cogl_winsys_has_feature (feature);
}
void
cogl_onscreen_clutter_backend_set_size (int width, int height)
{
@ -57,3 +63,11 @@ cogl_onscreen_clutter_backend_set_size (int width, int height)
_cogl_framebuffer_winsys_update_size (framebuffer, width, height);
}
#ifdef COGL_HAS_XLIB_SUPPORT
XVisualInfo *
cogl_clutter_winsys_xlib_get_visual_info (void)
{
return _cogl_winsys_xlib_get_visual_info ();
}
#endif

View File

@ -38,10 +38,20 @@ G_BEGIN_DECLS
gboolean
cogl_clutter_check_extension (const char *name, const char *ext);
#define cogl_clutter_winsys_has_feature cogl_clutter_winsys_has_feature_CLUTTER
gboolean
cogl_clutter_winsys_has_feature (CoglWinsysFeature feature);
#define cogl_onscreen_clutter_backend_set_size cogl_onscreen_clutter_backend_set_size_CLUTTER
void
cogl_onscreen_clutter_backend_set_size (int width, int height);
#ifdef COGL_HAS_XLIB
#define cogl_clutter_winsys_xlib_get_visual_info cogl_clutter_winsys_xlib_get_visual_info_CLUTTER
XVisualInfo *
cogl_clutter_winsys_xlib_get_visual_info (void);
#endif
G_END_DECLS
#endif /* __COGL_CLUTTER_H__ */

View File

@ -26,6 +26,11 @@
#include "cogl-internal.h"
#include "cogl-context.h"
#include "cogl-winsys-private.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include "cogl-xlib-private.h"
#endif
#if HAVE_COGL_GL
#include "cogl-context-driver-gl.h"
@ -35,7 +40,7 @@
#include "cogl-context-driver-gles.h"
#endif
#include "cogl-context-winsys.h"
#include "cogl-display-private.h"
#include "cogl-primitives.h"
#include "cogl-clip-stack.h"
#include "cogl-matrix-stack.h"
@ -55,9 +60,10 @@ struct _CoglContext
{
CoglObject _parent;
CoglDisplay *display;
/* Features cache */
CoglFeatureFlags feature_flags;
CoglFeatureFlagsPrivate feature_flags_private;
CoglFeatureFlags feature_flags;
CoglHandle default_pipeline;
CoglHandle default_layer_0;
@ -70,8 +76,6 @@ struct _CoglContext
gboolean enable_backface_culling;
CoglFrontWinding flushed_front_winding;
gboolean indirect;
/* A few handy matrix constants */
CoglMatrix identity_matrix;
CoglMatrix y_flip_matrix;
@ -237,8 +241,26 @@ struct _CoglContext
GByteArray *buffer_map_fallback_array;
gboolean buffer_map_fallback_in_use;
CoglWinsysRectangleState rectangle_state;
/* FIXME: remove these when we remove the last xlib based clutter
* backend. they should be tracked as part of the renderer but e.g.
* the eglx backend doesn't yet have a corresponding Cogl winsys
* and so we wont have a renderer in that case. */
#ifdef COGL_HAS_XLIB_SUPPORT
int damage_base;
/* List of callback functions that will be given every Xlib event */
GSList *event_filters;
/* Current top of the XError trap state stack. The actual memory for
these is expected to be allocated on the stack by the caller */
CoglXlibTrapState *trap_state;
#endif
CoglContextDriver drv;
CoglContextWinsys winsys;
CoglBitmask winsys_features;
void *winsys;
gboolean stub_winsys;
};
CoglContext *

View File

@ -28,6 +28,8 @@
#include "cogl.h"
#include "cogl-object.h"
#include "cogl-internal.h"
#include "cogl-private.h"
#include "cogl-winsys-private.h"
#include "cogl-profile.h"
#include "cogl-util.h"
#include "cogl-context-private.h"
@ -56,13 +58,8 @@ COGL_OBJECT_DEFINE (Context, context);
extern void
_cogl_create_context_driver (CoglContext *context);
extern void
_cogl_create_context_winsys (CoglContext *context);
extern void
_cogl_destroy_context_winsys (CoglContext *context);
static CoglContext *_context = NULL;
static gboolean gl_is_indirect = FALSE;
static void
_cogl_init_feature_overrides (CoglContext *ctx)
@ -102,15 +99,8 @@ cogl_context_new (CoglDisplay *display,
CoglContext *context;
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
unsigned long enable_flags = 0;
CoglHandle window_buffer;
int i;
/* A NULL display means "please just do something sensible"
* and since we haven't implemented anything for CoglDisplay
* yet that's the only kind of context construction we allow
* for now. */
g_return_val_if_fail (display == NULL, NULL);
#ifdef CLUTTER_ENABLE_PROFILE
/* We need to be absolutely sure that uprof has been initialized
* before calling _cogl_uprof_init. uprof_init (NULL, NULL)
@ -135,18 +125,21 @@ cogl_context_new (CoglDisplay *display,
* context which it can access via _COGL_GET_CONTEXT() including
* code used to construct a CoglContext. Until all of that code
* has been updated to take an explicit context argument we have
* to immediatly make our pointer the default context.
* to immediately make our pointer the default context.
*/
_context = context;
/* Init default values */
_context->feature_flags = 0;
_context->feature_flags_private = 0;
context->feature_flags = 0;
context->texture_types = NULL;
context->buffer_types = NULL;
if (!display)
context->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_UNKNOWN;
_cogl_bitmask_init (&context->winsys_features);
if (!display)
display = cogl_display_new (NULL, NULL);
else
cogl_object_ref (display);
@ -158,11 +151,32 @@ cogl_context_new (CoglDisplay *display,
return NULL;
}
/* Initialise the driver specific state */
_cogl_gl_context_init (context);
_cogl_init_feature_overrides (context);
context->display = display;
_cogl_create_context_winsys (context);
#ifdef COGL_HAS_FULL_WINSYS
if (!_cogl_winsys_context_init (context, error))
{
cogl_object_unref (display);
g_free (context);
return NULL;
}
#else
/* In this case Clutter is still responsible for creating a GL
* context. */
context->stub_winsys = TRUE;
if (!_cogl_gl_check_version (error))
{
g_free (context);
return NULL;
}
_cogl_gl_update_features (context);
#ifdef COGL_HAS_XLIB_SUPPORT
_cogl_xlib_query_damage_extension ();
#endif
#endif
/* Initialise the driver specific state */
_cogl_init_feature_overrides (context);
_cogl_pipeline_init_default_pipeline ();
_cogl_pipeline_init_default_layers ();
@ -174,8 +188,6 @@ cogl_context_new (CoglDisplay *display,
context->enable_backface_culling = FALSE;
context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
context->indirect = gl_is_indirect;
cogl_matrix_init_identity (&context->identity_matrix);
cogl_matrix_init_identity (&context->y_flip_matrix);
cogl_matrix_scale (&context->y_flip_matrix, 1, -1, 1);
@ -257,13 +269,18 @@ cogl_context_new (CoglDisplay *display,
context->framebuffer_stack = _cogl_create_framebuffer_stack ();
_context->current_clip_stack_valid = FALSE;
/* XXX: In this case the Clutter backend is still responsible for
* the OpenGL binding API and for creating onscreen framebuffers and
* so we have to add a dummy framebuffer to represent the backend
* owned window... */
if (context->stub_winsys)
{
CoglOnscreen *window = _cogl_onscreen_new ();
cogl_set_framebuffer (COGL_FRAMEBUFFER (window));
cogl_object_unref (COGL_FRAMEBUFFER (window));
}
window_buffer = _cogl_onscreen_new ();
cogl_set_framebuffer (window_buffer);
/* XXX: the deprecated _cogl_set_draw_buffer API expects to
* find the window buffer here... */
context->window_buffer = window_buffer;
_context->current_clip_stack_valid = FALSE;
context->dirty_bound_framebuffer = TRUE;
context->dirty_gl_viewport = TRUE;
@ -347,7 +364,7 @@ cogl_context_new (CoglDisplay *display,
static void
_cogl_context_free (CoglContext *context)
{
_cogl_destroy_context_winsys (context);
_cogl_winsys_context_deinit (context);
_cogl_destroy_texture_units ();
@ -424,6 +441,8 @@ _cogl_context_free (CoglContext *context)
g_byte_array_free (context->buffer_map_fallback_array, TRUE);
_cogl_bitmask_destroy (&context->winsys_features);
cogl_object_unref (context->display);
g_free (context);
@ -448,31 +467,12 @@ _cogl_context_get_default (void)
return _context;
}
/**
* _cogl_set_indirect_context:
* @indirect: TRUE if GL context is indirect
*
* Advises COGL that the GL context is indirect (commands are sent
* over a socket). COGL uses this information to try to avoid
* round-trips in its use of GL, for example.
*
* This function cannot be called "on the fly," only before COGL
* initializes.
*/
void
_cogl_set_indirect_context (gboolean indirect)
cogl_set_default_context (CoglContext *context)
{
/* we get called multiple times if someone creates
* more than the default stage
*/
if (_context != NULL)
{
if (indirect != _context->indirect)
g_warning ("Right now all stages will be treated as "
"either direct or indirect, ignoring attempt "
"to change to indirect=%d", indirect);
return;
}
cogl_object_ref (context);
gl_is_indirect = indirect;
if (_context)
cogl_object_unref (_context);
_context = context;
}

View File

@ -54,7 +54,12 @@ typedef struct _CoglContext CoglContext;
#define cogl_context_new cogl_context_new_EXP
CoglContext *
cogl_context_new (CoglDisplay *display);
cogl_context_new (CoglDisplay *display,
GError **error);
#define cogl_set_default_context cogl_set_default_context_EXP
void
cogl_set_default_context (CoglContext *context);
G_END_DECLS

View File

@ -63,6 +63,7 @@ typedef enum {
COGL_DEBUG_DISABLE_PROGRAM_CACHES,
COGL_DEBUG_DISABLE_FAST_READ_PIXEL,
COGL_DEBUG_CLIPPING,
COGL_DEBUG_WINSYS,
COGL_DEBUG_N_FLAGS
} CoglDebugFlags;

View File

@ -0,0 +1,57 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* 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, see
* <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_DISPLAY_GLX_PRIVATE_H
#define __COGL_DISPLAY_GLX_PRIVATE_H
#include "cogl-object-private.h"
#include "cogl-display-xlib-private.h"
typedef struct _CoglGLXCachedConfig
{
/* This will be -1 if there is no cached config in this slot */
int depth;
gboolean found;
GLXFBConfig fb_config;
gboolean can_mipmap;
} CoglGLXCachedConfig;
#define COGL_GLX_N_CACHED_CONFIGS 3
typedef struct _CoglDisplayGLX
{
CoglDisplayXlib _parent;
CoglGLXCachedConfig glx_cached_configs[COGL_GLX_N_CACHED_CONFIGS];
gboolean found_fbconfig;
gboolean fbconfig_has_rgba_visual;
GLXFBConfig fbconfig;
/* Single context for all wins */
GLXContext glx_context;
GLXWindow dummy_glxwin;
} CoglDisplayGLX;
#endif /* __COGL_DISPLAY_GLX_PRIVATE_H */

View File

@ -0,0 +1,35 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* 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, see
* <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_DISPLAY_XLIB_PRIVATE_H
#define __COGL_DISPLAY_XLIB_PRIVATE_H
#include <X11/Xlib.h>
typedef struct _CoglDisplayXlib
{
Window dummy_xwin;
} CoglDisplayXlib;
#endif /* __COGL_DISPLAY_XLIB_PRIVATE_H */

View File

@ -100,6 +100,11 @@ cogl_display_setup (CoglDisplay *display,
if (display->setup)
return TRUE;
#ifdef COGL_HAS_FULL_WINSYS
if (!_cogl_winsys_display_setup (display, error))
return FALSE;
#endif
display->setup = TRUE;
return TRUE;

View File

@ -31,6 +31,9 @@
#ifndef __COGL_DISPLAY_H__
#define __COGL_DISPLAY_H__
#include <cogl/cogl-renderer.h>
#include <cogl/cogl-onscreen-template.h>
G_BEGIN_DECLS
/**
@ -69,8 +72,15 @@ typedef struct _CoglDisplay CoglDisplay;
#define COGL_DISPLAY(OBJECT) ((CoglDisplay *)OBJECT)
#define cogl_display_new cogl_display_new_EXP
CoglDisplay *
cogl_display_new (CoglDisplay *display);
cogl_display_new (CoglRenderer *renderer,
CoglOnscreenTemplate *onscreen_template);
#define cogl_display_setup cogl_display_setup_EXP
gboolean
cogl_display_setup (CoglDisplay *display,
GError **error);
G_END_DECLS

View File

@ -37,7 +37,8 @@ _cogl_feature_check (const char *driver_prefix,
const CoglFeatureData *data,
unsigned int gl_major,
unsigned int gl_minor,
const char *extensions_string)
const char *extensions_string,
void *function_table)
{
const char *suffix = NULL;
@ -123,7 +124,7 @@ _cogl_feature_check (const char *driver_prefix,
break;
/* Set the function pointer in the context */
*(void **) ((guint8 *) ctx +
*(void **) ((guint8 *) function_table +
data->functions[func_num].pointer_offset) = func;
}

View File

@ -26,6 +26,8 @@
#include <glib.h>
#include "cogl-internal.h"
#define COGL_CHECK_GL_VERSION(driver_major, driver_minor, \
target_major, target_minor) \
((driver_major) > (target_major) || \
@ -59,17 +61,21 @@ struct _CoglFeatureData
const char *extension_names;
/* A set of feature flags to enable if the extension is available */
CoglFeatureFlags feature_flags;
/* A set of private feature flags to enable if the extension is available
* and for internal use only */
CoglFeatureFlagsPrivate feature_flags_private;
/* FIXME: This is now unused */
int padding_feature_flags_private;
/* An optional corresponding winsys feature. */
CoglWinsysFeature winsys_feature;
/* A list of functions required for this feature. Terminated with a
NULL name */
const CoglFeatureFunction *functions;
};
gboolean _cogl_feature_check (const char *driver_prefix,
const CoglFeatureData *data,
unsigned int gl_major, unsigned int gl_minor,
const char *extensions_string);
gboolean
_cogl_feature_check (const char *driver_prefix,
const CoglFeatureData *data,
unsigned int gl_major,
unsigned int gl_minor,
const char *extensions_string,
void *function_table);
#endif /* __COGL_FEATURE_PRIVATE_H */

View File

@ -24,11 +24,20 @@
#ifndef __COGL_FRAMEBUFFER_PRIVATE_H
#define __COGL_FRAMEBUFFER_PRIVATE_H
#include "cogl-handle.h"
#include "cogl-object-private.h"
#include "cogl-matrix-stack.h"
#include "cogl-clip-state-private.h"
#include "cogl-journal-private.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xlib.h>
#endif
#ifdef COGL_HAS_GLX_SUPPORT
#include <GL/glx.h>
#include <GL/glxext.h>
#endif
typedef enum _CoglFramebufferType {
COGL_FRAMEBUFFER_TYPE_ONSCREEN,
COGL_FRAMEBUFFER_TYPE_OFFSCREEN
@ -37,12 +46,14 @@ typedef enum _CoglFramebufferType {
struct _CoglFramebuffer
{
CoglObject _parent;
CoglContext *context;
CoglFramebufferType type;
int width;
int height;
/* Format of the pixels in the framebuffer (including the expected
premult state) */
CoglPixelFormat format;
gboolean allocated;
CoglMatrixStack *modelview_stack;
CoglMatrixStack *projection_stack;
@ -85,8 +96,6 @@ struct _CoglFramebuffer
gboolean clear_clip_dirty;
};
#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X))
typedef struct _CoglOffscreen
{
CoglFramebuffer _parent;
@ -103,12 +112,18 @@ typedef enum
#define COGL_OFFSCREEN(X) ((CoglOffscreen *)(X))
typedef struct _CoglOnscreen
struct _CoglOnscreen
{
CoglFramebuffer _parent;
} CoglOnscreen;
#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
#ifdef COGL_HAS_X11_SUPPORT
guint32 foreign_xid;
#endif
gboolean swap_throttled;
void *winsys;
};
void
_cogl_framebuffer_state_init (void);
@ -233,7 +248,11 @@ typedef enum _CoglFramebufferFlushFlags
COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW = 1L<<0,
/* Similarly this flag implies you are going to flush the clip state
yourself */
COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE = 1L<<1
COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE = 1L<<1,
/* When using this all that will be updated is the glBindFramebuffer
* state and corresponding winsys state to make the framebuffer
* current if it is a CoglOnscreen framebuffer. */
COGL_FRAMEBUFFER_FLUSH_BIND_ONLY = 1L<<2
} CoglFramebufferFlushFlags;
void
@ -241,9 +260,6 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
CoglFramebuffer *read_buffer,
CoglFramebufferFlushFlags flags);
CoglHandle
_cogl_onscreen_new (void);
CoglFramebuffer *
_cogl_get_read_framebuffer (void);
@ -339,5 +355,8 @@ _cogl_blit_framebuffer (unsigned int src_x,
unsigned int width,
unsigned int height);
CoglOnscreen *
_cogl_onscreen_new (void);
#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */

View File

@ -36,6 +36,7 @@
#include "cogl-framebuffer-private.h"
#include "cogl-clip-stack.h"
#include "cogl-journal-private.h"
#include "cogl-winsys-private.h"
#ifndef HAVE_COGL_GLES2
@ -291,6 +292,8 @@ _cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
int scissor_x1;
int scissor_y1;
g_return_if_fail (framebuffer->allocated);
_cogl_clip_stack_get_bounds (clip_stack,
&scissor_x0, &scissor_y0,
&scissor_x1, &scissor_y1);
@ -451,6 +454,8 @@ _cogl_framebuffer_clear (CoglFramebuffer *framebuffer,
unsigned long buffers,
const CoglColor *color)
{
g_return_if_fail (framebuffer->allocated);
_cogl_framebuffer_clear4f (framebuffer, buffers,
cogl_color_get_red_float (color),
cogl_color_get_green_float (color),
@ -811,8 +816,6 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
CoglFramebufferTryFBOData data;
gboolean fbo_created;
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
return COGL_INVALID_HANDLE;
@ -887,8 +890,11 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
if (fbo_created)
{
CoglOffscreen *ret;
CoglFramebuffer *fb = COGL_FRAMEBUFFER (offscreen);
_cogl_framebuffer_init (COGL_FRAMEBUFFER (offscreen),
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
_cogl_framebuffer_init (fb,
ctx,
COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
cogl_texture_get_format (texhandle),
@ -901,6 +907,8 @@ _cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
ret = _cogl_offscreen_object_new (offscreen);
_cogl_texture_associate_framebuffer (texhandle, COGL_FRAMEBUFFER (ret));
fb->allocated = TRUE;
return ret;
}
else
@ -946,16 +954,34 @@ _cogl_offscreen_free (CoglOffscreen *offscreen)
g_free (offscreen);
}
CoglHandle
/* XXX: While we still have backend in Clutter we need a dummy object
* to represent the CoglOnscreen framebuffer that the backend
* creates... */
CoglOnscreen *
_cogl_onscreen_new (void)
{
CoglOnscreen *onscreen;
CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1);
_COGL_GET_CONTEXT (ctx, NULL);
/* XXX: Until we have full winsys support in Cogl then we can't fully
* implement CoglOnscreen framebuffers, since we can't, e.g. keep track of
* the window size. */
_cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen),
ctx,
COGL_FRAMEBUFFER_TYPE_ONSCREEN,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
0xdeadbeef, /* width */
0xdeadbeef); /* height */
COGL_FRAMEBUFFER (onscreen)->allocated = TRUE;
/* XXX: Note we don't initialize onscreen->winsys in this case. */
return _cogl_onscreen_object_new (onscreen);
}
CoglOnscreen *
cogl_onscreen_new (CoglContext *ctx, int width, int height)
{
CoglOnscreen *onscreen;
/* FIXME: We are assuming onscreen buffers will always be
premultiplied so we'll set the premult flag on the bitmap
@ -973,15 +999,41 @@ _cogl_onscreen_new (void)
ctx,
COGL_FRAMEBUFFER_TYPE_ONSCREEN,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
0xdeadbeef, /* width */
0xdeadbeef); /* height */
width, /* width */
height); /* height */
onscreen->swap_throttled = TRUE;
return _cogl_onscreen_object_new (onscreen);
}
gboolean
cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
GError **error)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
if (framebuffer->allocated)
return TRUE;
/* XXX: with the current cogl_offscreen_new_to_texture() API the
* framebuffer is implicitly allocated before returning. */
g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN,
TRUE);
if (!_cogl_winsys_onscreen_init (onscreen, error))
return FALSE;
framebuffer->allocated = TRUE;
return TRUE;
}
static void
_cogl_onscreen_free (CoglOnscreen *onscreen)
{
_cogl_winsys_onscreen_deinit (onscreen);
/* Chain up to parent */
_cogl_framebuffer_free (COGL_FRAMEBUFFER (onscreen));
@ -1059,11 +1111,14 @@ static void
_cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer,
CoglFramebuffer *read_buffer)
{
CoglContext *ctx = draw_buffer->context;
CoglFramebufferStackEntry *entry;
GSList *l;
g_return_if_fail (context != NULL);
g_return_if_fail (draw_buffer->context == read_buffer->context);
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
g_return_if_fail (ctx != NULL);
g_return_if_fail (draw_buffer && read_buffer ?
draw_buffer->context == read_buffer->context : TRUE);
entry = ctx->framebuffer_stack->data;
@ -1087,9 +1142,26 @@ _cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer,
* projection matrix stacks and clip state so we need to dirty
* them to ensure they get flushed for the next batch of geometry
* we flush */
_cogl_matrix_stack_dirty (draw_buffer->modelview_stack);
_cogl_matrix_stack_dirty (draw_buffer->projection_stack);
if (draw_buffer)
{
_cogl_matrix_stack_dirty (draw_buffer->modelview_stack);
_cogl_matrix_stack_dirty (draw_buffer->projection_stack);
}
_cogl_clip_stack_dirty ();
/* XXX:
* To support the deprecated cogl_set_draw_buffer API we keep track
* of the last onscreen framebuffer that was pushed so that it can
* be restored if the COGL_WINDOW_BUFFER enum is used. */
ctx->window_buffer = NULL;
for (l = ctx->framebuffer_stack; l; l = l->next)
{
entry = l->data;
if (entry->draw_buffer &&
entry->draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
ctx->window_buffer = entry->draw_buffer;
}
}
static void
@ -1182,15 +1254,19 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
g_return_if_fail (_cogl_is_framebuffer (read_buffer));
ctx = draw_buffer->context;
g_return_if_fail (context != NULL);
g_return_if_fail (ctx != NULL);
g_return_if_fail (draw_buffer->context == read_buffer->context);
g_return_if_fail (context->framebuffer_stack != NULL);
g_return_if_fail (ctx->framebuffer_stack != NULL);
/* Copy the top of the stack so that when we call cogl_set_framebuffer
it will still know what the old framebuffer was */
old_draw_buffer = cogl_object_ref (cogl_get_draw_framebuffer ());
old_read_buffer = cogl_object_ref (_cogl_get_read_framebuffer ());
old_draw_buffer = cogl_get_draw_framebuffer ();
if (old_draw_buffer)
cogl_object_ref (old_draw_buffer);
old_read_buffer = _cogl_get_read_framebuffer ();
if (old_read_buffer)
cogl_object_ref (old_read_buffer);
ctx->framebuffer_stack =
g_slist_prepend (ctx->framebuffer_stack,
create_stack_entry (old_draw_buffer,
@ -1264,15 +1340,20 @@ cogl_pop_draw_buffer (void)
}
static void
bind_gl_framebuffer (GLenum target, CoglFramebuffer *framebuffer)
bind_gl_framebuffer (CoglContext *ctx,
GLenum target,
CoglFramebuffer *framebuffer)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
GE (glBindFramebuffer (target,
COGL_OFFSCREEN (framebuffer)->fbo_handle));
else
GE (glBindFramebuffer (target, 0));
{
#ifdef COGL_HAS_FULL_WINSYS
_cogl_winsys_onscreen_bind (COGL_ONSCREEN (framebuffer));
#endif
GE (glBindFramebuffer (target, 0));
}
}
void
@ -1282,21 +1363,29 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
{
CoglContext *ctx = draw_buffer->context;
if (cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
ctx->dirty_bound_framebuffer)
if (ctx->dirty_bound_framebuffer)
{
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT) ||
draw_buffer == read_buffer)
bind_gl_framebuffer (GL_FRAMEBUFFER, draw_buffer);
if (draw_buffer == read_buffer)
bind_gl_framebuffer (ctx, GL_FRAMEBUFFER, draw_buffer);
else
{
bind_gl_framebuffer (GL_DRAW_FRAMEBUFFER, draw_buffer);
bind_gl_framebuffer (GL_READ_FRAMEBUFFER, read_buffer);
}
/* NB: Currently we only take advantage of binding separate
* read/write buffers for offscreen framebuffer blit
* purposes. */
g_return_if_fail (cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT));
g_return_if_fail (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
g_return_if_fail (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
ctx->dirty_bound_framebuffer = FALSE;
bind_gl_framebuffer (ctx, GL_DRAW_FRAMEBUFFER, draw_buffer);
bind_gl_framebuffer (ctx, GL_READ_FRAMEBUFFER, read_buffer);
}
}
ctx->dirty_bound_framebuffer = FALSE;
if (flags & COGL_FRAMEBUFFER_FLUSH_BIND_ONLY)
return;
if (ctx->dirty_gl_viewport)
{
float gl_viewport_y;
@ -1452,6 +1541,8 @@ _cogl_blit_framebuffer (unsigned int src_x,
CoglFramebuffer *read_buffer;
CoglContext *ctx;
/* FIXME: this function should take explit src and dst framebuffer
* arguments. */
draw_buffer = cogl_get_draw_framebuffer ();
read_buffer = _cogl_get_read_framebuffer ();
ctx = draw_buffer->context;
@ -1484,3 +1575,83 @@ _cogl_blit_framebuffer (unsigned int src_x,
GL_COLOR_BUFFER_BIT,
GL_NEAREST);
}
void
cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer)
{
/* FIXME: we shouldn't need to flush *all* journals here! */
cogl_flush ();
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
_cogl_winsys_onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
}
void
cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
int *rectangles,
int n_rectangles)
{
/* FIXME: we shouldn't need to flush *all* journals here! */
cogl_flush ();
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
_cogl_winsys_onscreen_swap_region (COGL_ONSCREEN (framebuffer),
rectangles,
n_rectangles);
}
#ifdef COGL_HAS_X11_SUPPORT
void
cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
guint32 xid)
{
onscreen->foreign_xid = xid;
}
guint32
cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
{
return _cogl_winsys_onscreen_x11_get_window_xid (onscreen);
}
guint32
cogl_onscreen_x11_get_visual_xid (CoglOnscreen *onscreen)
{
guint32 id;
XVisualInfo *visinfo = _cogl_winsys_xlib_get_visual_info ();
id = (guint32)visinfo->visualid;
XFree (visinfo);
return id;
}
#endif /* COGL_HAS_X11_SUPPORT */
unsigned int
cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
CoglSwapBuffersNotify callback,
void *user_data)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
/* Should this just be cogl_onscreen API instead? */
g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN, 0);
return _cogl_winsys_onscreen_add_swap_buffers_callback (onscreen,
callback,
user_data);
}
void
cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
unsigned int id)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
_cogl_winsys_onscreen_remove_swap_buffers_callback (onscreen, id);
}
void
cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
gboolean throttled)
{
onscreen->swap_throttled = throttled;
if (COGL_FRAMEBUFFER (onscreen)->allocated)
_cogl_winsys_onscreen_update_swap_throttled (onscreen);
}

View File

@ -0,0 +1,109 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* 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, see
* <http://www.gnu.org/licenses/>.
*
*
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
*/
#ifndef __COGL_FRAMEBUFFER_H
#define __COGL_FRAMEBUFFER_H
#include <glib.h>
G_BEGIN_DECLS
#ifdef COGL_ENABLE_EXPERIMENTAL_API
#define cogl_onscreen_new cogl_onscreen_new_EXP
#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X))
#define cogl_framebuffer_allocate cogl_framebuffer_allocate_EXP
gboolean
cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
GError **error);
#define cogl_framebuffer_swap_buffers cogl_framebuffer_swap_buffers_EXP
void
cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer);
#define cogl_framebuffer_swap_region cogl_framebuffer_swap_region_EXP
void
cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
int *rectangles,
int n_rectangles);
typedef void (*CoglSwapBuffersNotify) (CoglFramebuffer *framebuffer,
void *user_data);
#define cogl_framebuffer_add_swap_buffers_callback \
cogl_framebuffer_add_swap_buffers_callback_EXP
unsigned int
cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
CoglSwapBuffersNotify callback,
void *user_data);
#define cogl_framebuffer_remove_swap_buffers_callback \
cogl_framebuffer_remove_swap_buffers_callback_EXP
void
cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
unsigned int id);
typedef struct _CoglOnscreen CoglOnscreen;
#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
CoglOnscreen *
cogl_onscreen_new (CoglContext *context, int width, int height);
#ifdef COGL_HAS_X11
#define cogl_onscreen_x11_set_foreign_window_xid \
cogl_onscreen_x11_set_foreign_window_xid_EXP
void
cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
guint32 xid);
#define cogl_onscreen_x11_get_window_xid cogl_onscreen_x11_get_window_xid_EXP
guint32
cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen);
#define cogl_onscreen_x11_get_visual_xid cogl_onscreen_x11_get_visual_xid_EXP
guint32
cogl_onscreen_x11_get_visual_xid (CoglOnscreen *onscreen);
#endif /* COGL_HAS_X11 */
void
cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
gboolean throttled);
#define cogl_get_draw_framebuffer cogl_get_draw_framebuffer_EXP
CoglFramebuffer *
cogl_get_draw_framebuffer (void);
#endif /* COGL_ENABLE_EXPERIMENTAL_API */
G_END_DECLS
#endif /* __COGL_FRAMEBUFFER_H */

View File

@ -29,7 +29,7 @@
#include "cogl-bitmask.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
typedef enum
@ -119,99 +119,17 @@ _cogl_transform_point (const CoglMatrix *matrix_mv,
float *x,
float *y);
#ifdef COGL_HAS_XLIB_SUPPORT
#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ())
/*
* CoglX11FilterReturn:
* @COGL_XLIB_FILTER_CONTINUE: The event was not handled, continues the
* processing
* @COGL_XLIB_FILTER_REMOVE: Remove the event, stops the processing
*
* Return values for the #CoglX11FilterFunc function.
*/
typedef enum _CoglXlibFilterReturn {
COGL_XLIB_FILTER_CONTINUE,
COGL_XLIB_FILTER_REMOVE
} CoglXlibFilterReturn;
/*
* CoglXlibFilterFunc:
*
* A callback function that can be registered with
* _cogl_xlib_add_filter. The function should return
* %COGL_XLIB_FILTER_REMOVE if it wants to prevent further processing
* or %COGL_XLIB_FILTER_CONTINUE otherwise.
*/
typedef CoglXlibFilterReturn (* CoglXlibFilterFunc) (XEvent *xevent,
gpointer data);
/*
* cogl_xlib_handle_event:
* @xevent: pointer to XEvent structure
*
* This function processes a single X event; it can be used to hook
* into external X event retrieval (for example that done by Clutter
* or GDK).
*
* Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE
* indicates that Cogl has internally handled the event and the
* caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE
* indicates that Cogl is either not interested in the event,
* or has used the event to update internal state without taking
* any exclusive action.
*/
CoglXlibFilterReturn
_cogl_xlib_handle_event (XEvent *xevent);
/*
* _cogl_xlib_get_display:
*
* Return value: the Xlib display that will be used by the Xlib winsys
* backend. The display needs to be set with _cogl_xlib_set_display()
* before this function is called.
*/
Display *
_cogl_xlib_get_display (void);
/*
* cogl_xlib_set_display:
*
* Sets the Xlib display that Cogl will use for the Xlib winsys
* backend. This function should eventually go away when Cogl gains a
* more complete winsys abstraction.
*/
void
_cogl_xlib_set_display (Display *display);
/*
* _cogl_xlib_add_filter:
*
* Adds a callback function that will receive all X11 events. The
* function can stop further processing of the event by return
* %COGL_XLIB_FILTER_REMOVE.
*/
void
_cogl_xlib_add_filter (CoglXlibFilterFunc func,
gpointer data);
/*
* _cogl_xlib_remove_filter:
*
* Removes a callback that was previously added with
* _cogl_xlib_add_filter().
*/
void
_cogl_xlib_remove_filter (CoglXlibFilterFunc func,
gpointer data);
#endif /* COGL_HAS_XLIB_SUPPORT */
typedef enum _CoglFeatureFlagsPrivate
{
COGL_FEATURE_PRIVATE_PLACE_HOLDER = (1 << 0)
} CoglFeatureFlagsPrivate;
typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/
COGL_DRIVER_ERROR_UNKNOWN_VERSION,
COGL_DRIVER_ERROR_INVALID_VERSION
} CoglDriverError;
gboolean
_cogl_features_available_private (CoglFeatureFlagsPrivate features);
_cogl_check_extension (const char *name, const char *ext);
GQuark
_cogl_driver_error_quark (void);
#endif /* __COGL_INTERNAL_H */

View File

@ -24,6 +24,7 @@
#ifndef __COGL_JOURNAL_PRIVATE_H
#define __COGL_JOURNAL_PRIVATE_H
#include "cogl.h"
#include "cogl-handle.h"
#include "cogl-clip-stack.h"

View File

@ -26,6 +26,12 @@
G_BEGIN_DECLS
gboolean
_cogl_gl_check_version (GError **error);
void
_cogl_gl_update_features (CoglContext *context);
gboolean
_cogl_check_extension (const char *name, const char *ext);

View File

@ -0,0 +1,61 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* 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, see
* <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_RENDERER_GLX_PRIVATE_H
#define __COGL_RENDERER_GLX_PRIVATE_H
#include "cogl-object-private.h"
#include "cogl-renderer-xlib-private.h"
typedef struct _CoglRendererGLX
{
CoglRendererXlib _parent;
int glx_major;
int glx_minor;
int glx_error_base;
int glx_event_base;
gboolean is_direct;
/* Vblank stuff */
int dri_fd;
/* Function pointers for GLX specific extensions */
#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
ret (APIENTRY * pf_ ## name) args;
#define COGL_WINSYS_FEATURE_END()
#include "cogl-winsys-glx-feature-functions.h"
#undef COGL_WINSYS_FEATURE_BEGIN
#undef COGL_WINSYS_FEATURE_FUNCTION
#undef COGL_WINSYS_FEATURE_END
} CoglRendererGLX;
#endif /* __COGL_RENDERER_GLX_PRIVATE_H */

View File

@ -0,0 +1,32 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_RENDERER_X11_PRIVATE_H
#define __COGL_RENDERER_X11_PRIVATE_H
typedef struct _CoglRendererX11
{
int damage_base;
} CoglRendererX11;
#endif /* __COGL_RENDERER_X11_PRIVATE_H */

View File

@ -3,7 +3,7 @@
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
* Copyright (C) 2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -15,30 +15,40 @@
* 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, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_XLIB_H
#define __COGL_XLIB_H
#ifndef __COGL_RENDERER_XLIB_PRIVATE_H
#define __COGL_RENDERER_XLIB_PRIVATE_H
#include "cogl.h"
#include "cogl-context-winsys.h"
#include "cogl-object-private.h"
#include "cogl-xlib-private.h"
#include "cogl-renderer-x11-private.h"
#include <X11/Xlib.h>
typedef struct _CoglXlibFilterClosure CoglXlibFilterClosure;
struct _CoglXlibFilterClosure
typedef struct _CoglRendererXlib
{
CoglXlibFilterFunc func;
gpointer data;
};
CoglRendererX11 _parent;
Display *xdpy;
/* List of callback functions that will be given every Xlib event */
GSList *event_filters;
/* Current top of the XError trap state stack. The actual memory for
these is expected to be allocated on the stack by the caller */
CoglXlibTrapState *trap_state;
} CoglRendererXlib;
gboolean
_cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error);
void
_cogl_renderer_xlib_disconnect (CoglRenderer *renderer);
/*
* _cogl_xlib_trap_errors:
* cogl_renderer_xlib_trap_errors:
* @state: A temporary place to store data for the trap.
*
* Traps every X error until _cogl_xlib_untrap_errors() called. You
@ -50,10 +60,11 @@ struct _CoglXlibFilterClosure
* pointers in reverse order.
*/
void
_cogl_xlib_trap_errors (CoglXlibTrapState *state);
_cogl_renderer_xlib_trap_errors (CoglRenderer *renderer,
CoglXlibTrapState *state);
/*
* _cogl_xlib_untrap_errors:
* cogl_renderer_xlib_untrap_errors:
* @state: The state that was passed to _cogl_xlib_trap_errors().
*
* Removes the X error trap and returns the current status.
@ -61,6 +72,7 @@ _cogl_xlib_trap_errors (CoglXlibTrapState *state);
* Return value: the trapped error code, or 0 for success
*/
int
_cogl_xlib_untrap_errors (CoglXlibTrapState *state);
_cogl_renderer_xlib_untrap_errors (CoglRenderer *renderer,
CoglXlibTrapState *state);
#endif /* __COGL_XLIB_H */
#endif /* __COGL_RENDERER_XLIB_PRIVATE_H */

View File

@ -0,0 +1,288 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2008,2009,2010 Intel Corporation.
*
* 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.
*
* Authors:
* Robert Bragg <robert@linux.intel.com>
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl.h"
#include "cogl-internal.h"
#include "cogl-object.h"
#include "cogl-renderer-private.h"
#include "cogl-renderer-xlib-private.h"
#include "cogl-renderer-x11-private.h"
#include "cogl-winsys-private.h"
#include <X11/Xlib.h>
#include <X11/extensions/Xdamage.h>
static char *_cogl_x11_display_name = NULL;
static GList *_cogl_xlib_renderers = NULL;
CoglXlibFilterReturn
cogl_renderer_xlib_handle_event (CoglRenderer *renderer,
XEvent *xevent)
{
CoglRendererXlib *xlib_renderer = renderer->winsys;
GSList *l;
g_return_val_if_fail (xlib_renderer->xdpy != NULL, COGL_XLIB_FILTER_CONTINUE);
/* XXX: should this be a more graceful check? */
g_return_val_if_fail (xlib_renderer != NULL, COGL_XLIB_FILTER_CONTINUE);
/* Pass the event on to all of the registered filters in turn */
for (l = xlib_renderer->event_filters; l; l = l->next)
{
CoglXlibFilterClosure *closure = l->data;
if (closure->func (xevent, closure->data) == COGL_XLIB_FILTER_REMOVE)
return COGL_XLIB_FILTER_REMOVE;
}
switch (xevent->type)
{
/* TODO... */
default:
break;
}
return COGL_XLIB_FILTER_CONTINUE;
}
void
cogl_renderer_xlib_add_filter (CoglRenderer *renderer,
CoglXlibFilterFunc func,
void *data)
{
CoglRendererXlib *xlib_renderer;
CoglXlibFilterClosure *closure;
xlib_renderer = renderer->winsys;
closure = g_slice_new (CoglXlibFilterClosure);
closure->func = func;
closure->data = data;
xlib_renderer->event_filters =
g_slist_prepend (xlib_renderer->event_filters, closure);
}
void
cogl_renderer_xlib_remove_filter (CoglRenderer *renderer,
CoglXlibFilterFunc func,
void *data)
{
CoglRendererXlib *xlib_renderer;
GSList *l, *prev = NULL;
xlib_renderer = renderer->winsys;
for (l = xlib_renderer->event_filters; l; prev = l, l = l->next)
{
CoglXlibFilterClosure *closure = l->data;
if (closure->func == func && closure->data == data)
{
g_slice_free (CoglXlibFilterClosure, closure);
if (prev)
prev->next = g_slist_delete_link (prev->next, l);
else
xlib_renderer->event_filters =
g_slist_delete_link (xlib_renderer->event_filters, l);
break;
}
}
}
static void
register_xlib_renderer (CoglRenderer *renderer)
{
GList *l;
for (l = _cogl_xlib_renderers; l; l = l->next)
if (l->data == renderer)
return;
_cogl_xlib_renderers = g_list_prepend (_cogl_xlib_renderers, renderer);
}
static void
unregister_xlib_renderer (CoglRenderer *renderer)
{
_cogl_xlib_renderers = g_list_remove (_cogl_xlib_renderers, renderer);
}
static CoglRenderer *
get_renderer_for_xdisplay (Display *xdpy)
{
GList *l;
for (l = _cogl_xlib_renderers; l; l = l->next)
{
CoglRenderer *renderer = l->data;
CoglRendererXlib *xlib_renderer = renderer->winsys;
if (xlib_renderer->xdpy == xdpy)
return renderer;
}
return NULL;
}
static int
error_handler (Display *xdpy,
XErrorEvent *error)
{
CoglRenderer *renderer;
CoglRendererXlib *xlib_renderer;
renderer = get_renderer_for_xdisplay (xdpy);
xlib_renderer = renderer->winsys;
g_assert (xlib_renderer->trap_state);
xlib_renderer->trap_state->trapped_error_code = error->error_code;
return 0;
}
void
_cogl_renderer_xlib_trap_errors (CoglRenderer *renderer,
CoglXlibTrapState *state)
{
CoglRendererXlib *xlib_renderer;
xlib_renderer = renderer->winsys;
state->trapped_error_code = 0;
state->old_error_handler = XSetErrorHandler (error_handler);
state->old_state = xlib_renderer->trap_state;
xlib_renderer->trap_state = state;
}
int
_cogl_renderer_xlib_untrap_errors (CoglRenderer *renderer,
CoglXlibTrapState *state)
{
CoglRendererXlib *xlib_renderer;
xlib_renderer = renderer->winsys;
g_assert (state == xlib_renderer->trap_state);
XSetErrorHandler (state->old_error_handler);
xlib_renderer->trap_state = state->old_state;
return state->trapped_error_code;
}
static Display *
assert_xlib_display (CoglRenderer *renderer, GError **error)
{
Display *xdpy = cogl_renderer_xlib_get_foreign_display (renderer);
CoglRendererXlib *xlib_renderer = renderer->winsys;
/* A foreign display may have already been set... */
if (xdpy)
{
xlib_renderer->xdpy = xdpy;
return xdpy;
}
xdpy = XOpenDisplay (_cogl_x11_display_name);
if (xdpy == NULL)
{
g_set_error (error,
COGL_RENDERER_ERROR,
COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN,
"Failed to open X Display %s", _cogl_x11_display_name);
return NULL;
}
xlib_renderer->xdpy = xdpy;
return xdpy;
}
gboolean
_cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error)
{
CoglRendererXlib *xlib_renderer = renderer->winsys;
CoglRendererX11 *x11_renderer = renderer->winsys;
int damage_error;
if (!assert_xlib_display (renderer, error))
return FALSE;
/* Check whether damage events are supported on this display */
if (!XDamageQueryExtension (xlib_renderer->xdpy,
&x11_renderer->damage_base,
&damage_error))
x11_renderer->damage_base = -1;
xlib_renderer->event_filters = NULL;
xlib_renderer->trap_state = NULL;
register_xlib_renderer (renderer);
return TRUE;
}
static void
free_xlib_filter_closure (void *data, void *user_data)
{
g_slice_free (CoglXlibFilterClosure, data);
}
void
_cogl_renderer_xlib_disconnect (CoglRenderer *renderer)
{
CoglRendererXlib *xlib_renderer = renderer->winsys;
g_slist_foreach (xlib_renderer->event_filters,
free_xlib_filter_closure, NULL);
g_slist_free (xlib_renderer->event_filters);
if (!renderer->foreign_xdpy)
XCloseDisplay (xlib_renderer->xdpy);
unregister_xlib_renderer (renderer);
}
Display *
cogl_renderer_xlib_get_display (CoglRenderer *renderer)
{
CoglRendererXlib *xlib_renderer;
g_return_val_if_fail (cogl_is_renderer (renderer), NULL);
xlib_renderer = renderer->winsys;
return xlib_renderer->xdpy;
}

View File

@ -50,6 +50,9 @@ cogl_renderer_error_quark (void)
static void
_cogl_renderer_free (CoglRenderer *renderer)
{
#ifdef COGL_HAS_FULL_WINSYS
_cogl_winsys_renderer_disconnect (renderer);
#endif
g_free (renderer);
}
@ -90,6 +93,21 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
CoglOnscreenTemplate *onscreen_template,
GError **error)
{
#ifdef COGL_HAS_FULL_WINSYS
CoglDisplay *display;
if (!_cogl_winsys_renderer_connect (renderer, error))
return FALSE;
display = cogl_display_new (renderer, onscreen_template);
if (!cogl_display_setup (display, error))
{
cogl_object_unref (display);
return FALSE;
}
cogl_object_unref (display);
#endif
return TRUE;
}
@ -101,6 +119,11 @@ cogl_renderer_connect (CoglRenderer *renderer, GError **error)
if (renderer->connected)
return TRUE;
#ifdef COGL_HAS_FULL_WINSYS
if (!_cogl_winsys_renderer_connect (renderer, error))
return FALSE;
#endif
renderer->connected = TRUE;
return TRUE;
}

View File

@ -30,6 +30,11 @@
#include <glib-object.h>
#include <cogl/cogl-defines.h>
#ifdef COGL_HAS_XLIB
#include <X11/Xlib.h>
#endif
G_BEGIN_DECLS
/* Some structures are meant to be opaque but they have public
@ -284,7 +289,8 @@ typedef enum
COGL_FEATURE_TEXTURE_3D = (1 << 19),
COGL_FEATURE_SHADERS_ARBFP = (1 << 20),
COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22)
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23)
} CoglFeatureFlags;
/**
@ -582,11 +588,84 @@ typedef enum
COGL_DEPTH_TEST_FUNCTION_GEQUAL = 0x0206,
COGL_DEPTH_TEST_FUNCTION_ALWAYS = 0x0207
} CoglDepthTestFunction;
/* XXX: Note these types are only referenced by experimental API so
* although they aren't explicitly guarded they are implicitly
* experimental too. */
/* NB: The above definitions are taken from gl.h equivalents */
typedef enum { /*< prefix=COGL_RENDERER_ERROR >*/
COGL_RENDERER_ERROR_NOT_FOUND,
COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN
} CoglRendererError;
/*
* CoglXlibFilterReturn:
* @COGL_XLIB_FILTER_CONTINUE: The event was not handled, continues the
* processing
* @COGL_XLIB_FILTER_REMOVE: Remove the event, stops the processing
*
* Return values for the #CoglXlibFilterFunc function.
*
* Stability: Unstable
*/
typedef enum _CoglXlibFilterReturn { /*< prefix=COGL_XLIB_FILTER >*/
COGL_XLIB_FILTER_CONTINUE,
COGL_XLIB_FILTER_REMOVE
} CoglXlibFilterReturn;
typedef enum _CoglWinsysFeature
{
COGL_WINSYS_FEATURE_NONE,
/* Available if the window system can support multiple onscreen
* framebuffers at the same time. */
COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
/* Available if onscreen framebuffer swaps can be automatically
* throttled to the vblank frequency. */
COGL_WINSYS_FEATURE_SWAP_THROTTLE,
/* Available if its possible to query a counter that
* increments at each vblank. */
COGL_WINSYS_FEATURE_VBLANK_COUNTER,
/* Available if its possible to wait until the next vertical
* blank period */
COGL_WINSYS_FEATURE_VBLANK_WAIT,
/* Available if the window system supports mapping native
* pixmaps to textures. */
COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP,
/* Available if the window system supports reporting an event
* for swap buffer completions. */
COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT,
/* Available if it's possible to swap a list of sub rectangles
* from the back buffer to the front buffer */
COGL_WINSYS_FEATURE_SWAP_REGION,
/* Available if swap_region requests can be automatically throttled
* to the vblank frequency. */
COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE
} CoglWinsysFeature;
/* XXX: Note these enum types are only referenced by experimental API
* so although they aren't explicitly guarded they are implicitly
* experimental too. */
#ifdef COGL_HAS_XLIB
/*
* CoglXlibFilterFunc:
*
* A callback function that can be registered with
* _cogl_xlib_add_filter. The function should return
* %COGL_XLIB_FILTER_REMOVE if it wants to prevent further processing
* or %COGL_XLIB_FILTER_CONTINUE otherwise.
*/
typedef CoglXlibFilterReturn (* CoglXlibFilterFunc) (XEvent *xevent,
void *data);
#endif /* COGL_HAS_XLIB */
G_END_DECLS
#endif /* __COGL_TYPES_H__ */

View File

@ -37,7 +37,6 @@
#include "cogl-shader.h"
#include "cogl-texture.h"
#include "cogl-types.h"
#include "cogl-handle.h"
#include "cogl-util.h"
/*

View File

@ -0,0 +1,82 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010,2011 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_XLIB_PRIVATE_H
#define __COGL_XLIB_PRIVATE_H
#include "cogl/cogl.h"
#include <X11/Xlib.h>
typedef struct _CoglXlibTrapState CoglXlibTrapState;
struct _CoglXlibTrapState
{
/* These values are intended to be internal to
* _cogl_xlib_{un,}trap_errors but they need to be in the header so
* that the struct can be allocated on the stack */
int (* old_error_handler) (Display *, XErrorEvent *);
int trapped_error_code;
CoglXlibTrapState *old_state;
};
typedef struct _CoglXlibFilterClosure
{
CoglXlibFilterFunc func;
void *data;
} CoglXlibFilterClosure;
void
_cogl_xlib_query_damage_extension (void);
int
_cogl_xlib_get_damage_base (void);
void
_cogl_xlib_trap_errors (CoglXlibTrapState *state);
int
_cogl_xlib_untrap_errors (CoglXlibTrapState *state);
/*
* _cogl_xlib_add_filter:
*
* Adds a callback function that will receive all X11 events. The
* function can stop further processing of the event by return
* %COGL_XLIB_FILTER_REMOVE.
*/
void
_cogl_xlib_add_filter (CoglXlibFilterFunc func,
void *data);
/*
* _cogl_xlib_remove_filter:
*
* Removes a callback that was previously added with
* _cogl_xlib_add_filter().
*/
void
_cogl_xlib_remove_filter (CoglXlibFilterFunc func,
void *data);
#endif /* __COGL_XLIB_PRIVATE_H */

View File

@ -3,7 +3,7 @@
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
* Copyright (C) 2010,2011 Intel Corporation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -34,24 +34,36 @@
#include <cogl-handle.h>
#include <cogl-context-private.h>
#include <cogl-framebuffer-private.h>
#include <cogl-display-private.h>
#include <cogl-renderer-private.h>
#include <cogl-renderer-xlib-private.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xdamage.h>
#include "cogl-xlib.h"
/* FIXME: when we remove the last X11 based Clutter backend then we
* will get rid of these functions and instead rely on the equivalent
* _cogl_renderer_xlib API
*/
/* This can't be in the Cogl context because it can be set before
context is created */
static Display *_cogl_xlib_display = NULL;
CoglXlibFilterReturn
_cogl_xlib_handle_event (XEvent *xevent)
cogl_xlib_handle_event (XEvent *xevent)
{
GSList *l;
_COGL_GET_CONTEXT (ctx, COGL_XLIB_FILTER_CONTINUE);
if (!ctx->stub_winsys)
return cogl_renderer_xlib_handle_event (ctx->display->renderer, xevent);
/* Pass the event on to all of the registered filters in turn */
for (l = ctx->winsys.event_filters; l; l = l->next)
for (l = ctx->event_filters; l; l = l->next)
{
CoglXlibFilterClosure *closure = l->data;
@ -70,10 +82,13 @@ _cogl_xlib_handle_event (XEvent *xevent)
}
Display *
_cogl_xlib_get_display (void)
cogl_xlib_get_display (void)
{
_COGL_GET_CONTEXT (ctx, NULL);
if (!ctx->stub_winsys)
return cogl_renderer_xlib_get_display (ctx->display->renderer);
/* _cogl_xlib_set_display should be called before this function */
g_assert (_cogl_xlib_display != NULL);
@ -81,7 +96,7 @@ _cogl_xlib_get_display (void)
}
void
_cogl_xlib_set_display (Display *display)
cogl_xlib_set_display (Display *display)
{
/* This can only be called once before the Cogl context is created */
g_assert (_cogl_xlib_display == NULL);
@ -91,29 +106,43 @@ _cogl_xlib_set_display (Display *display)
void
_cogl_xlib_add_filter (CoglXlibFilterFunc func,
gpointer data)
void *data)
{
CoglXlibFilterClosure *closure;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
if (!ctx->stub_winsys)
{
cogl_renderer_xlib_add_filter (ctx->display->renderer,
func, data);
return;
}
closure = g_slice_new (CoglXlibFilterClosure);
closure->func = func;
closure->data = data;
ctx->winsys.event_filters =
g_slist_prepend (ctx->winsys.event_filters, closure);
ctx->event_filters =
g_slist_prepend (ctx->event_filters, closure);
}
void
_cogl_xlib_remove_filter (CoglXlibFilterFunc func,
gpointer data)
void *data)
{
GSList *l, *prev = NULL;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
for (l = ctx->winsys.event_filters; l; prev = l, l = l->next)
if (!ctx->stub_winsys)
{
cogl_renderer_xlib_remove_filter (ctx->display->renderer,
func, data);
return;
}
for (l = ctx->event_filters; l; prev = l, l = l->next)
{
CoglXlibFilterClosure *closure = l->data;
@ -123,8 +152,8 @@ _cogl_xlib_remove_filter (CoglXlibFilterFunc func,
if (prev)
prev->next = g_slist_delete_link (prev->next, l);
else
ctx->winsys.event_filters =
g_slist_delete_link (ctx->winsys.event_filters, l);
ctx->event_filters =
g_slist_delete_link (ctx->event_filters, l);
break;
}
}
@ -136,9 +165,9 @@ error_handler (Display *xdpy,
{
_COGL_GET_CONTEXT (ctxt, 0);
g_assert (ctxt->winsys.trap_state);
g_assert (ctxt->trap_state);
ctxt->winsys.trap_state->trapped_error_code = error->error_code;
ctxt->trap_state->trapped_error_code = error->error_code;
return 0;
}
@ -148,11 +177,17 @@ _cogl_xlib_trap_errors (CoglXlibTrapState *state)
{
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
if (!ctxt->stub_winsys)
{
_cogl_renderer_xlib_trap_errors (ctxt->display->renderer, state);
return;
}
state->trapped_error_code = 0;
state->old_error_handler = XSetErrorHandler (error_handler);
state->old_state = ctxt->winsys.trap_state;
ctxt->winsys.trap_state = state;
state->old_state = ctxt->trap_state;
ctxt->trap_state = state;
}
int
@ -160,11 +195,44 @@ _cogl_xlib_untrap_errors (CoglXlibTrapState *state)
{
_COGL_GET_CONTEXT (ctxt, 0);
g_assert (state == ctxt->winsys.trap_state);
if (!ctxt->stub_winsys)
{
return _cogl_renderer_xlib_untrap_errors (ctxt->display->renderer, state);
}
g_assert (state == ctxt->trap_state);
XSetErrorHandler (state->old_error_handler);
ctxt->winsys.trap_state = state->old_state;
ctxt->trap_state = state->old_state;
return state->trapped_error_code;
}
void
_cogl_xlib_query_damage_extension (void)
{
int damage_error;
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
/* Check whether damage events are supported on this display */
if (!XDamageQueryExtension (cogl_xlib_get_display (),
&ctxt->damage_base,
&damage_error))
ctxt->damage_base = -1;
}
int
_cogl_xlib_get_damage_base (void)
{
_COGL_GET_CONTEXT (ctxt, -1);
if (!ctxt->stub_winsys)
{
CoglRendererX11 *x11_renderer = ctxt->display->renderer->winsys;
return x11_renderer->damage_base;
}
else
return ctxt->damage_base;
}

View File

@ -0,0 +1,84 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2011 Intel Corporation.
*
* 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.
*/
#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <cogl/cogl.h> can be included directly."
#endif
#ifndef __COGL_XLIB_H__
#define __COGL_XLIB_H__
#include <cogl/cogl-types.h>
#include <X11/Xlib.h>
G_BEGIN_DECLS
/*
* cogl_xlib_get_display:
*
* Return value: the Xlib display that will be used by the Xlib winsys
* backend. The display needs to be set with _cogl_xlib_set_display()
* before this function is called.
*
* Stability: Unstable
*/
#define cogl_xlib_get_display cogl_xlib_get_display_EXP
Display *
cogl_xlib_get_display (void);
/*
* cogl_xlib_set_display:
*
* Sets the Xlib display that Cogl will use for the Xlib winsys
* backend. This function should eventually go away when Cogl gains a
* more complete winsys abstraction.
*
* Stability: Unstable
*/
#define cogl_xlib_set_display cogl_xlib_set_display_EXP
void
cogl_xlib_set_display (Display *display);
/*
* cogl_xlib_handle_event:
* @xevent: pointer to XEvent structure
*
* This function processes a single X event; it can be used to hook
* into external X event retrieval (for example that done by Clutter
* or GDK).
*
* Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE
* indicates that Cogl has internally handled the event and the
* caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE
* indicates that Cogl is either not interested in the event,
* or has used the event to update internal state without taking
* any exclusive action.
*
* Stability: Unstable
*/
#define cogl_xlib_handle_event cogl_xlib_handle_event_EXP
CoglXlibFilterReturn
cogl_xlib_handle_event (XEvent *xevent);
#endif /* __COGL_XLIB_H__ */

View File

@ -38,7 +38,7 @@
#include "cogl-context-private.h"
#include "cogl-pipeline-private.h"
#include "cogl-pipeline-opengl-private.h"
#include "cogl-winsys.h"
#include "cogl-winsys-private.h"
#include "cogl-framebuffer-private.h"
#include "cogl-matrix-private.h"
#include "cogl-journal-private.h"
@ -394,14 +394,6 @@ cogl_features_available (CoglFeatureFlags features)
return (ctx->feature_flags & features) == features;
}
gboolean
_cogl_features_available_private (CoglFeatureFlagsPrivate features)
{
_COGL_GET_CONTEXT (ctx, 0);
return (ctx->feature_flags_private & features) == features;
}
/* XXX: This function should either be replaced with one returning
* integers, or removed/deprecated and make the
* _cogl_framebuffer_get_viewport* functions public.

View File

@ -67,7 +67,12 @@
#include <cogl/cogl-deprecated.h>
typedef struct _CoglFramebuffer CoglFramebuffer;
#if defined (COGL_ENABLE_EXPERIMENTAL_API)
#include <cogl/cogl-swap-chain.h>
#include <cogl/cogl-renderer.h>
#include <cogl/cogl-display.h>
#include <cogl/cogl-context.h>
#include <cogl/cogl-buffer.h>
#include <cogl/cogl-pixel-array.h>
@ -79,6 +84,13 @@
#include <cogl/cogl-attribute.h>
#include <cogl/cogl-primitive.h>
#include <cogl/cogl-pipeline.h>
#include <cogl/cogl-framebuffer.h>
#ifdef COGL_HAS_XLIB
#include <cogl/cogl-xlib.h>
#endif
/* XXX: This will definitly go away once all the Clutter winsys
* code has been migrated down into Cogl! */
#include <cogl/cogl-clutter.h>
#endif
G_BEGIN_DECLS
@ -90,8 +102,6 @@ G_BEGIN_DECLS
* General utility functions for COGL.
*/
typedef struct _CoglFramebuffer CoglFramebuffer;
/**
* cogl_get_option_group:
*
@ -1245,44 +1255,6 @@ cogl_begin_gl (void);
void
cogl_end_gl (void);
/*
* Internal API available only to Clutter.
*
* These are typically only to deal with the poor seperation of
* responsabilities that currently exists between Clutter and Cogl.
* Eventually a lot of the backend code currently in Clutter will
* move down into Cogl and these functions will be removed.
*/
void
_cogl_destroy_context (void);
/*< private >*/
#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ())
typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/
COGL_DRIVER_ERROR_UNKNOWN_VERSION,
COGL_DRIVER_ERROR_INVALID_VERSION
} CoglDriverError;
gboolean
_cogl_check_extension (const char *name, const char *ext);
void
_cogl_set_indirect_context (gboolean indirect);
gboolean
_cogl_check_driver_valid (GError **error);
GQuark
_cogl_driver_error_quark (void);
#ifdef COGL_ENABLE_EXPERIMENTAL_API
#define cogl_get_draw_framebuffer cogl_get_draw_framebuffer_EXP
CoglFramebuffer *
cogl_get_draw_framebuffer (void);
#endif
G_END_DECLS
#undef __COGL_H_INSIDE__

View File

@ -0,0 +1,53 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2007,2008,2009 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_CONTEXT_DRIVER_H
#define __COGL_CONTEXT_DRIVER_H
#include "cogl.h"
#ifndef APIENTRY
#define APIENTRY
#endif
#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
#define COGL_FEATURE_FUNCTION(ret, name, args) \
ret (APIENTRY * pf_ ## name) args;
#define COGL_FEATURE_END()
typedef struct _CoglContextDriver
{
/* This defines a list of function pointers */
#include "cogl-feature-functions-gl.h"
GLint gl_max_program_temoraries_arb;
} CoglContextDriver;
#undef COGL_FEATURE_BEGIN
#undef COGL_FEATURE_FUNCTION
#undef COGL_FEATURE_END
#endif /* __COGL_CONTEXT_DRIVER_H */

View File

@ -29,6 +29,7 @@
#include "cogl.h"
#include "cogl-private.h"
#include "cogl-internal.h"
#include "cogl-context-private.h"
#include "cogl-feature-private.h"
@ -95,7 +96,7 @@ _cogl_get_gl_version (int *major_out, int *minor_out)
}
gboolean
_cogl_check_driver_valid (GError **error)
_cogl_gl_check_version (GError **error)
{
int major, minor;
const char *gl_extensions;
@ -161,8 +162,8 @@ _cogl_check_driver_valid (GError **error)
namespaces, extension_names, \
feature_flags, feature_flags_private) \
{ min_gl_major, min_gl_minor, namespaces, \
extension_names, feature_flags, feature_flags_private, \
cogl_feature_ ## name ## _funcs },
extension_names, feature_flags, feature_flags_private, 0, \
cogl_feature_ ## name ## _funcs },
#undef COGL_FEATURE_FUNCTION
#define COGL_FEATURE_FUNCTION(ret, name, args)
#undef COGL_FEATURE_END
@ -182,23 +183,35 @@ static const CoglFeatureData cogl_feature_data[] =
#define COGL_FEATURE_END()
static void
initialize_context_driver (CoglContext *context)
initialize_function_table (CoglContext *context)
{
#include "cogl-feature-functions-gl.h"
}
/* Query the GL extensions and lookup the corresponding function
* pointers. Theoretically the list of extensions can change for
* different GL contexts so it is the winsys backend's responsiblity
* to know when to re-query the GL extensions. */
void
_cogl_gl_context_init (CoglContext *context)
_cogl_gl_update_features (CoglContext *context)
{
CoglFeatureFlags flags = 0;
CoglFeatureFlagsPrivate flags_private = 0;
const char *gl_extensions;
int max_clip_planes = 0;
int num_stencil_bits = 0;
int gl_major = 0, gl_minor = 0;
int i;
initialize_context_driver (context);
COGL_NOTE (WINSYS,
"Checking features\n"
" GL_VENDOR: %s\n"
" GL_RENDERER: %s\n"
" GL_VERSION: %s\n"
" GL_EXTENSIONS: %s",
glGetString (GL_VENDOR),
glGetString (GL_RENDERER),
glGetString (GL_VERSION),
glGetString (GL_EXTENSIONS));
_cogl_get_gl_version (&gl_major, &gl_minor);
@ -235,16 +248,15 @@ _cogl_gl_context_init (CoglContext *context)
if (max_clip_planes >= 4)
flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
initialize_function_table (context);
for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
if (_cogl_feature_check ("GL", cogl_feature_data + i,
gl_major, gl_minor,
gl_extensions))
{
flags |= cogl_feature_data[i].feature_flags;
flags_private |= cogl_feature_data[i].feature_flags_private;
}
gl_extensions,
context))
flags |= cogl_feature_data[i].feature_flags;
/* Cache features */
context->feature_flags = flags;
context->feature_flags_private = flags_private;
context->feature_flags |= flags;
}

View File

@ -0,0 +1,52 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2007,2008,2009 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_CONTEXT_DRIVER_H
#define __COGL_CONTEXT_DRIVER_H
#include "cogl.h"
#ifndef APIENTRY
#define APIENTRY
#endif
#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
#define COGL_FEATURE_FUNCTION(ret, name, args) \
ret (APIENTRY * pf_ ## name) args;
#define COGL_FEATURE_END()
typedef struct _CoglContextDriver
{
/* This defines a list of function pointers */
#include "cogl-feature-functions-gles.h"
} CoglContextDriver;
#undef COGL_FEATURE_BEGIN
#undef COGL_FEATURE_FUNCTION
#undef COGL_FEATURE_END
#endif /* __COGL_CONTEXT_DRIVER_H */

View File

@ -33,7 +33,7 @@
#include "cogl-feature-private.h"
gboolean
_cogl_check_driver_valid (GError **error)
_cogl_gl_check_version (GError **error)
{
/* The GLES backend doesn't have any particular version requirements */
return TRUE;
@ -58,8 +58,8 @@ _cogl_check_driver_valid (GError **error)
namespaces, extension_names, \
feature_flags, feature_flags_private) \
{ min_gl_major, min_gl_minor, namespaces, \
extension_names, feature_flags, feature_flags_private, \
cogl_feature_ ## name ## _funcs },
extension_names, feature_flags, feature_flags_private, 0, \
cogl_feature_ ## name ## _funcs },
#undef COGL_FEATURE_FUNCTION
#define COGL_FEATURE_FUNCTION(ret, name, args)
#undef COGL_FEATURE_END
@ -74,36 +74,44 @@ static const CoglFeatureData cogl_feature_data[] =
#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
#undef COGL_FEATURE_FUNCTION
#define COGL_FEATURE_FUNCTION(ret, name, args) \
_context->drv.pf_ ## name = NULL;
context->drv.pf_ ## name = NULL;
#undef COGL_FEATURE_END
#define COGL_FEATURE_END()
static void
initialize_context_driver (CoglContext *context)
initialize_function_table (CoglContext *context)
{
#include "cogl-feature-functions-gles.h"
}
/* Query the GL extensions and lookup the corresponding function
* pointers. Theoretically the list of extensions can change for
* different GL contexts so it is the winsys backend's responsiblity
* to know when to re-query the GL extensions. */
void
_cogl_gl_context_init (CoglContext *context)
_cogl_gl_update_features (CoglContext *context)
{
CoglFeatureFlags flags = 0;
const char *gl_extensions;
#ifndef HAVE_COGL_GLES2
int max_clip_planes = 0;
#endif
int num_stencil_bits = 0;
const char *gl_extensions;
int i;
initialize_context_driver (context);
COGL_NOTE (WINSYS,
"Checking features\n"
" GL_VENDOR: %s\n"
" GL_RENDERER: %s\n"
" GL_VERSION: %s\n"
" GL_EXTENSIONS: %s",
glGetString (GL_VENDOR),
glGetString (GL_RENDERER),
glGetString (GL_VERSION),
glGetString (GL_EXTENSIONS));
gl_extensions = (const char*) glGetString (GL_EXTENSIONS);
for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
if (_cogl_feature_check ("GL", cogl_feature_data + i,
0, 0,
gl_extensions))
flags |= cogl_feature_data[i].feature_flags;
GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
/* We need at least three stencil bits to combine clips */
@ -128,7 +136,15 @@ _cogl_gl_context_init (CoglContext *context)
/* Both GLES 1.1 and GLES 2.0 support point sprites in core */
flags |= COGL_FEATURE_POINT_SPRITE;
/* Cache features */
context->feature_flags = flags;
}
initialize_function_table (context);
for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
if (_cogl_feature_check ("GL", cogl_feature_data + i,
0, 0,
gl_extensions,
context))
flags |= cogl_feature_data[i].feature_flags;
/* Cache features */
context->feature_flags |= flags;
}

View File

@ -1,152 +0,0 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef COGL_HAS_GLX_SUPPORT
#include <GL/glx.h>
#endif
#include "cogl-context-private.h"
#include "cogl-feature-private.h"
/* Define a set of arrays containing the functions required from GL
for each winsys feature */
#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
feature_flags, feature_flags_private) \
static const CoglFeatureFunction \
cogl_winsys_feature_ ## name ## _funcs[] = {
#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
{ G_STRINGIFY (name), G_STRUCT_OFFSET (CoglContext, winsys.pf_ ## name) },
#define COGL_WINSYS_FEATURE_END() \
{ NULL, 0 }, \
};
#include "cogl-winsys-feature-functions.h"
/* Define an array of features */
#undef COGL_WINSYS_FEATURE_BEGIN
#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
feature_flags, feature_flags_private) \
{ 255, 255, namespaces, extension_names, \
feature_flags, feature_flags_private, \
cogl_winsys_feature_ ## name ## _funcs },
#undef COGL_WINSYS_FEATURE_FUNCTION
#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)
#undef COGL_WINSYS_FEATURE_END
#define COGL_WINSYS_FEATURE_END()
static const CoglFeatureData cogl_winsys_feature_data[] =
{
#include "cogl-winsys-feature-functions.h"
/* This stub is just here so that if the header is empty then we
won't end up declaring an empty array */
{ 0, }
};
#define COGL_WINSYS_N_FEATURES (G_N_ELEMENTS (cogl_winsys_feature_data) - 1)
static const char *
_cogl_get_winsys_extensions (void)
{
#ifdef COGL_HAS_GLX_SUPPORT
Display *display = _cogl_xlib_get_display ();
return glXQueryExtensionsString (display, DefaultScreen (display));
#else
return "";
#endif
}
static void
_cogl_winsys_features_init (CoglContext *context)
{
CoglWinsysFeatureFlags flags = 0;
const char *extensions = _cogl_get_winsys_extensions ();
int i;
for (i = 0; i < COGL_WINSYS_N_FEATURES; i++)
if (_cogl_feature_check ("GLX", cogl_winsys_feature_data + i, 0, 0,
extensions))
flags |= cogl_winsys_feature_data[i].feature_flags;
context->winsys.feature_flags = flags;
}
void
_cogl_create_context_winsys (CoglContext *context)
{
#ifdef COGL_HAS_XLIB_SUPPORT
{
Display *display = _cogl_xlib_get_display ();
int damage_error;
/* Check whether damage events are supported on this display */
if (!XDamageQueryExtension (display,
&context->winsys.damage_base,
&damage_error))
context->winsys.damage_base = -1;
context->winsys.event_filters = NULL;
context->winsys.trap_state = NULL;
}
#endif
#ifdef COGL_HAS_GLX_SUPPORT
{
int i;
for (i = 0; i < COGL_WINSYS_N_CACHED_CONFIGS; i++)
context->winsys.glx_cached_configs[i].depth = -1;
context->winsys.rectangle_state = COGL_WINSYS_RECTANGLE_STATE_UNKNOWN;
}
#endif
_cogl_winsys_features_init (context);
}
#ifdef COGL_HAS_XLIB_SUPPORT
#include "cogl-xlib.h"
static void
free_xlib_filter_closure (gpointer data, gpointer user_data)
{
g_slice_free (CoglXlibFilterClosure, data);
}
#endif
void
_cogl_destroy_context_winsys (CoglContext *context)
{
#ifdef COGL_HAS_XLIB_SUPPORT
g_slist_foreach (context->winsys.event_filters,
free_xlib_filter_closure, NULL);
g_slist_free (context->winsys.event_filters);
#endif
}

View File

@ -1,118 +0,0 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef __COGL_CONTEXT_WINSYS_H
#define __COGL_CONTEXT_WINSYS_H
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/extensions/Xdamage.h>
#include <X11/Xlib.h>
#endif
#ifdef COGL_HAS_GLX_SUPPORT
#include <GL/glx.h>
#endif
typedef enum
{
COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP = 1
} CoglWinsysFeatureFlags;
#ifdef COGL_HAS_XLIB_SUPPORT
typedef struct _CoglXlibTrapState CoglXlibTrapState;
struct _CoglXlibTrapState
{
/* These values are intended to be internal to
_cogl_xlib_{un,}trap_errors but they need to be in the header so
that the struct can be allocated on the stack */
int (* old_error_handler) (Display *, XErrorEvent *);
int trapped_error_code;
CoglXlibTrapState *old_state;
};
#endif /* COGL_HAS_XLIB_SUPPORT */
#ifdef COGL_HAS_GLX_SUPPORT
typedef struct
{
/* This will be -1 if there is no cached config in this slot */
int depth;
gboolean found;
GLXFBConfig fb_config;
gboolean can_mipmap;
} CoglWinsysCachedConfig;
#define COGL_WINSYS_N_CACHED_CONFIGS 3
typedef enum
{
COGL_WINSYS_RECTANGLE_STATE_UNKNOWN,
COGL_WINSYS_RECTANGLE_STATE_DISABLE,
COGL_WINSYS_RECTANGLE_STATE_ENABLE
} CoglWinsysRectangleState;
#endif /* COGL_HAS_GLX_SUPPORT */
typedef struct
{
/* These are specific to winsys backends supporting Xlib. This
should probably eventually be moved into a separate file specific
to Xlib when Cogl gains a more complete winsys abstraction */
#ifdef COGL_HAS_XLIB_SUPPORT
/* This will be -1 if the damage extension is not support, or it
will be the event number offset for damage events if it is */
int damage_base;
/* List of callback functions that will be given every Xlib event */
GSList *event_filters;
/* Current top of the XError trap state stack. The actual memory for
these is expected to be allocated on the stack by the caller */
CoglXlibTrapState *trap_state;
#endif
#ifdef COGL_HAS_GLX_SUPPORT
CoglWinsysCachedConfig glx_cached_configs[COGL_WINSYS_N_CACHED_CONFIGS];
/* Whether the texture rectangle extension should be used */
CoglWinsysRectangleState rectangle_state;
#endif
/* Function pointers for winsys specific extensions */
#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e)
#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
ret (APIENTRY * pf_ ## name) args;
#define COGL_WINSYS_FEATURE_END()
#include "cogl-winsys-feature-functions.h"
#undef COGL_WINSYS_FEATURE_BEGIN
#undef COGL_WINSYS_FEATURE_FUNCTION
#undef COGL_WINSYS_FEATURE_END
CoglWinsysFeatureFlags feature_flags;
} CoglContextWinsys;
#endif /* __COGL_CONTEXT_WINSYS_H */

View File

@ -42,7 +42,11 @@
#include "cogl-texture-rectangle-private.h"
#include "cogl-context-private.h"
#include "cogl-handle.h"
#include "cogl-winsys-xlib.h"
#if COGL_HAS_GLX_SUPPORT
#include "cogl-display-glx-private.h"
#include "cogl-renderer-private.h"
#include "cogl-renderer-glx-private.h"
#endif
#include "cogl-pipeline-opengl-private.h"
#include <X11/Xlib.h>
@ -55,9 +59,6 @@
#include <string.h>
#include <math.h>
#define glXBindTexImage ctx->winsys.pf_glXBindTexImage
#define glXReleaseTexImage ctx->winsys.pf_glXReleaseTexImage
static void _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap);
COGL_TEXTURE_DEFINE (TexturePixmapX11, texture_pixmap_x11);
@ -112,7 +113,7 @@ process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
display = _cogl_xlib_get_display ();
display = cogl_xlib_get_display ();
COGL_NOTE (TEXTURE_PIXMAP, "Damage event received for %p", tex_pixmap);
@ -206,10 +207,12 @@ static CoglXlibFilterReturn
_cogl_texture_pixmap_x11_filter (XEvent *event, gpointer data)
{
CoglTexturePixmapX11 *tex_pixmap = data;
int damage_base;
_COGL_GET_CONTEXT (ctxt, COGL_XLIB_FILTER_CONTINUE);
if (event->type == ctxt->winsys.damage_base + XDamageNotify)
damage_base = _cogl_xlib_get_damage_base ();
if (event->type == damage_base + XDamageNotify)
{
XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) event;
@ -228,26 +231,28 @@ get_fbconfig_for_depth (unsigned int depth,
gboolean *can_mipmap_ret)
{
GLXFBConfig *fbconfigs;
int n_elements, i;
Display *dpy;
int db, stencil, alpha, mipmap, rgba, value;
int spare_cache_slot = 0;
gboolean found = FALSE;
int n_elements, i;
Display *dpy;
int db, stencil, alpha, mipmap, rgba, value;
int spare_cache_slot = 0;
gboolean found = FALSE;
CoglDisplayGLX *glx_display;
_COGL_GET_CONTEXT (ctxt, FALSE);
glx_display = ctxt->display->winsys;
/* Check if we've already got a cached config for this depth */
for (i = 0; i < COGL_WINSYS_N_CACHED_CONFIGS; i++)
if (ctxt->winsys.glx_cached_configs[i].depth == -1)
for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
if (glx_display->glx_cached_configs[i].depth == -1)
spare_cache_slot = i;
else if (ctxt->winsys.glx_cached_configs[i].depth == depth)
else if (glx_display->glx_cached_configs[i].depth == depth)
{
*fbconfig_ret = ctxt->winsys.glx_cached_configs[i].fb_config;
*can_mipmap_ret = ctxt->winsys.glx_cached_configs[i].can_mipmap;
return ctxt->winsys.glx_cached_configs[i].found;
*fbconfig_ret = glx_display->glx_cached_configs[i].fb_config;
*can_mipmap_ret = glx_display->glx_cached_configs[i].can_mipmap;
return glx_display->glx_cached_configs[i].found;
}
dpy = _cogl_xlib_get_display ();
dpy = cogl_xlib_get_display ();
fbconfigs = glXGetFBConfigs (dpy, DefaultScreen (dpy),
&n_elements);
@ -349,10 +354,10 @@ get_fbconfig_for_depth (unsigned int depth,
if (n_elements)
XFree (fbconfigs);
ctxt->winsys.glx_cached_configs[spare_cache_slot].depth = depth;
ctxt->winsys.glx_cached_configs[spare_cache_slot].found = found;
ctxt->winsys.glx_cached_configs[spare_cache_slot].fb_config = *fbconfig_ret;
ctxt->winsys.glx_cached_configs[spare_cache_slot].can_mipmap = mipmap;
glx_display->glx_cached_configs[spare_cache_slot].depth = depth;
glx_display->glx_cached_configs[spare_cache_slot].found = found;
glx_display->glx_cached_configs[spare_cache_slot].fb_config = *fbconfig_ret;
glx_display->glx_cached_configs[spare_cache_slot].can_mipmap = mipmap;
return found;
}
@ -362,7 +367,7 @@ should_use_rectangle (void)
{
_COGL_GET_CONTEXT (ctxt, FALSE);
if (ctxt->winsys.rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN)
if (ctxt->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN)
{
if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
{
@ -378,7 +383,7 @@ should_use_rectangle (void)
the env var is set to 'allow' or not set and NPOTs textures
are not available */
ctxt->winsys.rectangle_state =
ctxt->rectangle_state =
cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) ?
COGL_WINSYS_RECTANGLE_STATE_DISABLE :
COGL_WINSYS_RECTANGLE_STATE_ENABLE;
@ -389,10 +394,10 @@ should_use_rectangle (void)
(rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE")))
{
if (g_ascii_strcasecmp (rect_env, "force") == 0)
ctxt->winsys.rectangle_state =
ctxt->rectangle_state =
COGL_WINSYS_RECTANGLE_STATE_ENABLE;
else if (g_ascii_strcasecmp (rect_env, "disable") == 0)
ctxt->winsys.rectangle_state =
ctxt->rectangle_state =
COGL_WINSYS_RECTANGLE_STATE_DISABLE;
else if (g_ascii_strcasecmp (rect_env, "allow"))
g_warning ("Unknown value for COGL_PIXMAP_TEXTURE_RECTANGLE, "
@ -400,10 +405,10 @@ should_use_rectangle (void)
}
}
else
ctxt->winsys.rectangle_state = COGL_WINSYS_RECTANGLE_STATE_DISABLE;
ctxt->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_DISABLE;
}
return ctxt->winsys.rectangle_state == COGL_WINSYS_RECTANGLE_STATE_ENABLE;
return ctxt->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_ENABLE;
}
static void
@ -425,11 +430,10 @@ try_create_glx_pixmap (CoglTexturePixmapX11 *tex_pixmap,
tex_pixmap->pixmap_bound = FALSE;
tex_pixmap->glx_pixmap = None;
if ((ctxt->winsys.feature_flags &
COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP) == 0)
if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP))
return;
dpy = _cogl_xlib_get_display ();
dpy = cogl_xlib_get_display ();
if (!get_fbconfig_for_depth (tex_pixmap->depth, &fb_config,
&tex_pixmap->glx_can_mipmap))
@ -507,7 +511,7 @@ set_damage_object_internal (CoglTexturePixmapX11 *tex_pixmap,
if (tex_pixmap->damage_owned)
{
XDamageDestroy (_cogl_xlib_get_display (), tex_pixmap->damage);
XDamageDestroy (cogl_xlib_get_display (), tex_pixmap->damage);
tex_pixmap->damage_owned = FALSE;
}
}
@ -524,12 +528,13 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
gboolean automatic_updates)
{
CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1);
Display *display = _cogl_xlib_get_display ();
Display *display = cogl_xlib_get_display ();
Window pixmap_root_window;
int pixmap_x, pixmap_y;
unsigned int pixmap_border_width;
CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
XWindowAttributes window_attributes;
int damage_base;
_COGL_GET_CONTEXT (ctxt, COGL_INVALID_HANDLE);
@ -565,7 +570,8 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
/* If automatic updates are requested and the Xlib connection
supports damage events then we'll register a damage object on the
pixmap */
if (automatic_updates && ctxt->winsys.damage_base >= 0)
damage_base = _cogl_xlib_get_damage_base ();
if (automatic_updates && damage_base >= 0)
{
Damage damage = XDamageCreate (display,
pixmap,
@ -601,7 +607,7 @@ try_alloc_shm (CoglTexturePixmapX11 *tex_pixmap)
XImage *dummy_image;
Display *display;
display = _cogl_xlib_get_display ();
display = cogl_xlib_get_display ();
if (!XShmQueryExtension (display))
return;
@ -709,13 +715,15 @@ cogl_texture_pixmap_x11_set_damage_object (CoglHandle handle,
report_level)
{
CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
int damage_base;
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
if (!cogl_is_texture_pixmap_x11 (tex_pixmap))
return;
if (ctxt->winsys.damage_base >= 0)
damage_base = _cogl_xlib_get_damage_base ();
if (damage_base >= 0)
set_damage_object_internal (tex_pixmap, damage, report_level);
}
@ -728,7 +736,7 @@ _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
int src_x, src_y;
int x, y, width, height;
display = _cogl_xlib_get_display ();
display = cogl_xlib_get_display ();
/* If the damage region is empty then there's nothing to do */
if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1)
@ -889,12 +897,15 @@ _cogl_texture_pixmap_x11_free_glx_pixmap (CoglTexturePixmapX11 *tex_pixmap)
if (tex_pixmap->glx_pixmap)
{
CoglXlibTrapState trap_state;
CoglRendererGLX *glx_renderer;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
glx_renderer = ctx->display->renderer->winsys;
if (tex_pixmap->pixmap_bound)
glXReleaseTexImage (_cogl_xlib_get_display (), tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT);
glx_renderer->pf_glXReleaseTexImage (cogl_xlib_get_display (),
tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT);
/* FIXME - we need to trap errors and synchronize here because
* of ordering issues between the XPixmap destruction and the
@ -913,8 +924,8 @@ _cogl_texture_pixmap_x11_free_glx_pixmap (CoglTexturePixmapX11 *tex_pixmap)
* http://bugzilla.clutter-project.org/show_bug.cgi?id=2324
*/
_cogl_xlib_trap_errors (&trap_state);
glXDestroyPixmap (_cogl_xlib_get_display (), tex_pixmap->glx_pixmap);
XSync (_cogl_xlib_get_display (), False);
glXDestroyPixmap (cogl_xlib_get_display (), tex_pixmap->glx_pixmap);
XSync (cogl_xlib_get_display (), False);
_cogl_xlib_untrap_errors (&trap_state);
tex_pixmap->glx_pixmap = None;
@ -927,8 +938,10 @@ _cogl_texture_pixmap_x11_update_glx_texture (CoglTexturePixmapX11 *tex_pixmap,
gboolean needs_mipmap)
{
gboolean ret = TRUE;
CoglRendererGLX *glx_renderer;
_COGL_GET_CONTEXT (ctx, FALSE);
glx_renderer = ctx->display->renderer->winsys;
/* If we don't have a GLX pixmap then fallback */
if (tex_pixmap->glx_pixmap == None)
@ -1031,14 +1044,14 @@ _cogl_texture_pixmap_x11_update_glx_texture (CoglTexturePixmapX11 *tex_pixmap,
GE( _cogl_bind_gl_texture_transient (gl_target, gl_handle, FALSE) );
if (tex_pixmap->pixmap_bound)
glXReleaseTexImage (_cogl_xlib_get_display (),
tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT);
glx_renderer->pf_glXReleaseTexImage (cogl_xlib_get_display (),
tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT);
glXBindTexImage (_cogl_xlib_get_display (),
tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT,
NULL);
glx_renderer->pf_glXBindTexImage (cogl_xlib_get_display (),
tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT,
NULL);
/* According to the recommended usage in the spec for
GLX_EXT_texture_pixmap we should release the texture after
@ -1373,7 +1386,7 @@ _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
if (tex_pixmap->shm_info.shmid != -1)
{
XShmDetach (_cogl_xlib_get_display (), &tex_pixmap->shm_info);
XShmDetach (cogl_xlib_get_display (), &tex_pixmap->shm_info);
shmdt (tex_pixmap->shm_info.shmaddr);
shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
}

View File

@ -1,45 +0,0 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
/* This can be included multiple times with different definitions for
the COGL_WINSYS_FEATURE_* functions */
#ifdef COGL_HAS_GLX_SUPPORT
COGL_WINSYS_FEATURE_BEGIN (texture_from_pixmap,
"EXT\0",
"texture_from_pixmap\0",
COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP,
0)
COGL_WINSYS_FEATURE_FUNCTION (void, glXBindTexImage,
(Display *display,
GLXDrawable drawable,
int buffer,
int *attribList))
COGL_WINSYS_FEATURE_FUNCTION (void, glXReleaseTexImage,
(Display *display,
GLXDrawable drawable,
int buffer))
COGL_WINSYS_FEATURE_END ()
#endif

View File

@ -0,0 +1,105 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
*
* 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, see
* <http://www.gnu.org/licenses/>.
*
*
*/
/* This can be included multiple times with different definitions for
* the COGL_WINSYS_FEATURE_* functions.
*/
/* Macro prototypes:
* COGL_WINSYS_FEATURE_BEGIN (name, namespaces, extension_names,
* implied_public_feature_flags,
* implied_private_feature_flags,
* implied_winsys_feature)
* COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name,
* (arguments))
* ...
* COGL_WINSYS_FEATURE_END ()
*
* Note: You can list multiple namespace and extension names if the
* corresponding _FEATURE_FUNCTIONS have the same semantics accross
* the different extension variants.
*
* XXX: NB: Don't add a trailing semicolon when using these macros
*/
COGL_WINSYS_FEATURE_BEGIN (texture_from_pixmap,
"EXT\0",
"texture_from_pixmap\0",
0,
0,
COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP)
COGL_WINSYS_FEATURE_FUNCTION (void, glXBindTexImage,
(Display *display,
GLXDrawable drawable,
int buffer,
int *attribList))
COGL_WINSYS_FEATURE_FUNCTION (void, glXReleaseTexImage,
(Display *display,
GLXDrawable drawable,
int buffer))
COGL_WINSYS_FEATURE_END ()
COGL_WINSYS_FEATURE_BEGIN (video_sync,
"SGI\0",
"video_sync\0",
0,
0,
COGL_WINSYS_FEATURE_VBLANK_COUNTER)
COGL_WINSYS_FEATURE_FUNCTION (int, glXGetVideoSync,
(unsigned int *count))
COGL_WINSYS_FEATURE_FUNCTION (int, glXWaitVideoSync,
(int divisor,
int remainder,
unsigned int *count))
COGL_WINSYS_FEATURE_END ()
COGL_WINSYS_FEATURE_BEGIN (swap_control,
"SGI\0",
"swap_control\0",
0,
0,
COGL_WINSYS_FEATURE_SWAP_THROTTLE)
COGL_WINSYS_FEATURE_FUNCTION (int, glXSwapInterval,
(int interval))
COGL_WINSYS_FEATURE_END ()
COGL_WINSYS_FEATURE_BEGIN (copy_sub_buffer,
"MESA\0",
"copy_sub_buffer\0",
0,
0,
0)
COGL_WINSYS_FEATURE_FUNCTION (void, glXCopySubBuffer,
(Display *dpy,
GLXDrawable drawable,
int x, int y, int width, int height))
COGL_WINSYS_FEATURE_END ()
COGL_WINSYS_FEATURE_BEGIN (swap_event,
"INTEL\0",
"swap_event\0",
0,
0,
COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT)
COGL_WINSYS_FEATURE_END ()

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,95 @@
#ifndef __COGL_WINSYS_PRIVATE_H
#define __COGL_WINSYS_PRIVATE_H
#include "cogl-framebuffer-private.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xutil.h>
#endif
GQuark
_cogl_winsys_error_quark (void);
#define COGL_WINSYS_ERROR (_cogl_winsys_error_quark ())
typedef enum { /*< prefix=COGL_WINSYS_ERROR >*/
COGL_WINSYS_ERROR_INIT,
COGL_WINSYS_ERROR_CREATE_CONTEXT,
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
} CoglWinsysError;
typedef enum
{
COGL_WINSYS_RECTANGLE_STATE_UNKNOWN,
COGL_WINSYS_RECTANGLE_STATE_DISABLE,
COGL_WINSYS_RECTANGLE_STATE_ENABLE
} CoglWinsysRectangleState;
CoglFuncPtr
_cogl_winsys_get_proc_address (const char *name);
gboolean
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
GError **error);
void
_cogl_winsys_renderer_disconnect (CoglRenderer *renderer);
gboolean
_cogl_winsys_display_setup (CoglDisplay *display,
GError **error);
void
_cogl_winsys_display_destroy (CoglDisplay *display);
gboolean
_cogl_winsys_context_init (CoglContext *context, GError **error);
void
_cogl_winsys_context_deinit (CoglContext *context);
gboolean
_cogl_winsys_has_feature (CoglWinsysFeature feature);
#ifdef COGL_HAS_XLIB_SUPPORT
XVisualInfo *
_cogl_winsys_xlib_get_visual_info (void);
#endif
gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
GError **error);
void
_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen);
void
_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen);
void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen);
void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
int *rectangles,
int n_rectangles);
void
_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen);
guint32
_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen);
guint32
_cogl_winsys_get_vsync_counter (void);
unsigned int
_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
CoglSwapBuffersNotify callback,
void *user_data);
void
_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
unsigned int id);
#endif /* __COGL_WINSYS_PRIVATE_H */

View File

@ -0,0 +1,114 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2010 Intel Corporation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl-framebuffer-private.h"
/* This provides a stub winsys implementation for when Clutter still handles
* creating an OpenGL context. This is useful so we don't have to guard all
* calls into the winsys layer with #ifdef COGL_HAS_FULL_WINSYS
*/
void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
{
}
void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
int *rectangles,
int n_rectangles)
{
}
void
_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
{
}
unsigned int
_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
CoglSwapBuffersNotify callback,
void *user_data)
{
g_assert (0);
return 0;
}
void
_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
unsigned int id)
{
g_assert (0);
}
#ifdef COGL_HAS_XLIB_SUPPORT
XVisualInfo *
_cogl_winsys_xlib_get_visual_info (void)
{
g_assert (0);
return NULL;
}
#endif
gboolean
_cogl_winsys_has_feature (CoglWinsysFeature feature)
{
g_assert (0);
return FALSE;
}
#ifdef COGL_HAS_X11_SUPPORT
guint32
_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
{
g_assert (0);
return 0;
}
#endif
gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
GError **error)
{
return TRUE;
}
void
_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
{
}
void
_cogl_winsys_context_deinit (CoglContext *context)
{
}

View File

@ -0,0 +1,36 @@
/*
* Cogl
*
* An object oriented GL/GLES Abstraction/Utility Layer
*
* Copyright (C) 2007,2008,2009,2010 Intel Corporation.
*
* 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, see
* <http://www.gnu.org/licenses/>.
*
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl.h"
GQuark
_cogl_winsys_error_quark (void)
{
return g_quark_from_static_string ("cogl-winsys-error-quark");
}

View File

@ -49,6 +49,7 @@
#include "clutter-stage-private.h"
#include "cogl/cogl.h"
#include "cogl/cogl-internal.h"
#define clutter_backend_glx_get_type _clutter_backend_glx_get_type
@ -57,12 +58,15 @@ G_DEFINE_TYPE (ClutterBackendGLX, clutter_backend_glx, CLUTTER_TYPE_BACKEND_X11)
/* singleton object */
static ClutterBackendGLX *backend_singleton = NULL;
static gchar *clutter_vblank_name = NULL;
static gchar *clutter_vblank = NULL;
G_CONST_RETURN gchar*
_clutter_backend_glx_get_vblank_method (void)
_clutter_backend_glx_get_vblank (void)
{
return clutter_vblank_name;
if (clutter_vblank && strcmp (clutter_vblank, "0") == 0)
return "none";
else
return clutter_vblank;
}
static gboolean
@ -76,7 +80,7 @@ clutter_backend_glx_pre_parse (ClutterBackend *backend,
env_string = g_getenv ("CLUTTER_VBLANK");
if (env_string)
{
clutter_vblank_name = g_strdup (env_string);
clutter_vblank = g_strdup (env_string);
env_string = NULL;
}
@ -87,42 +91,12 @@ static gboolean
clutter_backend_glx_post_parse (ClutterBackend *backend,
GError **error)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
ClutterBackendClass *parent_class =
CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
int glx_major, glx_minor;
if (!parent_class->post_parse (backend, error))
return FALSE;
if (!glXQueryExtension (backend_x11->xdpy,
&backend_glx->error_base,
&backend_glx->event_base))
{
g_set_error_literal (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"XServer appears to lack the required GLX support");
return FALSE;
}
/* XXX: Technically we should require >= GLX 1.3 support but for a long
* time Mesa has exported a hybrid GLX, exporting extensions specified
* to require GLX 1.3, but still reporting 1.2 via glXQueryVersion. */
glx_major = 1;
glx_minor = 2;
if (!glXQueryVersion (backend_x11->xdpy, &glx_major, &glx_minor) ||
!(glx_major == 1 && glx_minor >= 2))
{
g_set_error (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"XServer appears to lack the required GLX "
"1.2 support (%d.%d reported)",
glx_major, glx_minor);
return FALSE;
}
return TRUE;
}
@ -130,8 +104,9 @@ static const GOptionEntry entries[] =
{
{ "vblank", 0,
0,
G_OPTION_ARG_STRING, &clutter_vblank_name,
N_("VBlank method to be used (none, dri or glx)"), "METHOD"
G_OPTION_ARG_STRING, &clutter_vblank,
N_("Set to 'none' or '0' to disable throttling "
"framerate to vblank"), "OPTION"
},
{ NULL }
};
@ -160,32 +135,20 @@ clutter_backend_glx_finalize (GObject *gobject)
static void
clutter_backend_glx_dispose (GObject *gobject)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (gobject);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
/* Unrealize all shaders, since the GL context is going away */
/* XXX: Why isn't this done in
* clutter-backend.c:clutter_backend_dispose ?
*/
_clutter_shader_release_all ();
if (backend_glx->gl_context)
{
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
glXDestroyContext (backend_x11->xdpy, backend_glx->gl_context);
backend_glx->gl_context = NULL;
}
if (backend_glx->dummy_glxwin)
{
glXDestroyWindow (backend_x11->xdpy, backend_glx->dummy_glxwin);
backend_glx->dummy_glxwin = None;
}
if (backend_glx->dummy_xwin)
{
XDestroyWindow (backend_x11->xdpy, backend_glx->dummy_xwin);
backend_glx->dummy_xwin = None;
}
/* We chain up before disposing our CoglContext so that we will
* destroy all of the stages first. Otherwise the actors may try to
* make Cogl calls during destruction which would cause a crash */
G_OBJECT_CLASS (clutter_backend_glx_parent_class)->dispose (gobject);
cogl_object_unref (backend->cogl_context);
}
static GObject *
@ -212,197 +175,46 @@ clutter_backend_glx_constructor (GType gtype,
return g_object_ref (backend_singleton);
}
static gboolean
check_vblank_env (const char *name)
{
if (clutter_vblank_name && !g_ascii_strcasecmp (clutter_vblank_name, name))
return TRUE;
return FALSE;
}
static ClutterFeatureFlags
clutter_backend_glx_get_features (ClutterBackend *backend)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
ClutterBackendClass *parent_class;
const gchar *glx_extensions = NULL;
const gchar *gl_extensions = NULL;
ClutterFeatureFlags flags;
gboolean use_dri = FALSE;
parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
flags = parent_class->get_features (backend);
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
/* this will make sure that the GL context exists */
g_assert (backend_glx->gl_context != NULL);
g_assert (glXGetCurrentDrawable () != None);
CLUTTER_NOTE (BACKEND,
"Checking features\n"
" GL_VENDOR: %s\n"
" GL_RENDERER: %s\n"
" GL_VERSION: %s\n"
" GL_EXTENSIONS: %s",
glGetString (GL_VENDOR),
glGetString (GL_RENDERER),
glGetString (GL_VERSION),
glGetString (GL_EXTENSIONS));
glx_extensions =
glXQueryExtensionsString (clutter_x11_get_default_display (),
clutter_x11_get_default_screen ());
CLUTTER_NOTE (BACKEND, " GLX Extensions: %s", glx_extensions);
gl_extensions = (const gchar *)glGetString (GL_EXTENSIONS);
/* When using glBlitFramebuffer or glXCopySubBufferMESA for sub stage
* redraws, we cannot rely on glXSwapIntervalSGI to throttle the blits
* so we need to resort to manually synchronizing with the vblank so we
* always check for the video_sync extension...
*/
if (_cogl_check_extension ("GLX_SGI_video_sync", glx_extensions) &&
/* Note: the GLX_SGI_video_sync spec explicitly states this extension
* only works for direct contexts. */
glXIsDirect (clutter_x11_get_default_display (),
backend_glx->gl_context))
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN))
{
backend_glx->get_video_sync =
(GetVideoSyncProc) cogl_get_proc_address ("glXGetVideoSyncSGI");
backend_glx->wait_video_sync =
(WaitVideoSyncProc) cogl_get_proc_address ("glXWaitVideoSyncSGI");
CLUTTER_NOTE (BACKEND, "Cogl supports multiple onscreen framebuffers");
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
}
else
{
CLUTTER_NOTE (BACKEND, "Cogl only supports one onscreen framebuffer");
flags |= CLUTTER_FEATURE_STAGE_STATIC;
}
use_dri = check_vblank_env ("dri");
/* First check for explicit disabling or it set elsewhere (eg NVIDIA) */
if (check_vblank_env ("none"))
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE))
{
CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request");
goto vblank_setup_done;
}
if (g_getenv ("__GL_SYNC_TO_VBLANK") != NULL)
{
backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers throttling");
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
}
else
CLUTTER_NOTE (BACKEND, "Cogl doesn't support swap buffers throttling");
CLUTTER_NOTE (BACKEND, "Using __GL_SYNC_TO_VBLANK hint");
goto vblank_setup_done;
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
{
CLUTTER_NOTE (BACKEND, "Cogl supports swap buffers complete events");
flags |= CLUTTER_FEATURE_SWAP_EVENTS;
}
/* We try two GL vblank syncing mechanisms.
* glXSwapIntervalSGI is tried first, then glXGetVideoSyncSGI.
*
* glXSwapIntervalSGI is known to work with Mesa and in particular
* the Intel drivers. glXGetVideoSyncSGI has serious problems with
* Intel drivers causing terrible frame rate so it only tried as a
* fallback.
*
* How well glXGetVideoSyncSGI works with other driver (ATI etc) needs
* to be investigated. glXGetVideoSyncSGI on ATI at least seems to have
* no effect.
*/
if (!use_dri &&
_cogl_check_extension ("GLX_SGI_swap_control", glx_extensions))
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION))
{
backend_glx->swap_interval =
(SwapIntervalProc) cogl_get_proc_address ("glXSwapIntervalSGI");
CLUTTER_NOTE (BACKEND, "attempting glXSwapIntervalSGI vblank setup");
if (backend_glx->swap_interval != NULL &&
backend_glx->swap_interval (1) == 0)
{
backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI setup success");
#ifdef GLX_INTEL_swap_event
/* GLX_INTEL_swap_event allows us to avoid blocking the CPU
* while we wait for glXSwapBuffers to complete, and instead
* we get an X event notifying us of completion...
*/
if (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_SWAP_EVENTS) &&
_cogl_check_extension ("GLX_INTEL_swap_event", glx_extensions))
{
flags |= CLUTTER_FEATURE_SWAP_EVENTS;
}
#endif /* GLX_INTEL_swap_event */
goto vblank_setup_done;
}
CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI vblank setup failed");
}
if (!use_dri &&
!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK) &&
_cogl_check_extension ("GLX_SGI_video_sync", glx_extensions))
{
CLUTTER_NOTE (BACKEND, "attempting glXGetVideoSyncSGI vblank setup");
if ((backend_glx->get_video_sync != NULL) &&
(backend_glx->wait_video_sync != NULL))
{
CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup success");
backend_glx->vblank_type = CLUTTER_VBLANK_GLX;
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
goto vblank_setup_done;
}
CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed");
}
#ifdef __linux__
/*
* DRI is really an extreme fallback -rumoured to work with Via chipsets
*/
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
{
CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup");
backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR);
if (backend_glx->dri_fd >= 0)
{
CLUTTER_NOTE (BACKEND, "DRI vblank setup success");
backend_glx->vblank_type = CLUTTER_VBLANK_DRI;
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
goto vblank_setup_done;
}
CLUTTER_NOTE (BACKEND, "DRI vblank setup failed");
}
#endif /* __linux__ */
CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");
vblank_setup_done:
if (_cogl_check_extension ("GLX_MESA_copy_sub_buffer", glx_extensions))
{
backend_glx->copy_sub_buffer =
(CopySubBufferProc) cogl_get_proc_address ("glXCopySubBufferMESA");
CLUTTER_NOTE (BACKEND, "Cogl supports swapping buffer regions");
backend_glx->can_blit_sub_buffer = TRUE;
backend_glx->blit_sub_buffer_is_synchronized = TRUE;
}
else if (_cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions))
{
CLUTTER_NOTE (BACKEND,
"Using glBlitFramebuffer fallback for sub_buffer copies");
backend_glx->blit_framebuffer =
(BlitFramebufferProc) cogl_get_proc_address ("glBlitFramebuffer");
backend_glx->can_blit_sub_buffer = TRUE;
backend_glx->blit_sub_buffer_is_synchronized = FALSE;
}
CLUTTER_NOTE (BACKEND, "backend features checked");
@ -410,375 +222,77 @@ vblank_setup_done:
return flags;
}
/* It seems the GLX spec never defined an invalid GLXFBConfig that
* we could overload as an indication of error, so we have to return
* an explicit boolean status. */
gboolean
_clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_glx,
GLXFBConfig *config)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx);
GLXFBConfig *configs = NULL;
gboolean use_argb = clutter_x11_get_use_argb_visual ();
int n_configs, i;
static const int attributes[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, GL_TRUE,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_ALPHA_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_STENCIL_SIZE, 1,
None
};
if (backend_x11->xdpy == NULL || backend_x11->xscreen == NULL)
return FALSE;
/* If we don't already have a cached config then try to get one */
if (!backend_glx->found_fbconfig)
{
CLUTTER_NOTE (BACKEND,
"Retrieving GL fbconfig, dpy: %p, xscreen; %p (%d)",
backend_x11->xdpy,
backend_x11->xscreen,
backend_x11->xscreen_num);
configs = glXChooseFBConfig (backend_x11->xdpy,
backend_x11->xscreen_num,
attributes,
&n_configs);
if (configs)
{
if (use_argb)
{
for (i = 0; i < n_configs; i++)
{
XVisualInfo *vinfo;
vinfo = glXGetVisualFromFBConfig (backend_x11->xdpy,
configs[i]);
if (vinfo == NULL)
continue;
if (vinfo->depth == 32 &&
(vinfo->red_mask == 0xff0000 &&
vinfo->green_mask == 0x00ff00 &&
vinfo->blue_mask == 0x0000ff))
{
CLUTTER_NOTE (BACKEND,
"Found an ARGB FBConfig [index:%d]",
i);
backend_glx->found_fbconfig = TRUE;
backend_glx->fbconfig = configs[i];
goto out;
}
}
/* If we make it here then we didn't find an RGBA config so
we'll fall back to using an RGB config */
CLUTTER_NOTE (BACKEND, "ARGB visual requested, but none found");
}
if (n_configs >= 1)
{
CLUTTER_NOTE (BACKEND, "Using the first available FBConfig");
backend_glx->found_fbconfig = TRUE;
backend_glx->fbconfig = configs[0];
}
out:
XFree (configs);
}
}
if (G_LIKELY (backend_glx->found_fbconfig))
{
*config = backend_glx->fbconfig;
return TRUE;
}
return FALSE;
}
void
_clutter_backend_glx_blit_sub_buffer (ClutterBackendGLX *backend_glx,
GLXDrawable drawable,
int x,
int y,
int width,
int height)
{
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx);
if (backend_glx->copy_sub_buffer)
{
backend_glx->copy_sub_buffer (backend_x11->xdpy, drawable,
x, y, width, height);
}
else if (backend_glx->blit_framebuffer)
{
glDrawBuffer (GL_FRONT);
backend_glx->blit_framebuffer (x, y, x + width, y + height,
x, y, x + width, y + height,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
glDrawBuffer (GL_BACK);
}
/* NB: unlike glXSwapBuffers, glXCopySubBuffer and
* glBlitFramebuffer don't issue an implicit glFlush() so we
* have to flush ourselves if we want the request to complete in
* finite amount of time since otherwise the driver can batch
* the command indefinitely. */
glFlush();
}
static XVisualInfo *
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
GLXFBConfig config;
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
return NULL;
return glXGetVisualFromFBConfig (backend_x11->xdpy, config);
return cogl_clutter_winsys_xlib_get_visual_info ();
}
static gboolean
clutter_backend_glx_create_context (ClutterBackend *backend,
GError **error)
{
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
GLXFBConfig config;
gboolean is_direct;
Window root_xwin;
XSetWindowAttributes attrs;
XVisualInfo *xvisinfo;
Display *xdisplay;
int major;
int minor;
GLXDrawable dummy_drawable;
CoglSwapChain *swap_chain = NULL;
CoglOnscreenTemplate *onscreen_template = NULL;
if (backend_glx->gl_context != NULL)
if (backend->cogl_context)
return TRUE;
xdisplay = clutter_x11_get_default_display ();
root_xwin = clutter_x11_get_root_window ();
backend->cogl_renderer = cogl_renderer_new ();
cogl_renderer_xlib_set_foreign_display (backend->cogl_renderer,
backend_x11->xdpy);
if (!cogl_renderer_connect (backend->cogl_renderer, error))
goto error;
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
{
g_set_error_literal (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to find suitable fbconfig for the GLX context");
return FALSE;
}
swap_chain = cogl_swap_chain_new ();
cogl_swap_chain_set_has_alpha (swap_chain,
clutter_x11_get_use_argb_visual ());
CLUTTER_NOTE (BACKEND, "Creating GLX Context (display: %p)", xdisplay);
onscreen_template = cogl_onscreen_template_new (swap_chain);
cogl_object_unref (swap_chain);
backend_glx->gl_context = glXCreateNewContext (xdisplay,
config,
GLX_RGBA_TYPE,
NULL,
True);
if (backend_glx->gl_context == NULL)
{
g_set_error_literal (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to create suitable GL context");
return FALSE;
}
if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer,
onscreen_template,
error))
goto error;
is_direct = glXIsDirect (xdisplay, backend_glx->gl_context);
backend->cogl_display = cogl_display_new (backend->cogl_renderer,
onscreen_template);
cogl_object_unref (backend->cogl_renderer);
cogl_object_unref (onscreen_template);
CLUTTER_NOTE (GL, "Setting %s context",
is_direct ? "direct"
: "indirect");
_cogl_set_indirect_context (!is_direct);
if (!cogl_display_setup (backend->cogl_display, error))
goto error;
/* COGL assumes that there is always a GL context selected; in order
* to make sure that a GLX context exists and is made current, we use
* a dummy, offscreen override-redirect window to which we can always
* fall back if no stage is available
*
* XXX - we need to do this dance because GLX does not allow creating
* a context and querying it for basic information (even the function
* pointers) unless it's made current to a real Drawable. it should be
* possible to avoid this in future releases of Mesa and X11, but right
* now this is the best solution available.
*/
xvisinfo = glXGetVisualFromFBConfig (xdisplay, config);
if (xvisinfo == NULL)
{
g_set_error_literal (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to retrieve the X11 visual");
return FALSE;
}
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
if (!backend->cogl_context)
goto error;
clutter_x11_trap_x_errors ();
attrs.override_redirect = True;
attrs.colormap = XCreateColormap (xdisplay,
root_xwin,
xvisinfo->visual,
AllocNone);
attrs.border_pixel = 0;
backend_glx->dummy_xwin = XCreateWindow (xdisplay, root_xwin,
-100, -100, 1, 1,
0,
xvisinfo->depth,
CopyFromParent,
xvisinfo->visual,
CWOverrideRedirect | CWColormap | CWBorderPixel,
&attrs);
/* Try and create a GLXWindow to use with extensions dependent on
* GLX versions >= 1.3 that don't accept regular X Windows as GLX
* drawables. */
if (glXQueryVersion (backend_x11->xdpy, &major, &minor) &&
major == 1 && minor >= 3)
{
backend_glx->dummy_glxwin = glXCreateWindow (backend_x11->xdpy,
config,
backend_glx->dummy_xwin,
NULL);
}
if (backend_glx->dummy_glxwin)
dummy_drawable = backend_glx->dummy_glxwin;
else
dummy_drawable = backend_glx->dummy_xwin;
CLUTTER_NOTE (BACKEND, "Selecting dummy 0x%x for the GLX context",
(unsigned int) dummy_drawable);
glXMakeContextCurrent (xdisplay,
dummy_drawable,
dummy_drawable,
backend_glx->gl_context);
XFree (xvisinfo);
if (clutter_x11_untrap_x_errors ())
{
g_set_error_literal (error, CLUTTER_INIT_ERROR,
CLUTTER_INIT_ERROR_BACKEND,
"Unable to select the newly created GLX context");
return FALSE;
}
/* XXX: eventually this should go away but a lot of Cogl code still
* depends on a global default context. */
cogl_set_default_context (backend->cogl_context);
return TRUE;
}
/* TODO: remove this interface in favour of
* _clutter_stage_window_make_current () */
static void
clutter_backend_glx_ensure_context (ClutterBackend *backend,
ClutterStage *stage)
{
ClutterStageWindow *impl;
/* if there is no stage, the stage is being destroyed or it has no
* implementation attached to it then we clear the GL context
*/
if (stage == NULL ||
CLUTTER_ACTOR_IN_DESTRUCTION (stage) ||
((impl = _clutter_stage_get_window (stage)) == NULL))
error:
if (backend->cogl_display)
{
ClutterBackendX11 *backend_x11;
backend_x11 = CLUTTER_BACKEND_X11 (backend);
CLUTTER_NOTE (MULTISTAGE, "Clearing all context");
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
cogl_object_unref (backend->cogl_display);
backend->cogl_display = NULL;
}
else
if (onscreen_template)
cogl_object_unref (onscreen_template);
if (swap_chain)
cogl_object_unref (swap_chain);
if (backend->cogl_renderer)
{
ClutterBackendGLX *backend_glx;
ClutterBackendX11 *backend_x11;
ClutterStageGLX *stage_glx;
ClutterStageX11 *stage_x11;
GLXDrawable drawable;
g_assert (impl != NULL);
stage_glx = CLUTTER_STAGE_GLX (impl);
stage_x11 = CLUTTER_STAGE_X11 (impl);
backend_glx = CLUTTER_BACKEND_GLX (backend);
backend_x11 = CLUTTER_BACKEND_X11 (backend);
drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin;
CLUTTER_NOTE (BACKEND,
"Setting context for stage of type %s, window: 0x%x",
G_OBJECT_TYPE_NAME (impl),
(unsigned int) drawable);
/* no GL context to set */
if (backend_glx->gl_context == NULL)
return;
clutter_x11_trap_x_errors ();
/* we might get here inside the final dispose cycle, so we
* need to handle this gracefully
*/
if (drawable == None)
{
GLXDrawable dummy_drawable;
CLUTTER_NOTE (BACKEND,
"Received a stale stage, clearing all context");
if (backend_glx->dummy_glxwin)
dummy_drawable = backend_glx->dummy_glxwin;
else
dummy_drawable = backend_glx->dummy_xwin;
if (dummy_drawable == None)
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
else
{
glXMakeContextCurrent (backend_x11->xdpy,
dummy_drawable,
dummy_drawable,
backend_glx->gl_context);
}
}
else
{
CLUTTER_NOTE (BACKEND,
"MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p",
backend_x11->xdpy,
(unsigned int) drawable,
stage_x11->is_foreign_xwin ? "foreign" : "native",
backend_glx->gl_context);
glXMakeContextCurrent (backend_x11->xdpy,
drawable,
drawable,
backend_glx->gl_context);
/*
* In case we are using GLX_SGI_swap_control for vblank syncing we need call
* glXSwapIntervalSGI here to make sure that it affects the current drawable.
*/
if (backend_glx->vblank_type == CLUTTER_VBLANK_GLX_SWAP && backend_glx->swap_interval != NULL)
backend_glx->swap_interval (1);
}
if (clutter_x11_untrap_x_errors ())
g_critical ("Unable to make the stage window 0x%x the current "
"GLX drawable",
(unsigned int) drawable);
cogl_object_unref (backend->cogl_renderer);
backend->cogl_renderer = NULL;
}
return FALSE;
}
static ClutterStageWindow *
@ -812,6 +326,16 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
return stage_window;
}
static void
clutter_backend_glx_ensure_context (ClutterBackend *backend,
ClutterStage *stage)
{
ClutterStageGLX *stage_glx =
CLUTTER_STAGE_GLX (_clutter_stage_get_window (stage));
cogl_set_framebuffer (COGL_FRAMEBUFFER (stage_glx->onscreen));
}
static void
clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
{

View File

@ -47,30 +47,11 @@ typedef struct _ClutterBackendGLXClass ClutterBackendGLXClass;
typedef enum ClutterGLXVBlankType {
CLUTTER_VBLANK_NONE = 0,
CLUTTER_VBLANK_GLX_SWAP,
CLUTTER_VBLANK_GLX,
CLUTTER_VBLANK_DRI
CLUTTER_VBLANK_AUTOMATIC_THROTTLE,
CLUTTER_VBLANK_VBLANK_COUNTER,
CLUTTER_VBLANK_MANUAL_WAIT
} ClutterGLXVBlankType;
typedef int (*GetVideoSyncProc) (unsigned int *count);
typedef int (*WaitVideoSyncProc) (int divisor,
int remainder,
unsigned int *count);
typedef int (*SwapIntervalProc) (int interval);
typedef void (*CopySubBufferProc)(Display *dpy,
GLXDrawable drawable,
int x, int y, int width, int height);
typedef void (*BlitFramebufferProc) (GLint srcX0,
GLint srcY0,
GLint srcX1,
GLint srcY1,
GLint dstX0,
GLint dstY0,
GLint dstX1,
GLint dstY1,
GLbitfield mask,
GLenum filter);
struct _ClutterBackendGLX
{
ClutterBackendX11 parent_instance;
@ -78,25 +59,13 @@ struct _ClutterBackendGLX
int error_base;
int event_base;
/* Single context for all wins */
gboolean found_fbconfig;
GLXFBConfig fbconfig;
GLXContext gl_context;
Window dummy_xwin;
GLXWindow dummy_glxwin;
CoglContext *cogl_context;
/* Vblank stuff */
GetVideoSyncProc get_video_sync;
WaitVideoSyncProc wait_video_sync;
SwapIntervalProc swap_interval;
gint dri_fd;
ClutterGLXVBlankType vblank_type;
unsigned int last_video_sync_count;
gboolean can_blit_sub_buffer;
CopySubBufferProc copy_sub_buffer;
BlitFramebufferProc blit_framebuffer;
gboolean blit_sub_buffer_is_synchronized;
/* props */
Atom atom_WM_STATE;
@ -110,14 +79,8 @@ struct _ClutterBackendGLXClass
GType _clutter_backend_glx_get_type (void) G_GNUC_CONST;
gboolean
_clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_x11,
GLXFBConfig *config);
void
_clutter_backend_glx_blit_sub_buffer (ClutterBackendGLX *backend_glx,
GLXDrawable drawable,
int x, int y, int width, int height);
G_CONST_RETURN gchar*
_clutter_backend_glx_get_vblank (void);
G_END_DECLS

View File

@ -53,10 +53,8 @@
#endif
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
static ClutterEventTranslatorIface *clutter_event_translator_parent_iface = NULL;
#define clutter_stage_glx_get_type _clutter_stage_glx_get_type
@ -64,33 +62,37 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageGLX,
clutter_stage_glx,
CLUTTER_TYPE_STAGE_X11,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init)
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_EVENT_TRANSLATOR,
clutter_event_translator_iface_init));
clutter_stage_window_iface_init));
static void
clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
ClutterBackendX11 *backend_x11 = stage_x11->backend;
/* Note unrealize should free up any backend stage related resources */
CLUTTER_NOTE (BACKEND, "Unrealizing GLX stage [%p]", stage_glx);
clutter_x11_trap_x_errors ();
cogl_object_unref (stage_glx->onscreen);
stage_glx->onscreen = NULL;
}
if (stage_glx->glxwin != None)
{
glXDestroyWindow (backend_x11->xdpy, stage_glx->glxwin);
stage_glx->glxwin = None;
}
static void
handle_swap_complete_cb (CoglFramebuffer *framebuffer,
void *user_data)
{
ClutterStageGLX *stage_glx = user_data;
_clutter_stage_x11_destroy_window_untrapped (stage_x11);
XSync (backend_x11->xdpy, False);
clutter_x11_untrap_x_errors ();
/* Early versions of the swap_event implementation in Mesa
* deliver BufferSwapComplete event when not selected for,
* so if we get a swap event we aren't expecting, just ignore it.
*
* https://bugs.freedesktop.org/show_bug.cgi?id=27962
*
* FIXME: This issue can be hidden inside Cogl so we shouldn't
* need to care about this bug here.
*/
if (stage_glx->pending_swaps > 0)
stage_glx->pending_swaps--;
}
static gboolean
@ -98,56 +100,53 @@ clutter_stage_glx_realize (ClutterStageWindow *stage_window)
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
ClutterBackendX11 *backend_x11;
ClutterBackend *backend;
ClutterBackendGLX *backend_glx;
CoglFramebuffer *framebuffer;
GError *error = NULL;
gfloat width;
gfloat height;
const char *clutter_vblank;
CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]",
G_OBJECT_TYPE_NAME (stage_window),
stage_window);
if (!_clutter_stage_x11_create_window (stage_x11))
return FALSE;
backend = CLUTTER_BACKEND (stage_x11->backend);
backend_glx = CLUTTER_BACKEND_GLX (stage_x11->backend);
backend_x11 = stage_x11->backend;
backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
if (stage_glx->glxwin == None)
stage_glx->onscreen = cogl_onscreen_new (backend->cogl_context,
width, height);
if (stage_x11->xwin != None)
cogl_onscreen_x11_set_foreign_window_xid (stage_glx->onscreen,
stage_x11->xwin);
clutter_vblank = _clutter_backend_glx_get_vblank ();
if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)
cogl_onscreen_set_swap_throttled (stage_glx->onscreen, FALSE);
framebuffer = COGL_FRAMEBUFFER (stage_glx->onscreen);
if (!cogl_framebuffer_allocate (framebuffer, &error))
{
int major;
int minor;
GLXFBConfig config;
/* Try and create a GLXWindow to use with extensions dependent on
* GLX versions >= 1.3 that don't accept regular X Windows as GLX
* drawables.
*/
if (glXQueryVersion (backend_x11->xdpy, &major, &minor) &&
major == 1 && minor >= 3 &&
_clutter_backend_glx_get_fbconfig (backend_glx, &config))
{
stage_glx->glxwin = glXCreateWindow (backend_x11->xdpy,
config,
stage_x11->xwin,
NULL);
}
g_warning ("Failed to allocate stage: %s", error->message);
g_error_free (error);
cogl_object_unref (stage_glx->onscreen);
stage_glx->onscreen = NULL;
return FALSE;
}
#ifdef GLX_INTEL_swap_event
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
{
GLXDrawable drawable = stage_glx->glxwin
? stage_glx->glxwin
: stage_x11->xwin;
if (stage_x11->xwin == None)
stage_x11->xwin = cogl_onscreen_x11_get_window_xid (stage_glx->onscreen);
/* we unconditionally select this event because we rely on it to
* advance the master clock, and drive redraw/relayout, animations
* and event handling.
*/
glXSelectEvent (backend_x11->xdpy,
drawable,
GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
{
stage_glx->swap_callback_id =
cogl_framebuffer_add_swap_buffers_callback (framebuffer,
handle_swap_complete_cb,
stage_glx);
}
#endif /* GLX_INTEL_swap_event */
/* chain up to the StageX11 implementation */
return clutter_stage_window_parent_iface->realize (stage_window);
@ -311,65 +310,12 @@ clutter_stage_glx_add_redraw_clip (ClutterStageWindow *stage_window,
stage_glx->initialized_redraw_clip = TRUE;
}
#ifdef HAVE_DRM
static int
drm_wait_vblank(int fd, drm_wait_vblank_t *vbl)
{
int ret, rc;
do
{
ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
vbl->request.type &= ~_DRM_VBLANK_RELATIVE;
rc = errno;
}
while (ret && rc == EINTR);
return rc;
}
#endif /* HAVE_DRM */
static void
wait_for_vblank (ClutterBackendGLX *backend_glx)
{
if (backend_glx->vblank_type == CLUTTER_VBLANK_NONE)
return;
if (backend_glx->wait_video_sync)
{
unsigned int retraceCount;
CLUTTER_NOTE (BACKEND, "Waiting for vblank (wait_video_sync)");
backend_glx->get_video_sync (&retraceCount);
backend_glx->wait_video_sync (2,
(retraceCount + 1) % 2,
&retraceCount);
}
else
{
#ifdef HAVE_DRM
drm_wait_vblank_t blank;
CLUTTER_NOTE (BACKEND, "Waiting for vblank (drm)");
blank.request.type = _DRM_VBLANK_RELATIVE;
blank.request.sequence = 1;
blank.request.signal = 0;
drm_wait_vblank (backend_glx->dri_fd, &blank);
#else
CLUTTER_NOTE (BACKEND, "No vblank mechanism found");
#endif /* HAVE_DRM */
}
}
static void
clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
{
ClutterBackendX11 *backend_x11;
ClutterBackendGLX *backend_glx;
ClutterStageX11 *stage_x11;
ClutterStageGLX *stage_glx;
GLXDrawable drawable;
unsigned int video_sync_count;
gboolean may_use_clipped_redraw;
gboolean use_clipped_redraw;
@ -395,8 +341,7 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
stage_glx = CLUTTER_STAGE_GLX (stage_window);
backend_x11 = stage_x11->backend;
backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
backend_glx = CLUTTER_BACKEND_GLX (stage_x11->backend);
CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);
@ -502,173 +447,75 @@ clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
cogl_object_unref (vbo);
}
cogl_flush ();
CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer);
drawable = stage_glx->glxwin
? stage_glx->glxwin
: stage_x11->xwin;
/* If we might ever use _clutter_backend_glx_blit_sub_buffer then we
* always need to keep track of the video_sync_count so that we can
* throttle blits.
*
* Note: we get the count *before* we issue any glXCopySubBuffer or
* blit_sub_buffer request in case the count would go up before
* returning control to us.
*/
if (backend_glx->can_blit_sub_buffer && backend_glx->get_video_sync)
backend_glx->get_video_sync (&video_sync_count);
/* push on the screen */
if (use_clipped_redraw)
{
ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
ClutterGeometry copy_area;
int copy_area[4];
ClutterActor *actor;
CLUTTER_NOTE (BACKEND,
"_glx_blit_sub_buffer (window: 0x%lx, "
"x: %d, y: %d, "
"width: %d, height: %d)",
(unsigned long) drawable,
stage_glx->bounding_redraw_clip.x,
stage_glx->bounding_redraw_clip.y,
stage_glx->bounding_redraw_clip.width,
stage_glx->bounding_redraw_clip.height);
/* XXX: It seems there will be a race here in that the stage
* window may be resized before glXCopySubBufferMESA is handled
* and so we may copy the wrong region. I can't really see how
* we can handle this with the current state of X but at least
* in this case a full redraw should be queued by the resize
* anyway so it should only exhibit temporary artefacts.
* window may be resized before the cogl_framebuffer_swap_region
* is handled and so we may copy the wrong region. I can't
* really see how we can handle this with the current state of X
* but at least in this case a full redraw should be queued by
* the resize anyway so it should only exhibit temporary
* artefacts.
*/
actor = CLUTTER_ACTOR (stage_x11->wrapper);
copy_area.y = clutter_actor_get_height (actor)
- clip->y
- clip->height;
copy_area.x = clip->x;
copy_area.width = clip->width;
copy_area.height = clip->height;
/* We need to ensure that all the rendering is done, otherwise
* redraw operations that are slower than the framerate can
* queue up in the pipeline during a heavy animation, causing a
* larger and larger backlog of rendering visible as lag to the
* user.
*
* Note: since calling glFinish() and sycnrhonizing the CPU with
* the GPU is far from ideal, we hope that this is only a short
* term solution.
* - One idea is to using sync objects to track render
* completion so we can throttle the backlog (ideally with an
* additional extension that lets us get notifications in our
* mainloop instead of having to busy wait for the
* completion.)
* - Another option is to support clipped redraws by reusing the
* contents of old back buffers such that we can flip instead
* of using a blit and then we can use GLX_INTEL_swap_events
* to throttle. For this though we would still probably want an
* additional extension so we can report the limited region of
* the window damage to X/compositors.
*/
glFinish ();
copy_area[0] = clip->x;
copy_area[1] = clutter_actor_get_height (actor) - clip->y - clip->height;
copy_area[2] = clip->width;
copy_area[3] = clip->height;
/* glXCopySubBufferMESA and glBlitFramebuffer are not integrated
* with the glXSwapIntervalSGI mechanism which we usually use to
* throttle the Clutter framerate to the vertical refresh and so
* we have to manually wait for the vblank period...
*/
/* Here 'is_synchronized' only means that the blit won't cause a
* tear, ie it won't prevent multiple blits per retrace if they
* can all be performed in the blanking period. If that's the
* case then we still want to use the vblank sync menchanism but
* we only need it to throttle redraws.
*/
if (!backend_glx->blit_sub_buffer_is_synchronized)
{
/* XXX: note that glXCopySubBuffer, at least for Intel, is
* synchronized with the vblank but glBlitFramebuffer may
* not be so we use the same scheme we do when calling
* glXSwapBuffers without the swap_control extension and
* call glFinish () before waiting for the vblank period.
*
* See where we call glXSwapBuffers for more details.
*/
wait_for_vblank (backend_glx);
}
else if (backend_glx->get_video_sync)
{
/* If we have the GLX_SGI_video_sync extension then we can
* be a bit smarter about how we throttle blits by avoiding
* any waits if we can see that the video sync count has
* already progressed. */
if (backend_glx->last_video_sync_count == video_sync_count)
wait_for_vblank (backend_glx);
}
else
wait_for_vblank (backend_glx);
CLUTTER_NOTE (BACKEND,
"cogl_framebuffer_swap_region (onscreen: %p, "
"x: %d, y: %d, "
"width: %d, height: %d)",
stage_glx->onscreen,
copy_area[0], copy_area[1], copy_area[2], copy_area[3]);
CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
_clutter_backend_glx_blit_sub_buffer (backend_glx,
drawable,
copy_area.x,
copy_area.y,
copy_area.width,
copy_area.height);
cogl_framebuffer_swap_region (COGL_FRAMEBUFFER (stage_glx->onscreen),
copy_area, 1);
CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
}
else
{
CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
backend_x11->xdpy,
(unsigned long) drawable);
CLUTTER_NOTE (BACKEND, "cogl_framebuffer_swap_buffers (onscreen: %p)",
stage_glx->onscreen);
/* If we have GLX swap buffer events then glXSwapBuffers will return
* immediately and we need to track that there is a swap in
* progress... */
/* If we have swap buffer events then
* cogl_framebuffer_swap_buffers will return immediately and we
* need to track that there is a swap in progress... */
if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
stage_glx->pending_swaps++;
if (backend_glx->vblank_type != CLUTTER_VBLANK_GLX_SWAP &&
backend_glx->vblank_type != CLUTTER_VBLANK_NONE)
{
/* If we are going to wait for VBLANK manually, we not only
* need to flush out pending drawing to the GPU before we
* sleep, we need to wait for it to finish. Otherwise, we
* may end up with the situation:
*
* - We finish drawing - GPU drawing continues
* - We go to sleep - GPU drawing continues
* VBLANK - We call glXSwapBuffers - GPU drawing continues
* - GPU drawing continues
* - Swap buffers happens
*
* Producing a tear. Calling glFinish() first will cause us
* to properly wait for the next VBLANK before we swap. This
* obviously does not happen when we use _GLX_SWAP and let
* the driver do the right thing
*/
glFinish ();
wait_for_vblank (backend_glx);
}
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
glXSwapBuffers (backend_x11->xdpy, drawable);
cogl_framebuffer_swap_buffers (COGL_FRAMEBUFFER (stage_glx->onscreen));
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
}
backend_glx->last_video_sync_count = video_sync_count;
/* reset the redraw clipping for the next paint... */
stage_glx->initialized_redraw_clip = FALSE;
stage_glx->frame_count++;
}
static CoglFramebuffer *
clutter_stage_glx_get_active_framebuffer (ClutterStageWindow *stage_window)
{
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
return COGL_FRAMEBUFFER (stage_glx->onscreen);
}
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
@ -682,55 +529,7 @@ clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
iface->has_redraw_clips = clutter_stage_glx_has_redraw_clips;
iface->ignoring_redraw_clips = clutter_stage_glx_ignoring_redraw_clips;
iface->redraw = clutter_stage_glx_redraw;
iface->get_active_framebuffer = clutter_stage_glx_get_active_framebuffer;
/* the rest is inherited from ClutterStageX11 */
}
static ClutterTranslateReturn
clutter_stage_glx_translate_event (ClutterEventTranslator *translator,
gpointer native,
ClutterEvent *event)
{
#ifdef GLX_INTEL_swap_event
ClutterBackendGLX *backend_glx;
XEvent *xevent = native;
backend_glx = CLUTTER_BACKEND_GLX (clutter_get_default_backend ());
if (xevent->type == (backend_glx->event_base + GLX_BufferSwapComplete))
{
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (translator);
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (translator);
GLXBufferSwapComplete *swap_complete_event;
swap_complete_event = (GLXBufferSwapComplete *) xevent;
if (stage_x11->xwin == swap_complete_event->drawable)
{
/* Early versions of the swap_event implementation in Mesa
* deliver BufferSwapComplete event when not selected for,
* so if we get a swap event we aren't expecting, just ignore it.
*
* https://bugs.freedesktop.org/show_bug.cgi?id=27962
*/
if (stage_glx->pending_swaps > 0)
stage_glx->pending_swaps--;
return CLUTTER_TRANSLATE_REMOVE;
}
}
#endif
/* chain up to the common X11 implementation */
return clutter_event_translator_parent_iface->translate_event (translator,
native,
event);
}
static void
clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface)
{
clutter_event_translator_parent_iface = g_type_interface_peek_parent (iface);
iface->translate_event = clutter_stage_glx_translate_event;
}

View File

@ -50,8 +50,9 @@ struct _ClutterStageGLX
gint pending_swaps;
GLXPixmap glxpixmap;
GLXWindow glxwin;
CoglOnscreen *onscreen;
unsigned int swap_callback_id;
/* We only enable clipped redraws after 2 frames, since we've seen
* a lot of drivers can struggle to get going and may output some

View File

@ -134,7 +134,7 @@ cogl_xlib_filter (XEvent *xevent,
ClutterX11FilterReturn retval;
CoglXlibFilterReturn ret;
ret = _cogl_xlib_handle_event (xevent);
ret = cogl_xlib_handle_event (xevent);
switch (ret)
{
case COGL_XLIB_FILTER_REMOVE:
@ -390,7 +390,7 @@ _clutter_backend_x11_post_parse (ClutterBackend *backend,
/* Cogl needs to know the Xlib display connection for
CoglTexturePixmapX11 */
_cogl_xlib_set_display (backend_x11->xdpy);
cogl_xlib_set_display (backend_x11->xdpy);
/* add event filter for Cogl events */
clutter_x11_add_filter (cogl_xlib_filter, NULL);

View File

@ -379,6 +379,13 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
ClutterDeviceManager *device_manager;
int event_flags;
if (clutter_stages_by_xid == NULL)
clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
g_hash_table_insert (clutter_stages_by_xid,
GINT_TO_POINTER (stage_x11->xwin),
stage_x11);
set_wm_pid (stage_x11);
set_wm_title (stage_x11);
set_cursor_visible (stage_x11);
@ -1436,13 +1443,6 @@ _clutter_stage_x11_create_window (ClutterStageX11 *stage_x11)
XFree (xvisinfo);
if (clutter_stages_by_xid == NULL)
clutter_stages_by_xid = g_hash_table_new (NULL, NULL);
g_hash_table_insert (clutter_stages_by_xid,
GINT_TO_POINTER (stage_x11->xwin),
stage_x11);
return TRUE;
}

View File

@ -447,6 +447,8 @@ AS_IF([test "x$SUPPORT_GLX" = "x1"],
[
AC_DEFINE([COGL_HAS_GLX_SUPPORT], [1], [Cogl supports OpenGL using the GLX API])
AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
AC_DEFINE([HAVE_CLUTTER_GLX], [1], [Have the GLX backend])
AC_CHECK_HEADERS([GL/glx.h],