mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
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:
parent
aa1a2cb661
commit
d6f110a4d2
@ -37,6 +37,11 @@ struct _ClutterBackend
|
||||
{
|
||||
/*< private >*/
|
||||
GObject parent_instance;
|
||||
|
||||
CoglRenderer *cogl_renderer;
|
||||
CoglDisplay *cogl_display;
|
||||
CoglContext *cogl_context;
|
||||
|
||||
ClutterBackendPrivate *priv;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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__ */
|
||||
|
@ -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 *
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
57
clutter/cogl/cogl/cogl-display-glx-private.h
Normal file
57
clutter/cogl/cogl/cogl-display-glx-private.h
Normal 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 */
|
35
clutter/cogl/cogl/cogl-display-xlib-private.h
Normal file
35
clutter/cogl/cogl/cogl-display-xlib-private.h
Normal 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 */
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
109
clutter/cogl/cogl/cogl-framebuffer.h
Normal file
109
clutter/cogl/cogl/cogl-framebuffer.h
Normal 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 */
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
61
clutter/cogl/cogl/cogl-renderer-glx-private.h
Normal file
61
clutter/cogl/cogl/cogl-renderer-glx-private.h
Normal 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 */
|
32
clutter/cogl/cogl/cogl-renderer-x11-private.h
Normal file
32
clutter/cogl/cogl/cogl-renderer-x11-private.h
Normal 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 */
|
@ -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 */
|
288
clutter/cogl/cogl/cogl-renderer-xlib.c
Normal file
288
clutter/cogl/cogl/cogl-renderer-xlib.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include "cogl-shader.h"
|
||||
#include "cogl-texture.h"
|
||||
#include "cogl-types.h"
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-util.h"
|
||||
|
||||
/*
|
||||
|
82
clutter/cogl/cogl/cogl-xlib-private.h
Normal file
82
clutter/cogl/cogl/cogl-xlib-private.h
Normal 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 */
|
@ -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;
|
||||
}
|
84
clutter/cogl/cogl/cogl-xlib.h
Normal file
84
clutter/cogl/cogl/cogl-xlib.h
Normal 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__ */
|
@ -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.
|
||||
|
@ -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__
|
||||
|
53
clutter/cogl/cogl/driver/gl/cogl-context-driver-gl.h
Normal file
53
clutter/cogl/cogl/driver/gl/cogl-context-driver-gl.h
Normal 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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
52
clutter/cogl/cogl/driver/gles/cogl-context-driver-gles.h
Normal file
52
clutter/cogl/cogl/driver/gles/cogl-context-driver-gles.h
Normal 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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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 */
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
105
clutter/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h
Normal file
105
clutter/cogl/cogl/winsys/cogl-winsys-glx-feature-functions.h
Normal 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
@ -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 */
|
||||
|
114
clutter/cogl/cogl/winsys/cogl-winsys-stub.c
Normal file
114
clutter/cogl/cogl/winsys/cogl-winsys-stub.c
Normal 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)
|
||||
{
|
||||
|
||||
}
|
36
clutter/cogl/cogl/winsys/cogl-winsys.c
Normal file
36
clutter/cogl/cogl/winsys/cogl-winsys.c
Normal 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");
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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],
|
||||
|
Loading…
Reference in New Issue
Block a user