unify egl and glx backends as "cogl" backend
Since GLX and EGL are abstracted by Cogl the two backends are both implementing everything using the Cogl API and they are almost identical. This updates the egl backend to support everything that the glx backend supports. Now that EGL and GLX are abstracted by Cogl, the plan is that we will squash the clutter-egl/glx backends into one. Since the EGL backend in clutter can conditionally not depend on X11 we will use the EGL backend as the starting point of our common backend. https://bugzilla.gnome.org/show_bug.cgi?id=649826
This commit is contained in:
parent
951cb82ec5
commit
2d8083bab8
@ -353,32 +353,37 @@ clutterx11_includedir = $(clutter_includedir)/x11
|
||||
clutterx11_include_HEADERS = $(x11_source_h)
|
||||
endif # SUPPORT_X11
|
||||
|
||||
# GLX backend rules
|
||||
glx_source_c = \
|
||||
$(srcdir)/glx/clutter-backend-glx.c \
|
||||
$(srcdir)/glx/clutter-glx-texture-pixmap.c \
|
||||
$(srcdir)/glx/clutter-stage-glx.c \
|
||||
# Shared cogl backend files
|
||||
cogl_source_h =
|
||||
|
||||
cogl_source_c = \
|
||||
$(srcdir)/cogl/clutter-backend-cogl.c \
|
||||
$(srcdir)/cogl/clutter-stage-cogl.c \
|
||||
$(NULL)
|
||||
|
||||
glx_source_h = \
|
||||
$(srcdir)/glx/clutter-glx-texture-pixmap.h \
|
||||
$(srcdir)/glx/clutter-glx.h \
|
||||
cogl_source_h_priv = \
|
||||
$(srcdir)/cogl/clutter-backend-cogl.h \
|
||||
$(srcdir)/cogl/clutter-stage-cogl.h \
|
||||
$(NULL)
|
||||
|
||||
glx_source_h_priv = \
|
||||
$(srcdir)/glx/clutter-backend-glx.h \
|
||||
$(srcdir)/glx/clutter-stage-glx.h \
|
||||
$(NULL)
|
||||
cogl_source_c_priv =
|
||||
|
||||
if SUPPORT_GLX
|
||||
backend_source_h += $(glx_source_h)
|
||||
backend_source_c += $(glx_source_c)
|
||||
backend_source_h_priv += $(glx_source_h_priv)
|
||||
|
||||
# XXX - this is another hack; we installed glx headers under includedir/glx
|
||||
# instead of using the same directory.
|
||||
if SUPPORT_X11
|
||||
# For compatability with the old GLX backend
|
||||
#
|
||||
# Note: there wasn't actually anything GLX specific so we can add
|
||||
# the compatability if clutter supports x11
|
||||
glx_source_c = $(srcdir)/cogl/clutter-glx-texture-pixmap.c
|
||||
glx_source_h = $(srcdir)/cogl/clutter-glx-texture-pixmap.h \
|
||||
$(srcdir)/cogl/clutter-glx.h
|
||||
clutterglx_includedir = $(clutter_includedir)/glx
|
||||
clutterglx_include_HEADERS = $(glx_source_h)
|
||||
endif
|
||||
|
||||
if SUPPORT_GLX
|
||||
backend_source_h += $(cogl_source_h)
|
||||
backend_source_c += $(cogl_source_c)
|
||||
backend_source_h_priv += $(cogl_source_h_priv)
|
||||
endif # SUPPORT_GLX
|
||||
|
||||
# Windows backend rules
|
||||
@ -429,22 +434,10 @@ EXTRA_DIST += \
|
||||
|
||||
# EGL backend rules
|
||||
egl_source_h = \
|
||||
$(srcdir)/egl/clutter-egl-headers.h \
|
||||
$(srcdir)/egl/clutter-egl.h \
|
||||
$(srcdir)/cogl/clutter-egl-headers.h \
|
||||
$(srcdir)/cogl/clutter-egl.h \
|
||||
$(NULL)
|
||||
|
||||
egl_source_c = \
|
||||
$(srcdir)/egl/clutter-backend-egl.c \
|
||||
$(srcdir)/egl/clutter-stage-egl.c \
|
||||
$(NULL)
|
||||
|
||||
egl_source_h_priv = \
|
||||
$(srcdir)/egl/clutter-backend-egl.h \
|
||||
$(srcdir)/egl/clutter-stage-egl.h \
|
||||
$(NULL)
|
||||
|
||||
egl_source_c_priv =
|
||||
|
||||
egl_tslib_c = $(srcdir)/egl/clutter-event-tslib.c
|
||||
|
||||
evdev_c_priv = \
|
||||
@ -458,29 +451,28 @@ evdev_h_priv = \
|
||||
$(srcdir)/evdev/clutter-input-device-evdev.h \
|
||||
$(NULL)
|
||||
|
||||
egl_cex_h = egl/clutter-cex100.h
|
||||
BUILT_SOURCES += egl/clutter-cex100.h
|
||||
EXTRA_DIST += $(srcdir)/egl/clutter-cex100.h.in
|
||||
|
||||
if SUPPORT_EGL
|
||||
cex_h = cogl/clutter-cex100.h
|
||||
BUILT_SOURCES += $(cex_h)
|
||||
EXTRA_DIST += $(srcdir)/$(cex_h).in
|
||||
|
||||
if USE_TSLIB
|
||||
egl_source_c_priv += $(egl_tslib_c)
|
||||
backend_source_c_priv += $(egl_tslib_c)
|
||||
endif # SUPPORT_TSLIB
|
||||
|
||||
if SUPPORT_EVDEV
|
||||
egl_source_c_priv += $(evdev_c_priv)
|
||||
egl_source_h_priv += $(evdev_h_priv)
|
||||
backend_source_c_priv += $(evdev_c_priv)
|
||||
backend_source_h_priv += $(evdev_h_priv)
|
||||
endif # SUPPORT_EVDEV
|
||||
|
||||
if SUPPORT_CEX100
|
||||
egl_source_h += $(egl_cex_h)
|
||||
backend_source_h += $(cex_h)
|
||||
endif # SUPPORT_CEX100
|
||||
|
||||
backend_source_h += $(egl_source_h)
|
||||
backend_source_c += $(egl_source_c)
|
||||
backend_source_h_priv += $(egl_source_h_priv)
|
||||
backend_source_c_priv += $(egl_source_c_priv)
|
||||
if SUPPORT_EGL
|
||||
backend_source_h += $(cogl_source_h) $(egl_source_h)
|
||||
backend_source_c += $(cogl_source_c)
|
||||
backend_source_h_priv += $(cogl_source_h_priv)
|
||||
backend_source_c_priv += $(cogl_source_c_priv)
|
||||
|
||||
clutteregl_includedir = $(clutter_includedir)/egl
|
||||
clutteregl_include_HEADERS = $(egl_source_h)
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* 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
|
||||
@ -36,9 +36,8 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "clutter-backend-egl.h"
|
||||
#include "clutter-stage-egl.h"
|
||||
#include "clutter-egl.h"
|
||||
#include "clutter-backend-cogl.h"
|
||||
#include "clutter-stage-cogl.h"
|
||||
|
||||
#ifdef HAVE_EVDEV
|
||||
#include "clutter-device-manager-evdev.h"
|
||||
@ -48,12 +47,15 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-stage-private.h"
|
||||
/* FIXME: We should have CLUTTER_ define for this... */
|
||||
|
||||
#ifdef COGL_HAS_EGL_SUPPORT
|
||||
#include "clutter-egl.h"
|
||||
#endif
|
||||
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
|
||||
#include "clutter-cex100.h"
|
||||
#endif
|
||||
|
||||
static ClutterBackendEGL *backend_singleton = NULL;
|
||||
static ClutterBackendCogl *backend_singleton = NULL;
|
||||
|
||||
static gchar *clutter_vblank = NULL;
|
||||
|
||||
@ -64,9 +66,9 @@ static guint gdl_n_buffers = CLUTTER_CEX100_TRIPLE_BUFFERING;
|
||||
#endif
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
G_DEFINE_TYPE (ClutterBackendEGL, _clutter_backend_egl, CLUTTER_TYPE_BACKEND_X11);
|
||||
G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND_X11);
|
||||
#else
|
||||
G_DEFINE_TYPE (ClutterBackendEGL, _clutter_backend_egl, CLUTTER_TYPE_BACKEND);
|
||||
G_DEFINE_TYPE (ClutterBackendCogl, _clutter_backend_cogl, CLUTTER_TYPE_BACKEND);
|
||||
#endif
|
||||
|
||||
static void
|
||||
@ -77,7 +79,7 @@ clutter_backend_at_exit (void)
|
||||
}
|
||||
|
||||
const gchar*
|
||||
_clutter_backend_egl_get_vblank (void)
|
||||
_clutter_backend_cogl_get_vblank (void)
|
||||
{
|
||||
if (clutter_vblank && strcmp (clutter_vblank, "0") == 0)
|
||||
return "none";
|
||||
@ -86,13 +88,13 @@ _clutter_backend_egl_get_vblank (void)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_egl_pre_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
clutter_backend_cogl_pre_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
const gchar *env_string;
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
ClutterBackendClass *parent_class =
|
||||
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
||||
CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class);
|
||||
|
||||
if (!parent_class->pre_parse (backend, error))
|
||||
return FALSE;
|
||||
@ -109,12 +111,12 @@ clutter_backend_egl_pre_parse (ClutterBackend *backend,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_egl_post_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
clutter_backend_cogl_post_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
ClutterBackendClass *parent_class =
|
||||
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
||||
CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class);
|
||||
|
||||
if (!parent_class->post_parse (backend, error))
|
||||
return FALSE;
|
||||
@ -129,62 +131,62 @@ clutter_backend_egl_post_parse (ClutterBackend *backend,
|
||||
|
||||
#ifndef COGL_HAS_XLIB_SUPPORT
|
||||
static ClutterDeviceManager *
|
||||
clutter_backend_egl_get_device_manager (ClutterBackend *backend)
|
||||
clutter_backend_cogl_get_device_manager (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend);
|
||||
|
||||
if (G_UNLIKELY (backend_egl->device_manager == NULL))
|
||||
if (G_UNLIKELY (backend_cogl->device_manager == NULL))
|
||||
{
|
||||
#ifdef HAVE_EVDEV
|
||||
backend_egl->device_manager =
|
||||
backend_cogl->device_manager =
|
||||
g_object_new (CLUTTER_TYPE_DEVICE_MANAGER_EVDEV,
|
||||
"backend", backend_egl,
|
||||
"backend", backend_cogl,
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
return backend_egl->device_manager;
|
||||
return backend_cogl->device_manager;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
clutter_backend_egl_init_events (ClutterBackend *backend)
|
||||
clutter_backend_cogl_init_events (ClutterBackend *backend)
|
||||
{
|
||||
#ifdef HAVE_TSLIB
|
||||
/* XXX: This should be renamed to _clutter_events_tslib_init */
|
||||
_clutter_events_egl_init (CLUTTER_BACKEND_EGL (backend));
|
||||
_clutter_events_tslib_init (CLUTTER_BACKEND_COGL (backend));
|
||||
#endif
|
||||
#ifdef HAVE_EVDEV
|
||||
_clutter_events_evdev_init (CLUTTER_BACKEND (backend));
|
||||
#endif
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
/* Chain up to the X11 backend */
|
||||
CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class)->
|
||||
CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class)->
|
||||
init_events (backend);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_egl_finalize (GObject *gobject)
|
||||
clutter_backend_cogl_finalize (GObject *gobject)
|
||||
{
|
||||
if (backend_singleton)
|
||||
backend_singleton = NULL;
|
||||
|
||||
G_OBJECT_CLASS (_clutter_backend_egl_parent_class)->finalize (gobject);
|
||||
G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_egl_dispose (GObject *gobject)
|
||||
clutter_backend_cogl_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBackend *backend = CLUTTER_BACKEND (gobject);
|
||||
#ifdef HAVE_TSLIB
|
||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (gobject);
|
||||
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (gobject);
|
||||
#endif
|
||||
|
||||
/* 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_egl_parent_class)->dispose (gobject);
|
||||
G_OBJECT_CLASS (_clutter_backend_cogl_parent_class)->dispose (gobject);
|
||||
|
||||
if (backend->cogl_context)
|
||||
{
|
||||
@ -194,30 +196,30 @@ clutter_backend_egl_dispose (GObject *gobject)
|
||||
|
||||
#ifdef HAVE_TSLIB
|
||||
/* XXX: This should be renamed to _clutter_events_tslib_uninit */
|
||||
_clutter_events_egl_uninit (backend_egl);
|
||||
_clutter_events_egl_uninit (backend_cogl);
|
||||
|
||||
if (backend_egl->event_timer != NULL)
|
||||
if (backend_cogl->event_timer != NULL)
|
||||
{
|
||||
g_timer_destroy (backend_egl->event_timer);
|
||||
backend_egl->event_timer = NULL;
|
||||
g_timer_destroy (backend_cogl->event_timer);
|
||||
backend_cogl->event_timer = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static GObject *
|
||||
clutter_backend_egl_constructor (GType gtype,
|
||||
guint n_params,
|
||||
GObjectConstructParam *params)
|
||||
clutter_backend_cogl_constructor (GType gtype,
|
||||
guint n_params,
|
||||
GObjectConstructParam *params)
|
||||
{
|
||||
GObjectClass *parent_class;
|
||||
GObject *retval;
|
||||
|
||||
if (!backend_singleton)
|
||||
{
|
||||
parent_class = G_OBJECT_CLASS (_clutter_backend_egl_parent_class);
|
||||
parent_class = G_OBJECT_CLASS (_clutter_backend_cogl_parent_class);
|
||||
retval = parent_class->constructor (gtype, n_params, params);
|
||||
|
||||
backend_singleton = CLUTTER_BACKEND_EGL (retval);
|
||||
backend_singleton = CLUTTER_BACKEND_COGL (retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -229,16 +231,16 @@ clutter_backend_egl_constructor (GType gtype,
|
||||
}
|
||||
|
||||
static ClutterFeatureFlags
|
||||
clutter_backend_egl_get_features (ClutterBackend *backend)
|
||||
clutter_backend_cogl_get_features (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend);
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
ClutterBackendClass *parent_class;
|
||||
#endif
|
||||
ClutterFeatureFlags flags = 0;
|
||||
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_egl_parent_class);
|
||||
parent_class = CLUTTER_BACKEND_CLASS (_clutter_backend_cogl_parent_class);
|
||||
|
||||
flags = parent_class->get_features (backend);
|
||||
#endif
|
||||
@ -271,7 +273,7 @@ clutter_backend_egl_get_features (ClutterBackend *backend)
|
||||
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Cogl supports swapping buffer regions");
|
||||
backend_egl->can_blit_sub_buffer = TRUE;
|
||||
backend_cogl->can_blit_sub_buffer = TRUE;
|
||||
}
|
||||
|
||||
return flags;
|
||||
@ -279,15 +281,15 @@ clutter_backend_egl_get_features (ClutterBackend *backend)
|
||||
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
static XVisualInfo *
|
||||
clutter_backend_egl_get_visual_info (ClutterBackendX11 *backend_x11)
|
||||
clutter_backend_cogl_get_visual_info (ClutterBackendX11 *backend_x11)
|
||||
{
|
||||
return cogl_clutter_winsys_xlib_get_visual_info ();
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
clutter_backend_egl_create_context (ClutterBackend *backend,
|
||||
GError **error)
|
||||
clutter_backend_cogl_create_context (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
@ -372,9 +374,9 @@ error:
|
||||
}
|
||||
|
||||
static ClutterStageWindow *
|
||||
clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
clutter_backend_cogl_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
{
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
@ -382,7 +384,7 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
ClutterStageWindow *stage;
|
||||
ClutterStageX11 *stage_x11;
|
||||
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_COGL, NULL);
|
||||
|
||||
/* copy backend data into the stage */
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
@ -392,33 +394,33 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
translator = CLUTTER_EVENT_TRANSLATOR (stage_x11);
|
||||
_clutter_backend_add_event_translator (backend, translator);
|
||||
|
||||
CLUTTER_NOTE (MISC, "EGLX stage created (display:%p, screen:%d, root:%u)",
|
||||
CLUTTER_NOTE (MISC, "Cogl stage created (display:%p, screen:%d, root:%u)",
|
||||
backend_x11->xdpy,
|
||||
backend_x11->xscreen_num,
|
||||
(unsigned int) backend_x11->xwin_root);
|
||||
|
||||
#else /* COGL_HAS_XLIB_SUPPORT */
|
||||
|
||||
ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||
ClutterBackendCogl *backend_cogl = CLUTTER_BACKEND_COGL (backend);
|
||||
ClutterStageWindow *stage;
|
||||
ClutterStageEGL *stage_egl;
|
||||
ClutterStageCogl *stage_cogl;
|
||||
|
||||
if (G_UNLIKELY (backend_egl->stage != NULL))
|
||||
if (G_UNLIKELY (backend_cogl->stage != NULL))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"The Cogl backend does not support multiple "
|
||||
"onscreen windows");
|
||||
return backend_egl->stage;
|
||||
return backend_cogl->stage;
|
||||
}
|
||||
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_EGL, NULL);
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_COGL, NULL);
|
||||
|
||||
stage_egl = CLUTTER_STAGE_EGL (stage);
|
||||
stage_egl->backend = backend_egl;
|
||||
stage_egl->wrapper = wrapper;
|
||||
stage_cogl = CLUTTER_STAGE_COGL (stage);
|
||||
stage_cogl->backend = backend_cogl;
|
||||
stage_cogl->wrapper = wrapper;
|
||||
|
||||
backend_egl->stage = stage;
|
||||
backend_cogl->stage = stage;
|
||||
|
||||
#endif /* COGL_HAS_XLIB_SUPPORT */
|
||||
|
||||
@ -426,17 +428,23 @@ clutter_backend_egl_create_stage (ClutterBackend *backend,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_egl_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
clutter_backend_cogl_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterStageEGL *stage_egl =
|
||||
CLUTTER_STAGE_EGL (_clutter_stage_get_window (stage));
|
||||
ClutterStageCogl *stage_cogl;
|
||||
|
||||
cogl_set_framebuffer (COGL_FRAMEBUFFER (stage_egl->onscreen));
|
||||
/* ignore ensuring the context on an empty stage */
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
stage_cogl =
|
||||
CLUTTER_STAGE_COGL (_clutter_stage_get_window (stage));
|
||||
|
||||
cogl_set_framebuffer (COGL_FRAMEBUFFER (stage_cogl->onscreen));
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
||||
_clutter_backend_cogl_class_init (ClutterBackendCoglClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
||||
@ -444,40 +452,41 @@ _clutter_backend_egl_class_init (ClutterBackendEGLClass *klass)
|
||||
ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
|
||||
#endif
|
||||
|
||||
gobject_class->constructor = clutter_backend_egl_constructor;
|
||||
gobject_class->dispose = clutter_backend_egl_dispose;
|
||||
gobject_class->finalize = clutter_backend_egl_finalize;
|
||||
gobject_class->constructor = clutter_backend_cogl_constructor;
|
||||
gobject_class->dispose = clutter_backend_cogl_dispose;
|
||||
gobject_class->finalize = clutter_backend_cogl_finalize;
|
||||
|
||||
backend_class->pre_parse = clutter_backend_egl_pre_parse;
|
||||
backend_class->post_parse = clutter_backend_egl_post_parse;
|
||||
backend_class->get_features = clutter_backend_egl_get_features;
|
||||
backend_class->pre_parse = clutter_backend_cogl_pre_parse;
|
||||
backend_class->post_parse = clutter_backend_cogl_post_parse;
|
||||
backend_class->get_features = clutter_backend_cogl_get_features;
|
||||
#ifndef COGL_HAS_XLIB_SUPPORT
|
||||
backend_class->get_device_manager = clutter_backend_egl_get_device_manager;
|
||||
backend_class->get_device_manager = clutter_backend_cogl_get_device_manager;
|
||||
#endif
|
||||
backend_class->init_events = clutter_backend_egl_init_events;
|
||||
backend_class->create_stage = clutter_backend_egl_create_stage;
|
||||
backend_class->create_context = clutter_backend_egl_create_context;
|
||||
backend_class->ensure_context = clutter_backend_egl_ensure_context;
|
||||
backend_class->init_events = clutter_backend_cogl_init_events;
|
||||
backend_class->create_stage = clutter_backend_cogl_create_stage;
|
||||
backend_class->create_context = clutter_backend_cogl_create_context;
|
||||
backend_class->ensure_context = clutter_backend_cogl_ensure_context;
|
||||
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
backendx11_class->get_visual_info = clutter_backend_egl_get_visual_info;
|
||||
backendx11_class->get_visual_info = clutter_backend_cogl_get_visual_info;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_backend_egl_init (ClutterBackendEGL *backend_egl)
|
||||
_clutter_backend_cogl_init (ClutterBackendCogl *backend_cogl)
|
||||
{
|
||||
#ifdef HAVE_TSLIB
|
||||
backend_egl->event_timer = g_timer_new ();
|
||||
backend_cogl->event_timer = g_timer_new ();
|
||||
#endif
|
||||
}
|
||||
|
||||
GType
|
||||
_clutter_backend_impl_get_type (void)
|
||||
{
|
||||
return _clutter_backend_egl_get_type ();
|
||||
return _clutter_backend_cogl_get_type ();
|
||||
}
|
||||
|
||||
#ifdef COGL_HAS_EGL_SUPPORT
|
||||
EGLDisplay
|
||||
clutter_eglx_display (void)
|
||||
{
|
||||
@ -501,6 +510,7 @@ clutter_egl_get_egl_display (void)
|
||||
|
||||
return cogl_context_egl_get_egl_display (backend_singleton->cogl_context);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FIXME we should have a CLUTTER_ define for this */
|
||||
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
|
@ -22,8 +22,8 @@
|
||||
* Robert Bragg
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_BACKEND_EGL_H__
|
||||
#define __CLUTTER_BACKEND_EGL_H__
|
||||
#ifndef __CLUTTER_BACKEND_COGL_H__
|
||||
#define __CLUTTER_BACKEND_COGL_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-event.h>
|
||||
@ -37,8 +37,6 @@
|
||||
|
||||
#include "clutter-backend-private.h"
|
||||
|
||||
#include "clutter-egl-headers.h"
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
#include "../x11/clutter-backend-x11.h"
|
||||
#endif
|
||||
@ -47,17 +45,17 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BACKEND_EGL (_clutter_backend_egl_get_type ())
|
||||
#define CLUTTER_BACKEND_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEGL))
|
||||
#define CLUTTER_IS_BACKEND_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_EGL))
|
||||
#define CLUTTER_BACKEND_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEGLClass))
|
||||
#define CLUTTER_IS_BACKEND_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_EGL))
|
||||
#define CLUTTER_BACKEND_EGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_EGL, ClutterBackendEGLClass))
|
||||
#define CLUTTER_TYPE_BACKEND_COGL (_clutter_backend_cogl_get_type ())
|
||||
#define CLUTTER_BACKEND_COGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_COGL, ClutterBackendCogl))
|
||||
#define CLUTTER_IS_BACKEND_COGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_COGL))
|
||||
#define CLUTTER_BACKEND_COGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_COGL, ClutterBackendCoglClass))
|
||||
#define CLUTTER_IS_BACKEND_COGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_COGL))
|
||||
#define CLUTTER_BACKEND_COGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_COGL, ClutterBackendCoglClass))
|
||||
|
||||
typedef struct _ClutterBackendEGL ClutterBackendEGL;
|
||||
typedef struct _ClutterBackendEGLClass ClutterBackendEGLClass;
|
||||
typedef struct _ClutterBackendCogl ClutterBackendCogl;
|
||||
typedef struct _ClutterBackendCoglClass ClutterBackendCoglClass;
|
||||
|
||||
struct _ClutterBackendEGL
|
||||
struct _ClutterBackendCogl
|
||||
{
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
ClutterBackendX11 parent_instance;
|
||||
@ -84,7 +82,7 @@ struct _ClutterBackendEGL
|
||||
gboolean can_blit_sub_buffer;
|
||||
};
|
||||
|
||||
struct _ClutterBackendEGLClass
|
||||
struct _ClutterBackendCoglClass
|
||||
{
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
ClutterBackendX11Class parent_class;
|
||||
@ -93,13 +91,15 @@ struct _ClutterBackendEGLClass
|
||||
#endif
|
||||
};
|
||||
|
||||
GType _clutter_backend_egl_get_type (void) G_GNUC_CONST;
|
||||
GType _clutter_backend_cogl_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void _clutter_events_egl_init (ClutterBackendEGL *backend);
|
||||
void _clutter_events_egl_uninit (ClutterBackendEGL *backend);
|
||||
#ifdef HAVE_TSLIB
|
||||
void _clutter_events_tslib_init (ClutterBackendCogl *backend);
|
||||
void _clutter_events_tslib_uninit (ClutterBackendCogl *backend);
|
||||
#endif
|
||||
|
||||
const gchar *_clutter_backend_egl_get_vblank (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BACKEND_EGL_H__ */
|
||||
#endif /* __CLUTTER_BACKEND_COGL_H__ */
|
@ -96,7 +96,7 @@ get_backend_time (void)
|
||||
#endif
|
||||
|
||||
void
|
||||
_clutter_events_egl_init (ClutterBackendEGL *backend_egl)
|
||||
_clutter_events_tslib_init (ClutterBackendEGL *backend_egl)
|
||||
{
|
||||
#ifdef HAVE_TSLIB
|
||||
ClutterEventSource *event_source;
|
@ -1,10 +1,37 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2007,2008,2009,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/>.
|
||||
|
||||
* Authors:
|
||||
* Matthew Allum
|
||||
* Robert Bragg
|
||||
* Neil Roberts
|
||||
* Emmanuele Bassi
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-stage-egl.h"
|
||||
#include "clutter-egl.h"
|
||||
#include "clutter-backend-egl.h"
|
||||
#include "clutter-stage-cogl.h"
|
||||
#include "clutter-backend-cogl.h"
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-event.h"
|
||||
@ -17,13 +44,13 @@
|
||||
#include "clutter-util.h"
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
static ClutterStageWindowIface *clutter_stage_egl_parent_iface = NULL;
|
||||
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
|
||||
#endif
|
||||
|
||||
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
|
||||
_clutter_stage_egl,
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterStageCogl,
|
||||
_clutter_stage_cogl,
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
CLUTTER_TYPE_STAGE_X11,
|
||||
#else
|
||||
@ -33,30 +60,49 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
|
||||
clutter_stage_window_iface_init));
|
||||
|
||||
static void
|
||||
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_unrealize (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Unrealizing EGL stage [%p]", stage_egl);
|
||||
CLUTTER_NOTE (BACKEND, "Unrealizing Cogl stage [%p]", stage_cogl);
|
||||
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
/* chain up to the StageX11 implementation */
|
||||
clutter_stage_window_parent_iface->unrealize (stage_window);
|
||||
#endif
|
||||
|
||||
cogl_object_unref (stage_egl->onscreen);
|
||||
stage_egl->onscreen = NULL;
|
||||
cogl_object_unref (stage_cogl->onscreen);
|
||||
stage_cogl->onscreen = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_swap_complete_cb (CoglFramebuffer *framebuffer,
|
||||
void *user_data)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = user_data;
|
||||
|
||||
/* 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_cogl->pending_swaps > 0)
|
||||
stage_cogl->pending_swaps--;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_realize (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
#endif
|
||||
ClutterBackend *backend;
|
||||
ClutterBackendEGL *backend_egl;
|
||||
ClutterBackendCogl *backend_cogl;
|
||||
CoglFramebuffer *framebuffer;
|
||||
GError *error = NULL;
|
||||
gfloat width = 800;
|
||||
@ -64,23 +110,23 @@ clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
||||
const char *clutter_vblank;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Realizing stage '%s' [%p]",
|
||||
G_OBJECT_TYPE_NAME (stage_egl),
|
||||
stage_egl);
|
||||
G_OBJECT_TYPE_NAME (stage_cogl),
|
||||
stage_cogl);
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||
backend_cogl = CLUTTER_BACKEND_COGL (backend);
|
||||
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
|
||||
#endif
|
||||
|
||||
stage_egl->onscreen = cogl_onscreen_new (backend->cogl_context,
|
||||
stage_cogl->onscreen = cogl_onscreen_new (backend->cogl_context,
|
||||
width, height);
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
if (stage_x11->xwin != None)
|
||||
{
|
||||
cogl_onscreen_x11_set_foreign_window_xid (
|
||||
stage_egl->onscreen,
|
||||
stage_cogl->onscreen,
|
||||
stage_x11->xwin,
|
||||
_clutter_stage_x11_update_foreign_event_mask,
|
||||
stage_x11);
|
||||
@ -88,39 +134,55 @@ clutter_stage_egl_realize (ClutterStageWindow *stage_window)
|
||||
}
|
||||
#endif
|
||||
|
||||
clutter_vblank = _clutter_backend_egl_get_vblank ();
|
||||
clutter_vblank = _clutter_backend_cogl_get_vblank ();
|
||||
if (clutter_vblank && strcmp (clutter_vblank, "none") == 0)
|
||||
cogl_onscreen_set_swap_throttled (stage_egl->onscreen, FALSE);
|
||||
cogl_onscreen_set_swap_throttled (stage_cogl->onscreen, FALSE);
|
||||
|
||||
framebuffer = COGL_FRAMEBUFFER (stage_egl->onscreen);
|
||||
framebuffer = COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
||||
if (!cogl_framebuffer_allocate (framebuffer, &error))
|
||||
{
|
||||
g_warning ("Failed to allocate stage: %s", error->message);
|
||||
g_error_free (error);
|
||||
cogl_object_unref (stage_egl->onscreen);
|
||||
stage_egl->onscreen = NULL;
|
||||
cogl_object_unref (stage_cogl->onscreen);
|
||||
stage_cogl->onscreen = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
/* FIXME: for fullscreen EGL platforms then the size we gave above
|
||||
/* FIXME: for fullscreen Cogl platforms then the size we gave above
|
||||
* will be ignored, so we need to make sure the stage size is
|
||||
* updated to this size. */
|
||||
|
||||
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
|
||||
{
|
||||
stage_cogl->swap_callback_id =
|
||||
cogl_framebuffer_add_swap_buffers_callback (framebuffer,
|
||||
handle_swap_complete_cb,
|
||||
stage_cogl);
|
||||
}
|
||||
|
||||
#ifdef COGL_HAS_XLIB_SUPPORT
|
||||
if (stage_x11->xwin == None)
|
||||
stage_x11->xwin = cogl_onscreen_x11_get_window_xid (stage_egl->onscreen);
|
||||
stage_x11->xwin = cogl_onscreen_x11_get_window_xid (stage_cogl->onscreen);
|
||||
|
||||
return clutter_stage_egl_parent_iface->realize (stage_window);
|
||||
return clutter_stage_window_parent_iface->realize (stage_window);
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
clutter_stage_cogl_get_pending_swaps (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
return stage_cogl->pending_swaps;
|
||||
}
|
||||
|
||||
#ifndef COGL_HAS_XLIB_SUPPORT
|
||||
|
||||
/* FIXME: Move this warnings up into clutter-stage.c */
|
||||
|
||||
static void
|
||||
clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
|
||||
clutter_stage_cogl_set_fullscreen (ClutterStageWindow *stage_window,
|
||||
gboolean fullscreen)
|
||||
{
|
||||
g_warning ("Stage of type '%s' do not support ClutterStage::set_fullscreen",
|
||||
@ -128,7 +190,7 @@ clutter_stage_egl_set_fullscreen (ClutterStageWindow *stage_window,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_set_title (ClutterStageWindow *stage_window,
|
||||
clutter_stage_cogl_set_title (ClutterStageWindow *stage_window,
|
||||
const gchar *title)
|
||||
{
|
||||
g_warning ("Stage of type '%s' do not support ClutterStage::set_title",
|
||||
@ -136,7 +198,7 @@ clutter_stage_egl_set_title (ClutterStageWindow *stage_window,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||
clutter_stage_cogl_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||
gboolean cursor_visible)
|
||||
{
|
||||
g_warning ("Stage of type '%s' do not support ClutterStage::set_cursor_visible",
|
||||
@ -144,40 +206,40 @@ clutter_stage_egl_set_cursor_visible (ClutterStageWindow *stage_window,
|
||||
}
|
||||
|
||||
static ClutterActor *
|
||||
clutter_stage_egl_get_wrapper (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_get_wrapper (ClutterStageWindow *stage_window)
|
||||
{
|
||||
return CLUTTER_ACTOR (CLUTTER_STAGE_EGL (stage_window)->wrapper);
|
||||
return CLUTTER_ACTOR (CLUTTER_STAGE_COGL (stage_window)->wrapper);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_show (ClutterStageWindow *stage_window,
|
||||
clutter_stage_cogl_show (ClutterStageWindow *stage_window,
|
||||
gboolean do_raise)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
clutter_actor_map (CLUTTER_ACTOR (stage_egl->wrapper));
|
||||
clutter_actor_map (CLUTTER_ACTOR (stage_cogl->wrapper));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_hide (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_hide (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
clutter_actor_unmap (CLUTTER_ACTOR (stage_egl->wrapper));
|
||||
clutter_actor_unmap (CLUTTER_ACTOR (stage_cogl->wrapper));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_get_geometry (ClutterStageWindow *stage_window,
|
||||
clutter_stage_cogl_get_geometry (ClutterStageWindow *stage_window,
|
||||
ClutterGeometry *geometry)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
if (geometry)
|
||||
{
|
||||
if (stage_egl->onscreen)
|
||||
if (stage_cogl->onscreen)
|
||||
{
|
||||
CoglFramebuffer *framebuffer =
|
||||
COGL_FRAMEBUFFER (stage_egl->onscreen);
|
||||
COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
||||
|
||||
geometry->x = geometry->y = 0;
|
||||
|
||||
@ -194,7 +256,7 @@ clutter_stage_egl_get_geometry (ClutterStageWindow *stage_window,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_egl_resize (ClutterStageWindow *stage_window,
|
||||
clutter_stage_cogl_resize (ClutterStageWindow *stage_window,
|
||||
gint width,
|
||||
gint height)
|
||||
{
|
||||
@ -203,9 +265,9 @@ clutter_stage_egl_resize (ClutterStageWindow *stage_window,
|
||||
#endif /* COGL_HAS_XLIB_SUPPORT */
|
||||
|
||||
static gboolean
|
||||
clutter_stage_egl_has_redraw_clips (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_has_redraw_clips (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
/* NB: at the start of each new frame there is an implied clip that
|
||||
* clips everything (i.e. nothing would be drawn) so we need to make
|
||||
@ -214,22 +276,22 @@ clutter_stage_egl_has_redraw_clips (ClutterStageWindow *stage_window)
|
||||
* NB: a clip width of 0 means a full stage redraw has been queued
|
||||
* so we effectively don't have any redraw clips in that case.
|
||||
*/
|
||||
if (!stage_egl->initialized_redraw_clip ||
|
||||
(stage_egl->initialized_redraw_clip &&
|
||||
stage_egl->bounding_redraw_clip.width != 0))
|
||||
if (!stage_cogl->initialized_redraw_clip ||
|
||||
(stage_cogl->initialized_redraw_clip &&
|
||||
stage_cogl->bounding_redraw_clip.width != 0))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_egl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
/* NB: a clip width of 0 means a full stage redraw is required */
|
||||
if (stage_egl->initialized_redraw_clip &&
|
||||
stage_egl->bounding_redraw_clip.width == 0)
|
||||
if (stage_cogl->initialized_redraw_clip &&
|
||||
stage_cogl->bounding_redraw_clip.width == 0)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
@ -238,7 +300,7 @@ clutter_stage_egl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
||||
/* A redraw clip represents (in stage coordinates) the bounding box of
|
||||
* something that needs to be redraw. Typically they are added to the
|
||||
* StageWindow as a result of clutter_actor_queue_clipped_redraw() by
|
||||
* actors such as ClutterEGLTexturePixmap. All redraw clips are
|
||||
* actors such as ClutterGLXTexturePixmap. All redraw clips are
|
||||
* discarded after the next paint.
|
||||
*
|
||||
* A NULL stage_clip means the whole stage needs to be redrawn.
|
||||
@ -250,22 +312,22 @@ clutter_stage_egl_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
||||
* buffer.
|
||||
*/
|
||||
static void
|
||||
clutter_stage_egl_add_redraw_clip (ClutterStageWindow *stage_window,
|
||||
clutter_stage_cogl_add_redraw_clip (ClutterStageWindow *stage_window,
|
||||
ClutterGeometry *stage_clip)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
/* If we are already forced to do a full stage redraw then bail early */
|
||||
if (clutter_stage_egl_ignoring_redraw_clips (stage_window))
|
||||
if (clutter_stage_cogl_ignoring_redraw_clips (stage_window))
|
||||
return;
|
||||
|
||||
/* A NULL stage clip means a full stage redraw has been queued and
|
||||
* we keep track of this by setting a zero width
|
||||
* stage_egl->bounding_redraw_clip */
|
||||
* stage_cogl->bounding_redraw_clip */
|
||||
if (stage_clip == NULL)
|
||||
{
|
||||
stage_egl->bounding_redraw_clip.width = 0;
|
||||
stage_egl->initialized_redraw_clip = TRUE;
|
||||
stage_cogl->bounding_redraw_clip.width = 0;
|
||||
stage_cogl->initialized_redraw_clip = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -273,30 +335,30 @@ clutter_stage_egl_add_redraw_clip (ClutterStageWindow *stage_window,
|
||||
if (stage_clip->width == 0 || stage_clip->height == 0)
|
||||
return;
|
||||
|
||||
if (!stage_egl->initialized_redraw_clip)
|
||||
if (!stage_cogl->initialized_redraw_clip)
|
||||
{
|
||||
stage_egl->bounding_redraw_clip.x = stage_clip->x;
|
||||
stage_egl->bounding_redraw_clip.y = stage_clip->y;
|
||||
stage_egl->bounding_redraw_clip.width = stage_clip->width;
|
||||
stage_egl->bounding_redraw_clip.height = stage_clip->height;
|
||||
stage_cogl->bounding_redraw_clip.x = stage_clip->x;
|
||||
stage_cogl->bounding_redraw_clip.y = stage_clip->y;
|
||||
stage_cogl->bounding_redraw_clip.width = stage_clip->width;
|
||||
stage_cogl->bounding_redraw_clip.height = stage_clip->height;
|
||||
}
|
||||
else if (stage_egl->bounding_redraw_clip.width > 0)
|
||||
else if (stage_cogl->bounding_redraw_clip.width > 0)
|
||||
{
|
||||
clutter_geometry_union (&stage_egl->bounding_redraw_clip, stage_clip,
|
||||
&stage_egl->bounding_redraw_clip);
|
||||
clutter_geometry_union (&stage_cogl->bounding_redraw_clip, stage_clip,
|
||||
&stage_cogl->bounding_redraw_clip);
|
||||
}
|
||||
|
||||
stage_egl->initialized_redraw_clip = TRUE;
|
||||
stage_cogl->initialized_redraw_clip = TRUE;
|
||||
}
|
||||
|
||||
/* XXX: This is basically identical to clutter_stage_glx_redraw */
|
||||
static void
|
||||
clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
||||
clutter_stage_cogl_redraw (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
ClutterActor *wrapper;
|
||||
ClutterBackend *backend;
|
||||
ClutterBackendEGL *backend_egl;
|
||||
ClutterBackendCogl *backend_cogl;
|
||||
gboolean may_use_clipped_redraw;
|
||||
gboolean use_clipped_redraw;
|
||||
|
||||
@ -317,27 +379,27 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
||||
0 /* no application private data */);
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_egl);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_cogl);
|
||||
|
||||
wrapper = CLUTTER_ACTOR (stage_x11->wrapper);
|
||||
#else
|
||||
wrapper = CLUTTER_ACTOR (stage_egl->wrapper);
|
||||
wrapper = CLUTTER_ACTOR (stage_cogl->wrapper);
|
||||
#endif
|
||||
|
||||
if (!stage_egl->onscreen)
|
||||
if (!stage_cogl->onscreen)
|
||||
return;
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
backend_egl = CLUTTER_BACKEND_EGL (backend);
|
||||
backend_cogl = CLUTTER_BACKEND_COGL (backend);
|
||||
|
||||
CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);
|
||||
|
||||
if (G_LIKELY (backend_egl->can_blit_sub_buffer) &&
|
||||
if (G_LIKELY (backend_cogl->can_blit_sub_buffer) &&
|
||||
/* NB: a zero width redraw clip == full stage redraw */
|
||||
stage_egl->bounding_redraw_clip.width != 0 &&
|
||||
stage_cogl->bounding_redraw_clip.width != 0 &&
|
||||
/* some drivers struggle to get going and produce some junk
|
||||
* frames when starting up... */
|
||||
G_LIKELY (stage_egl->frame_count > 3)
|
||||
G_LIKELY (stage_cogl->frame_count > 3)
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
/* While resizing a window clipped redraws are disabled to avoid
|
||||
* artefacts. See clutter-event-x11.c:event_translate for a
|
||||
@ -360,22 +422,42 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
||||
|
||||
if (use_clipped_redraw)
|
||||
{
|
||||
cogl_clip_push_window_rectangle (stage_egl->bounding_redraw_clip.x,
|
||||
stage_egl->bounding_redraw_clip.y,
|
||||
stage_egl->bounding_redraw_clip.width,
|
||||
stage_egl->bounding_redraw_clip.height);
|
||||
CLUTTER_NOTE (CLIPPING,
|
||||
"Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n",
|
||||
stage_cogl->bounding_redraw_clip.x,
|
||||
stage_cogl->bounding_redraw_clip.y,
|
||||
stage_cogl->bounding_redraw_clip.width,
|
||||
stage_cogl->bounding_redraw_clip.height);
|
||||
cogl_clip_push_window_rectangle (stage_cogl->bounding_redraw_clip.x,
|
||||
stage_cogl->bounding_redraw_clip.y,
|
||||
stage_cogl->bounding_redraw_clip.width,
|
||||
stage_cogl->bounding_redraw_clip.height);
|
||||
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper),
|
||||
&stage_egl->bounding_redraw_clip);
|
||||
&stage_cogl->bounding_redraw_clip);
|
||||
cogl_clip_pop ();
|
||||
}
|
||||
else
|
||||
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
|
||||
{
|
||||
CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
|
||||
|
||||
/* If we are trying to debug redraw issues then we want to pass
|
||||
* the bounding_redraw_clip so it can be visualized */
|
||||
if (G_UNLIKELY (clutter_paint_debug_flags &
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
|
||||
may_use_clipped_redraw)
|
||||
{
|
||||
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper),
|
||||
&stage_cogl->bounding_redraw_clip);
|
||||
}
|
||||
else
|
||||
_clutter_stage_do_paint (CLUTTER_STAGE (wrapper), NULL);
|
||||
}
|
||||
|
||||
if (may_use_clipped_redraw &&
|
||||
G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
|
||||
{
|
||||
static CoglMaterial *outline = NULL;
|
||||
ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
|
||||
ClutterGeometry *clip = &stage_cogl->bounding_redraw_clip;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (wrapper);
|
||||
CoglHandle vbo;
|
||||
float x_1 = clip->x;
|
||||
@ -422,7 +504,7 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
||||
/* push on the screen */
|
||||
if (use_clipped_redraw)
|
||||
{
|
||||
ClutterGeometry *clip = &stage_egl->bounding_redraw_clip;
|
||||
ClutterGeometry *clip = &stage_cogl->bounding_redraw_clip;
|
||||
int copy_area[4];
|
||||
ClutterActor *actor;
|
||||
|
||||
@ -445,13 +527,13 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
||||
"cogl_framebuffer_swap_region (onscreen: %p, "
|
||||
"x: %d, y: %d, "
|
||||
"width: %d, height: %d)",
|
||||
stage_egl->onscreen,
|
||||
stage_cogl->onscreen,
|
||||
copy_area[0], copy_area[1], copy_area[2], copy_area[3]);
|
||||
|
||||
|
||||
CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
|
||||
|
||||
cogl_framebuffer_swap_region (COGL_FRAMEBUFFER (stage_egl->onscreen),
|
||||
cogl_framebuffer_swap_region (COGL_FRAMEBUFFER (stage_cogl->onscreen),
|
||||
copy_area, 1);
|
||||
|
||||
CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
|
||||
@ -459,73 +541,89 @@ clutter_stage_egl_redraw (ClutterStageWindow *stage_window)
|
||||
else
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "cogl_framebuffer_swap_buffers (onscreen: %p)",
|
||||
stage_egl->onscreen);
|
||||
stage_cogl->onscreen);
|
||||
|
||||
/* 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_cogl->pending_swaps++;
|
||||
|
||||
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
|
||||
cogl_framebuffer_swap_buffers (COGL_FRAMEBUFFER (stage_egl->onscreen));
|
||||
cogl_framebuffer_swap_buffers (COGL_FRAMEBUFFER (stage_cogl->onscreen));
|
||||
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
|
||||
}
|
||||
|
||||
/* reset the redraw clipping for the next paint... */
|
||||
stage_egl->initialized_redraw_clip = FALSE;
|
||||
stage_cogl->initialized_redraw_clip = FALSE;
|
||||
|
||||
stage_egl->frame_count++;
|
||||
stage_cogl->frame_count++;
|
||||
}
|
||||
|
||||
static CoglFramebuffer *
|
||||
clutter_stage_cogl_get_active_framebuffer (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||
|
||||
return COGL_FRAMEBUFFER (stage_cogl->onscreen);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
|
||||
{
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
clutter_stage_egl_parent_iface = g_type_interface_peek_parent (iface);
|
||||
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
|
||||
|
||||
iface->realize = clutter_stage_egl_realize;
|
||||
iface->unrealize = clutter_stage_egl_unrealize;
|
||||
iface->realize = clutter_stage_cogl_realize;
|
||||
iface->unrealize = clutter_stage_cogl_unrealize;
|
||||
|
||||
/* the rest is inherited from ClutterStageX11 */
|
||||
|
||||
#else /* COGL_HAS_X11_SUPPORT */
|
||||
|
||||
iface->realize = clutter_stage_egl_realize;
|
||||
iface->unrealize = clutter_stage_egl_unrealize;
|
||||
iface->set_fullscreen = clutter_stage_egl_set_fullscreen;
|
||||
iface->set_title = clutter_stage_egl_set_title;
|
||||
iface->set_cursor_visible = clutter_stage_egl_set_cursor_visible;
|
||||
iface->get_wrapper = clutter_stage_egl_get_wrapper;
|
||||
iface->get_geometry = clutter_stage_egl_get_geometry;
|
||||
iface->resize = clutter_stage_egl_resize;
|
||||
iface->show = clutter_stage_egl_show;
|
||||
iface->hide = clutter_stage_egl_hide;
|
||||
iface->realize = clutter_stage_cogl_realize;
|
||||
iface->unrealize = clutter_stage_cogl_unrealize;
|
||||
iface->set_fullscreen = clutter_stage_cogl_set_fullscreen;
|
||||
iface->set_title = clutter_stage_cogl_set_title;
|
||||
iface->set_cursor_visible = clutter_stage_cogl_set_cursor_visible;
|
||||
iface->get_wrapper = clutter_stage_cogl_get_wrapper;
|
||||
iface->get_geometry = clutter_stage_cogl_get_geometry;
|
||||
iface->resize = clutter_stage_cogl_resize;
|
||||
iface->show = clutter_stage_cogl_show;
|
||||
iface->hide = clutter_stage_cogl_hide;
|
||||
|
||||
#endif /* COGL_HAS_X11_SUPPORT */
|
||||
|
||||
iface->add_redraw_clip = clutter_stage_egl_add_redraw_clip;
|
||||
iface->has_redraw_clips = clutter_stage_egl_has_redraw_clips;
|
||||
iface->ignoring_redraw_clips = clutter_stage_egl_ignoring_redraw_clips;
|
||||
iface->redraw = clutter_stage_egl_redraw;
|
||||
iface->get_pending_swaps = clutter_stage_cogl_get_pending_swaps;
|
||||
iface->add_redraw_clip = clutter_stage_cogl_add_redraw_clip;
|
||||
iface->has_redraw_clips = clutter_stage_cogl_has_redraw_clips;
|
||||
iface->ignoring_redraw_clips = clutter_stage_cogl_ignoring_redraw_clips;
|
||||
iface->redraw = clutter_stage_cogl_redraw;
|
||||
iface->get_active_framebuffer = clutter_stage_cogl_get_active_framebuffer;
|
||||
}
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
static void
|
||||
clutter_stage_egl_dispose (GObject *gobject)
|
||||
clutter_stage_cogl_dispose (GObject *gobject)
|
||||
{
|
||||
G_OBJECT_CLASS (_clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
G_OBJECT_CLASS (_clutter_stage_cogl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
||||
_clutter_stage_cogl_class_init (ClutterStageCoglClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_stage_egl_dispose;
|
||||
gobject_class->dispose = clutter_stage_cogl_dispose;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
_clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
|
||||
_clutter_stage_cogl_class_init (ClutterStageCoglClass *klass)
|
||||
{
|
||||
}
|
||||
#endif /* COGL_HAS_X11_SUPPORT */
|
||||
|
||||
static void
|
||||
_clutter_stage_egl_init (ClutterStageEGL *stage)
|
||||
_clutter_stage_cogl_init (ClutterStageCogl *stage)
|
||||
{
|
||||
}
|
78
clutter/cogl/clutter-stage-cogl.h
Normal file
78
clutter/cogl/clutter-stage-cogl.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef __CLUTTER_STAGE_COGL_H__
|
||||
#define __CLUTTER_STAGE_COGL_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include "../x11/clutter-stage-x11.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-backend-cogl.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_STAGE_COGL (_clutter_stage_cogl_get_type ())
|
||||
#define CLUTTER_STAGE_COGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_COGL, ClutterStageCogl))
|
||||
#define CLUTTER_IS_STAGE_COGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_COGL))
|
||||
#define CLUTTER_STAGE_COGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_COGL, ClutterStageCoglClass))
|
||||
#define CLUTTER_IS_STAGE_COGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_COGL))
|
||||
#define CLUTTER_STAGE_COGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_COGL, ClutterStageCoglClass))
|
||||
|
||||
typedef struct _ClutterStageCogl ClutterStageCogl;
|
||||
typedef struct _ClutterStageCoglClass ClutterStageCoglClass;
|
||||
|
||||
struct _ClutterStageCogl
|
||||
{
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
|
||||
ClutterStageX11 parent_instance;
|
||||
|
||||
#else
|
||||
|
||||
GObject parent_instance;
|
||||
|
||||
/* the stage wrapper */
|
||||
ClutterStage *wrapper;
|
||||
|
||||
/* back pointer to the backend */
|
||||
ClutterBackendCogl *backend;
|
||||
|
||||
#endif
|
||||
|
||||
CoglOnscreen *onscreen;
|
||||
|
||||
gint pending_swaps;
|
||||
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
|
||||
* junk frames to start with. */
|
||||
unsigned long frame_count;
|
||||
|
||||
ClutterGeometry bounding_redraw_clip;
|
||||
|
||||
guint initialized_redraw_clip : 1;
|
||||
};
|
||||
|
||||
struct _ClutterStageCoglClass
|
||||
{
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
ClutterStageX11Class parent_class;
|
||||
#else
|
||||
GObjectClass parent_class;
|
||||
#endif
|
||||
};
|
||||
|
||||
GType _clutter_stage_cogl_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_COGL_H__ */
|
@ -1,46 +0,0 @@
|
||||
/* Clutter.
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
* Copyright (C) 2006-2007 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_EGL_HEADERS_H__
|
||||
#define __CLUTTER_EGL_HEADERS_H__
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#if defined(COGL_HAS_GLES1)
|
||||
#include <GLES/gl.h>
|
||||
#include <GLES/egl.h>
|
||||
#else
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#define NativeDisplayType EGLNativeDisplayType
|
||||
#define NativeWindowType EGLNativeWindowType
|
||||
|
||||
#if defined(COGL_HAS_GLES2)
|
||||
#include <GLES2/gl2.h>
|
||||
#elif defined(COGL_HAS_GL)
|
||||
#include <GL/gl.h>
|
||||
#else
|
||||
#error Unknown Cogl backend
|
||||
#endif
|
||||
|
||||
#endif /* !COGL_HAS_GLES1 */
|
||||
|
||||
#endif /* __CLUTTER_EGL_HEADERS_H__ */
|
@ -1,75 +0,0 @@
|
||||
#ifndef __CLUTTER_STAGE_EGL_H__
|
||||
#define __CLUTTER_STAGE_EGL_H__
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include "../x11/clutter-stage-x11.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-egl-headers.h"
|
||||
#include "clutter-backend-egl.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_STAGE_EGL (_clutter_stage_egl_get_type ())
|
||||
#define CLUTTER_STAGE_EGL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGL))
|
||||
#define CLUTTER_IS_STAGE_EGL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_EGL))
|
||||
#define CLUTTER_STAGE_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGLClass))
|
||||
#define CLUTTER_IS_STAGE_EGL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_EGL))
|
||||
#define CLUTTER_STAGE_EGL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_EGL, ClutterStageEGLClass))
|
||||
|
||||
typedef struct _ClutterStageEGL ClutterStageEGL;
|
||||
typedef struct _ClutterStageEGLClass ClutterStageEGLClass;
|
||||
|
||||
struct _ClutterStageEGL
|
||||
{
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
|
||||
ClutterStageX11 parent_instance;
|
||||
|
||||
#else
|
||||
|
||||
GObject parent_instance;
|
||||
|
||||
/* the stage wrapper */
|
||||
ClutterStage *wrapper;
|
||||
|
||||
/* back pointer to the backend */
|
||||
ClutterBackendEGL *backend;
|
||||
|
||||
#endif
|
||||
|
||||
CoglOnscreen *onscreen;
|
||||
|
||||
/* 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
|
||||
* junk frames to start with. */
|
||||
unsigned long frame_count;
|
||||
|
||||
gboolean initialized_redraw_clip;
|
||||
ClutterGeometry bounding_redraw_clip;
|
||||
};
|
||||
|
||||
struct _ClutterStageEGLClass
|
||||
{
|
||||
#ifdef COGL_HAS_X11_SUPPORT
|
||||
ClutterStageX11Class parent_class;
|
||||
#else
|
||||
GObjectClass parent_class;
|
||||
#endif
|
||||
};
|
||||
|
||||
GType _clutter_stage_egl_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_EGL_H__ */
|
@ -1,380 +0,0 @@
|
||||
/* Clutter.
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
* Copyright (C) 2006-2007 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glxext.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "clutter-backend-glx.h"
|
||||
#include "clutter-stage-glx.h"
|
||||
#include "clutter-glx.h"
|
||||
#include "clutter-profile.h"
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-event-translator.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
#define clutter_backend_glx_get_type _clutter_backend_glx_get_type
|
||||
|
||||
G_DEFINE_TYPE (ClutterBackendGLX, clutter_backend_glx, CLUTTER_TYPE_BACKEND_X11);
|
||||
|
||||
/* singleton object */
|
||||
static ClutterBackendGLX *backend_singleton = NULL;
|
||||
|
||||
static gchar *clutter_vblank = NULL;
|
||||
|
||||
const gchar *
|
||||
_clutter_backend_glx_get_vblank (void)
|
||||
{
|
||||
if (clutter_vblank && strcmp (clutter_vblank, "0") == 0)
|
||||
return "none";
|
||||
else
|
||||
return clutter_vblank;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_glx_pre_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendClass *parent_class =
|
||||
CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
|
||||
const gchar *env_string;
|
||||
|
||||
env_string = g_getenv ("CLUTTER_VBLANK");
|
||||
if (env_string)
|
||||
{
|
||||
clutter_vblank = g_strdup (env_string);
|
||||
env_string = NULL;
|
||||
}
|
||||
|
||||
return parent_class->pre_parse (backend, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_glx_post_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendClass *parent_class =
|
||||
CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
|
||||
|
||||
if (!parent_class->post_parse (backend, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const GOptionEntry entries[] =
|
||||
{
|
||||
{ "vblank", 0,
|
||||
0,
|
||||
G_OPTION_ARG_STRING, &clutter_vblank,
|
||||
N_("Set to 'none' or '0' to disable throttling "
|
||||
"framerate to vblank"), "OPTION"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
clutter_backend_glx_add_options (ClutterBackend *backend,
|
||||
GOptionGroup *group)
|
||||
{
|
||||
ClutterBackendClass *parent_class =
|
||||
CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
|
||||
|
||||
g_option_group_add_entries (group, entries);
|
||||
|
||||
parent_class->add_options (backend, group);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_finalize (GObject *gobject)
|
||||
{
|
||||
if (backend_singleton)
|
||||
backend_singleton = NULL;
|
||||
|
||||
G_OBJECT_CLASS (clutter_backend_glx_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_dispose (GObject *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 ();
|
||||
|
||||
/* 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);
|
||||
|
||||
if (backend->cogl_context)
|
||||
{
|
||||
cogl_object_unref (backend->cogl_context);
|
||||
backend->cogl_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static GObject *
|
||||
clutter_backend_glx_constructor (GType gtype,
|
||||
guint n_params,
|
||||
GObjectConstructParam *params)
|
||||
{
|
||||
GObjectClass *parent_class;
|
||||
GObject *retval;
|
||||
|
||||
if (!backend_singleton)
|
||||
{
|
||||
parent_class = G_OBJECT_CLASS (clutter_backend_glx_parent_class);
|
||||
retval = parent_class->constructor (gtype, n_params, params);
|
||||
|
||||
backend_singleton = CLUTTER_BACKEND_GLX (retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
g_warning ("Attempting to create a new backend object. This should "
|
||||
"never happen, so we return the singleton instance.");
|
||||
|
||||
return g_object_ref (backend_singleton);
|
||||
}
|
||||
|
||||
static ClutterFeatureFlags
|
||||
clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||
ClutterBackendClass *parent_class;
|
||||
ClutterFeatureFlags flags;
|
||||
|
||||
parent_class = CLUTTER_BACKEND_CLASS (clutter_backend_glx_parent_class);
|
||||
|
||||
flags = parent_class->get_features (backend);
|
||||
|
||||
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_THROTTLE))
|
||||
{
|
||||
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");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (cogl_clutter_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Cogl supports swapping buffer regions");
|
||||
backend_glx->can_blit_sub_buffer = TRUE;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "backend features checked");
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static XVisualInfo *
|
||||
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11)
|
||||
{
|
||||
return cogl_clutter_winsys_xlib_get_visual_info ();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_glx_create_context (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
CoglSwapChain *swap_chain = NULL;
|
||||
CoglOnscreenTemplate *onscreen_template = NULL;
|
||||
|
||||
if (backend->cogl_context)
|
||||
return TRUE;
|
||||
|
||||
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;
|
||||
|
||||
swap_chain = cogl_swap_chain_new ();
|
||||
cogl_swap_chain_set_has_alpha (swap_chain,
|
||||
clutter_x11_get_use_argb_visual ());
|
||||
|
||||
onscreen_template = cogl_onscreen_template_new (swap_chain);
|
||||
cogl_object_unref (swap_chain);
|
||||
|
||||
if (!cogl_renderer_check_onscreen_template (backend->cogl_renderer,
|
||||
onscreen_template,
|
||||
error))
|
||||
goto error;
|
||||
|
||||
backend->cogl_display = cogl_display_new (backend->cogl_renderer,
|
||||
onscreen_template);
|
||||
cogl_object_unref (backend->cogl_renderer);
|
||||
cogl_object_unref (onscreen_template);
|
||||
|
||||
if (!cogl_display_setup (backend->cogl_display, error))
|
||||
goto error;
|
||||
|
||||
backend->cogl_context = cogl_context_new (backend->cogl_display, error);
|
||||
if (!backend->cogl_context)
|
||||
goto error;
|
||||
|
||||
/* 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;
|
||||
|
||||
error:
|
||||
if (backend->cogl_display)
|
||||
{
|
||||
cogl_object_unref (backend->cogl_display);
|
||||
backend->cogl_display = NULL;
|
||||
}
|
||||
|
||||
if (onscreen_template)
|
||||
cogl_object_unref (onscreen_template);
|
||||
if (swap_chain)
|
||||
cogl_object_unref (swap_chain);
|
||||
|
||||
if (backend->cogl_renderer)
|
||||
{
|
||||
cogl_object_unref (backend->cogl_renderer);
|
||||
backend->cogl_renderer = NULL;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static ClutterStageWindow *
|
||||
clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
ClutterEventTranslator *translator;
|
||||
ClutterStageWindow *stage_window;
|
||||
ClutterStageX11 *stage_x11;
|
||||
|
||||
stage_window = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
|
||||
|
||||
/* copy backend data into the stage */
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
stage_x11->wrapper = wrapper;
|
||||
stage_x11->backend = backend_x11;
|
||||
|
||||
translator = CLUTTER_EVENT_TRANSLATOR (stage_x11);
|
||||
_clutter_backend_add_event_translator (backend, translator);
|
||||
|
||||
CLUTTER_NOTE (BACKEND,
|
||||
"GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)",
|
||||
stage_window,
|
||||
backend_x11->xdpy,
|
||||
backend_x11->xscreen_num,
|
||||
(unsigned int) backend_x11->xwin_root,
|
||||
wrapper);
|
||||
|
||||
return stage_window;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterStageGLX *stage_glx;
|
||||
|
||||
/* ignore ensuring the context on an empty stage */
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
||||
ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
|
||||
|
||||
gobject_class->constructor = clutter_backend_glx_constructor;
|
||||
gobject_class->dispose = clutter_backend_glx_dispose;
|
||||
gobject_class->finalize = clutter_backend_glx_finalize;
|
||||
|
||||
backend_class->pre_parse = clutter_backend_glx_pre_parse;
|
||||
backend_class->post_parse = clutter_backend_glx_post_parse;
|
||||
backend_class->create_stage = clutter_backend_glx_create_stage;
|
||||
backend_class->add_options = clutter_backend_glx_add_options;
|
||||
backend_class->get_features = clutter_backend_glx_get_features;
|
||||
backend_class->create_context = clutter_backend_glx_create_context;
|
||||
backend_class->ensure_context = clutter_backend_glx_ensure_context;
|
||||
|
||||
backendx11_class->get_visual_info = clutter_backend_glx_get_visual_info;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_init (ClutterBackendGLX *backend_glx)
|
||||
{
|
||||
}
|
||||
|
||||
/* every backend must implement this function */
|
||||
GType
|
||||
_clutter_backend_impl_get_type (void)
|
||||
{
|
||||
return _clutter_backend_glx_get_type ();
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/* Clutter.
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
* Copyright (C) 2006-2007 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_BACKEND_GLX_H__
|
||||
#define __CLUTTER_BACKEND_GLX_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-event.h>
|
||||
#include <clutter/clutter-backend.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <GL/glx.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "../x11/clutter-backend-x11.h"
|
||||
#include "clutter-glx.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BACKEND_GLX (_clutter_backend_glx_get_type ())
|
||||
#define CLUTTER_BACKEND_GLX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_GLX, ClutterBackendGLX))
|
||||
#define CLUTTER_IS_BACKEND_GLX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_GLX))
|
||||
#define CLUTTER_BACKEND_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_GLX, ClutterBackendGLXClass))
|
||||
#define CLUTTER_IS_BACKEND_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_GLX))
|
||||
#define CLUTTER_BACKEND_GLX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_GLX, ClutterBackendGLXClass))
|
||||
|
||||
typedef struct _ClutterBackendGLX ClutterBackendGLX;
|
||||
typedef struct _ClutterBackendGLXClass ClutterBackendGLXClass;
|
||||
|
||||
typedef enum ClutterGLXVBlankType {
|
||||
CLUTTER_VBLANK_NONE = 0,
|
||||
CLUTTER_VBLANK_AUTOMATIC_THROTTLE,
|
||||
CLUTTER_VBLANK_VBLANK_COUNTER,
|
||||
CLUTTER_VBLANK_MANUAL_WAIT
|
||||
} ClutterGLXVBlankType;
|
||||
|
||||
struct _ClutterBackendGLX
|
||||
{
|
||||
ClutterBackendX11 parent_instance;
|
||||
|
||||
CoglContext *cogl_context;
|
||||
|
||||
gboolean can_blit_sub_buffer;
|
||||
};
|
||||
|
||||
struct _ClutterBackendGLXClass
|
||||
{
|
||||
ClutterBackendX11Class parent_class;
|
||||
};
|
||||
|
||||
GType _clutter_backend_glx_get_type (void) G_GNUC_CONST;
|
||||
|
||||
const gchar *_clutter_backend_glx_get_vblank (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BACKEND_GLX_H__ */
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2006 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-glx
|
||||
* @short_description: GLX specific API
|
||||
*
|
||||
* The GLX backend for Clutter provides some specific API for GLX
|
||||
* related calls.
|
||||
*
|
||||
* The ClutterGLX API is available since Clutter 0.4
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_GLX_H__
|
||||
#define __CLUTTER_GLX_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/glx/clutter-glx-texture-pixmap.h>
|
||||
|
||||
#endif /* __CLUTTER_GLX_H__ */
|
@ -1,541 +0,0 @@
|
||||
/* Clutter.
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
* Copyright (C) 2006-2007 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-backend-glx.h"
|
||||
#include "clutter-stage-glx.h"
|
||||
#include "clutter-glx.h"
|
||||
#include "clutter-profile.h"
|
||||
|
||||
#include "clutter-actor-private.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-device-manager.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
|
||||
#include <GL/glx.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_DRM
|
||||
#include <drm.h>
|
||||
#endif
|
||||
|
||||
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
|
||||
|
||||
static ClutterStageWindowIface *clutter_stage_window_parent_iface = NULL;
|
||||
|
||||
#define clutter_stage_glx_get_type _clutter_stage_glx_get_type
|
||||
|
||||
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));
|
||||
|
||||
static void
|
||||
clutter_stage_glx_unrealize (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
|
||||
/* Note unrealize should free up any backend stage related resources */
|
||||
CLUTTER_NOTE (BACKEND, "Unrealizing GLX stage [%p]", stage_glx);
|
||||
|
||||
/* chain up to the StageX11 implementation */
|
||||
clutter_stage_window_parent_iface->unrealize (stage_window);
|
||||
|
||||
cogl_object_unref (stage_glx->onscreen);
|
||||
stage_glx->onscreen = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_swap_complete_cb (CoglFramebuffer *framebuffer,
|
||||
void *user_data)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = user_data;
|
||||
|
||||
/* 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
|
||||
clutter_stage_glx_realize (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
ClutterBackend *backend;
|
||||
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);
|
||||
|
||||
backend = CLUTTER_BACKEND (stage_x11->backend);
|
||||
|
||||
clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height);
|
||||
|
||||
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_stage_x11_update_foreign_event_mask,
|
||||
stage_x11);
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (stage_x11->xwin == None)
|
||||
stage_x11->xwin = cogl_onscreen_x11_get_window_xid (stage_glx->onscreen);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* chain up to the StageX11 implementation */
|
||||
return clutter_stage_window_parent_iface->realize (stage_window);
|
||||
}
|
||||
|
||||
static int
|
||||
clutter_stage_glx_get_pending_swaps (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
|
||||
return stage_glx->pending_swaps;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_glx_class_init (ClutterStageGLXClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_glx_init (ClutterStageGLX *stage)
|
||||
{
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_glx_has_redraw_clips (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
|
||||
/* NB: at the start of each new frame there is an implied clip that
|
||||
* clips everything (i.e. nothing would be drawn) so we need to make
|
||||
* sure we return True in the un-initialized case here.
|
||||
*
|
||||
* NB: a clip width of 0 means a full stage redraw has been queued
|
||||
* so we effectively don't have any redraw clips in that case.
|
||||
*/
|
||||
if (!stage_glx->initialized_redraw_clip ||
|
||||
(stage_glx->initialized_redraw_clip &&
|
||||
stage_glx->bounding_redraw_clip.width != 0))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_stage_glx_ignoring_redraw_clips (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
|
||||
/* NB: a clip width of 0 means a full stage redraw is required */
|
||||
if (stage_glx->initialized_redraw_clip &&
|
||||
stage_glx->bounding_redraw_clip.width == 0)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* A redraw clip represents (in stage coordinates) the bounding box of
|
||||
* something that needs to be redraw. Typically they are added to the
|
||||
* StageWindow as a result of clutter_actor_queue_clipped_redraw() by
|
||||
* actors such as ClutterGLXTexturePixmap. All redraw clips are
|
||||
* discarded after the next paint.
|
||||
*
|
||||
* A NULL stage_clip means the whole stage needs to be redrawn.
|
||||
*
|
||||
* What we do with this information:
|
||||
* - we keep track of the bounding box for all redraw clips
|
||||
* - when we come to redraw; if the bounding box is smaller than the
|
||||
* stage we scissor the redraw to that box and use
|
||||
* GLX_MESA_copy_sub_buffer to present the redraw to the front
|
||||
* buffer.
|
||||
*
|
||||
* XXX - In theory, we should have some sort of heuristics to promote
|
||||
* a clipped redraw to a full screen redraw; in reality, it turns out
|
||||
* that promotion is fairly expensive. See the Clutter bug described
|
||||
* at: http://bugzilla.clutter-project.org/show_bug.cgi?id=2136 .
|
||||
*
|
||||
* TODO - we should use different heuristics depending on whether the
|
||||
* framebuffer is on screen and not redirected by a compositor VS
|
||||
* offscreen (either due to compositor redirection or because we are
|
||||
* rendering to a CoglOffscreen framebuffer)
|
||||
*
|
||||
* When not redirected glXCopySubBuffer (on intel hardware at least)
|
||||
* will block the GPU until the vertical trace is at the optimal point
|
||||
* so the copy can be done without tearing. In this case we don't want
|
||||
* to copy tall regions because they increase the average time spent
|
||||
* blocking the GPU.
|
||||
*
|
||||
* When rendering offscreen (CoglOffscreen or redirected by
|
||||
* compositor) then no extra synchronization is needed before the copy
|
||||
* can start.
|
||||
*
|
||||
* In all cases we need to consider that glXCopySubBuffer implies a
|
||||
* blit which may be avoided by promoting to a full stage redraw if:
|
||||
* - the framebuffer is redirected offscreen or a CoglOffscreen.
|
||||
* - the framebuffer is onscreen and fullscreen.
|
||||
* By promoting to a full stage redraw we trade off the cost involved
|
||||
* in rasterizing the extra pixels vs avoiding to use a blit to
|
||||
* present the back buffer.
|
||||
*/
|
||||
static void
|
||||
clutter_stage_glx_add_redraw_clip (ClutterStageWindow *stage_window,
|
||||
ClutterGeometry *stage_clip)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
|
||||
/* If we are already forced to do a full stage redraw then bail early */
|
||||
if (clutter_stage_glx_ignoring_redraw_clips (stage_window))
|
||||
return;
|
||||
|
||||
/* A NULL stage clip means a full stage redraw has been queued and
|
||||
* we keep track of this by setting a zero width
|
||||
* stage_glx->bounding_redraw_clip */
|
||||
if (stage_clip == NULL)
|
||||
{
|
||||
stage_glx->bounding_redraw_clip.width = 0;
|
||||
stage_glx->initialized_redraw_clip = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore requests to add degenerate/empty clip rectangles */
|
||||
if (stage_clip->width == 0 || stage_clip->height == 0)
|
||||
return;
|
||||
|
||||
if (!stage_glx->initialized_redraw_clip)
|
||||
{
|
||||
stage_glx->bounding_redraw_clip.x = stage_clip->x;
|
||||
stage_glx->bounding_redraw_clip.y = stage_clip->y;
|
||||
stage_glx->bounding_redraw_clip.width = stage_clip->width;
|
||||
stage_glx->bounding_redraw_clip.height = stage_clip->height;
|
||||
}
|
||||
else if (stage_glx->bounding_redraw_clip.width > 0)
|
||||
{
|
||||
clutter_geometry_union (&stage_glx->bounding_redraw_clip,
|
||||
stage_clip,
|
||||
&stage_glx->bounding_redraw_clip);
|
||||
}
|
||||
|
||||
#if 0
|
||||
redraw_area = (stage_glx->bounding_redraw_clip.width *
|
||||
stage_glx->bounding_redraw_clip.height);
|
||||
stage_area = stage_x11->xwin_width * stage_x11->xwin_height;
|
||||
|
||||
/* Redrawing and blitting >70% of the stage is assumed to be more
|
||||
* expensive than redrawing the additional 30% to avoid the blit.
|
||||
*
|
||||
* FIXME: This threshold was plucked out of thin air!
|
||||
*
|
||||
* The threshold has been disabled after verifying that it indeed
|
||||
* made redraws more expensive than intended; see bug reference:
|
||||
*
|
||||
* http://bugzilla.clutter-project.org/show_bug.cgi?id=2136
|
||||
*/
|
||||
if (redraw_area > (stage_area * 0.7f))
|
||||
{
|
||||
g_print ("DEBUG: clipped redraw too big, forcing full redraw\n");
|
||||
/* Set a zero width clip to force a full redraw */
|
||||
stage_glx->bounding_redraw_clip.width = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
stage_glx->initialized_redraw_clip = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
|
||||
{
|
||||
ClutterBackendGLX *backend_glx;
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterStageGLX *stage_glx;
|
||||
gboolean may_use_clipped_redraw;
|
||||
gboolean use_clipped_redraw;
|
||||
|
||||
CLUTTER_STATIC_TIMER (painting_timer,
|
||||
"Redrawing", /* parent */
|
||||
"Painting actors",
|
||||
"The time spent painting actors",
|
||||
0 /* no application private data */);
|
||||
CLUTTER_STATIC_TIMER (swapbuffers_timer,
|
||||
"Redrawing", /* parent */
|
||||
"glXSwapBuffers",
|
||||
"The time spent blocked by glXSwapBuffers",
|
||||
0 /* no application private data */);
|
||||
CLUTTER_STATIC_TIMER (blit_sub_buffer_timer,
|
||||
"Redrawing", /* parent */
|
||||
"glx_blit_sub_buffer",
|
||||
"The time spent in _glx_blit_sub_buffer",
|
||||
0 /* no application private data */);
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
if (stage_x11->xwin == None)
|
||||
return;
|
||||
|
||||
stage_glx = CLUTTER_STAGE_GLX (stage_window);
|
||||
|
||||
backend_glx = CLUTTER_BACKEND_GLX (stage_x11->backend);
|
||||
|
||||
CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);
|
||||
|
||||
if (G_LIKELY (backend_glx->can_blit_sub_buffer) &&
|
||||
/* NB: a zero width redraw clip == full stage redraw */
|
||||
stage_glx->bounding_redraw_clip.width != 0 &&
|
||||
/* some drivers struggle to get going and produce some junk
|
||||
* frames when starting up... */
|
||||
G_LIKELY (stage_glx->frame_count > 3) &&
|
||||
/* While resizing a window clipped redraws are disabled to avoid
|
||||
* artefacts. See clutter-event-x11.c:event_translate for a
|
||||
* detailed explanation */
|
||||
G_LIKELY (stage_x11->clipped_redraws_cool_off == 0))
|
||||
{
|
||||
may_use_clipped_redraw = TRUE;
|
||||
}
|
||||
else
|
||||
may_use_clipped_redraw = FALSE;
|
||||
|
||||
if (may_use_clipped_redraw &&
|
||||
G_LIKELY (!(clutter_paint_debug_flags &
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
|
||||
use_clipped_redraw = TRUE;
|
||||
else
|
||||
use_clipped_redraw = FALSE;
|
||||
|
||||
if (use_clipped_redraw)
|
||||
{
|
||||
CLUTTER_NOTE (CLIPPING,
|
||||
"Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n",
|
||||
stage_glx->bounding_redraw_clip.x,
|
||||
stage_glx->bounding_redraw_clip.y,
|
||||
stage_glx->bounding_redraw_clip.width,
|
||||
stage_glx->bounding_redraw_clip.height);
|
||||
cogl_clip_push_window_rectangle (stage_glx->bounding_redraw_clip.x,
|
||||
stage_glx->bounding_redraw_clip.y,
|
||||
stage_glx->bounding_redraw_clip.width,
|
||||
stage_glx->bounding_redraw_clip.height);
|
||||
_clutter_stage_do_paint (stage_x11->wrapper,
|
||||
&stage_glx->bounding_redraw_clip);
|
||||
cogl_clip_pop ();
|
||||
}
|
||||
else
|
||||
{
|
||||
CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
|
||||
|
||||
/* If we are trying to debug redraw issues then we want to pass
|
||||
* the bounding_redraw_clip so it can be visualized */
|
||||
if (G_UNLIKELY (clutter_paint_debug_flags &
|
||||
CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS) &&
|
||||
may_use_clipped_redraw)
|
||||
{
|
||||
_clutter_stage_do_paint (stage_x11->wrapper,
|
||||
&stage_glx->bounding_redraw_clip);
|
||||
}
|
||||
else
|
||||
_clutter_stage_do_paint (stage_x11->wrapper, NULL);
|
||||
}
|
||||
|
||||
if (may_use_clipped_redraw &&
|
||||
G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
|
||||
{
|
||||
static CoglMaterial *outline = NULL;
|
||||
ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (stage_x11->wrapper);
|
||||
CoglHandle vbo;
|
||||
float x_1 = clip->x;
|
||||
float x_2 = clip->x + clip->width;
|
||||
float y_1 = clip->y;
|
||||
float y_2 = clip->y + clip->height;
|
||||
float quad[8] = {
|
||||
x_1, y_1,
|
||||
x_2, y_1,
|
||||
x_2, y_2,
|
||||
x_1, y_2
|
||||
};
|
||||
CoglMatrix modelview;
|
||||
|
||||
if (outline == NULL)
|
||||
{
|
||||
outline = cogl_material_new ();
|
||||
cogl_material_set_color4ub (outline, 0xff, 0x00, 0x00, 0xff);
|
||||
}
|
||||
|
||||
vbo = cogl_vertex_buffer_new (4);
|
||||
cogl_vertex_buffer_add (vbo,
|
||||
"gl_Vertex",
|
||||
2, /* n_components */
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT,
|
||||
FALSE, /* normalized */
|
||||
0, /* stride */
|
||||
quad);
|
||||
cogl_vertex_buffer_submit (vbo);
|
||||
|
||||
cogl_push_matrix ();
|
||||
cogl_matrix_init_identity (&modelview);
|
||||
_clutter_actor_apply_modelview_transform (actor, &modelview);
|
||||
cogl_set_modelview_matrix (&modelview);
|
||||
cogl_set_source (outline);
|
||||
cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP,
|
||||
0 , 4);
|
||||
cogl_pop_matrix ();
|
||||
cogl_object_unref (vbo);
|
||||
}
|
||||
|
||||
CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer);
|
||||
|
||||
/* push on the screen */
|
||||
if (use_clipped_redraw)
|
||||
{
|
||||
ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
|
||||
int copy_area[4];
|
||||
ClutterActor *actor;
|
||||
|
||||
/* XXX: It seems there will be a race here in that the stage
|
||||
* 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[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;
|
||||
|
||||
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);
|
||||
|
||||
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, "cogl_framebuffer_swap_buffers (onscreen: %p)",
|
||||
stage_glx->onscreen);
|
||||
|
||||
/* 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++;
|
||||
|
||||
CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
|
||||
cogl_framebuffer_swap_buffers (COGL_FRAMEBUFFER (stage_glx->onscreen));
|
||||
CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
|
||||
|
||||
iface->realize = clutter_stage_glx_realize;
|
||||
iface->unrealize = clutter_stage_glx_unrealize;
|
||||
iface->get_pending_swaps = clutter_stage_glx_get_pending_swaps;
|
||||
|
||||
iface->add_redraw_clip = clutter_stage_glx_add_redraw_clip;
|
||||
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 */
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/* Clutter.
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
* Copyright (C) 2006-2007 OpenedHand
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_STAGE_GLX_H__
|
||||
#define __CLUTTER_STAGE_GLX_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <GL/glx.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "clutter-backend-glx.h"
|
||||
#include "../x11/clutter-stage-x11.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_STAGE_GLX (_clutter_stage_glx_get_type ())
|
||||
#define CLUTTER_STAGE_GLX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_GLX, ClutterStageGLX))
|
||||
#define CLUTTER_IS_STAGE_GLX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_GLX))
|
||||
#define CLUTTER_STAGE_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_GLX, ClutterStageGLXClass))
|
||||
#define CLUTTER_IS_STAGE_GLX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_GLX))
|
||||
#define CLUTTER_STAGE_GLX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_GLX, ClutterStageGLXClass))
|
||||
|
||||
typedef struct _ClutterStageGLX ClutterStageGLX;
|
||||
typedef struct _ClutterStageGLXClass ClutterStageGLXClass;
|
||||
|
||||
struct _ClutterStageGLX
|
||||
{
|
||||
ClutterStageX11 parent_instance;
|
||||
|
||||
gint pending_swaps;
|
||||
|
||||
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
|
||||
* junk frames to start with.
|
||||
*/
|
||||
guint frame_count;
|
||||
|
||||
ClutterGeometry bounding_redraw_clip;
|
||||
|
||||
guint initialized_redraw_clip : 1;
|
||||
};
|
||||
|
||||
struct _ClutterStageGLXClass
|
||||
{
|
||||
ClutterStageX11Class parent_class;
|
||||
};
|
||||
|
||||
GType _clutter_stage_glx_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_H__ */
|
12
configure.ac
12
configure.ac
@ -207,7 +207,7 @@ AS_CASE([$CLUTTER_FLAVOUR],
|
||||
SUPPORT_XLIB=1
|
||||
SUPPORT_GLX=1
|
||||
|
||||
CLUTTER_WINSYS=glx
|
||||
CLUTTER_WINSYS=cogl
|
||||
CLUTTER_WINSYS_BASE=x11
|
||||
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
|
||||
CLUTTER_SONAME_INFIX=glx
|
||||
@ -238,7 +238,7 @@ AS_CASE([$CLUTTER_FLAVOUR],
|
||||
SUPPORT_EGL=1
|
||||
SUPPORT_EGL_PLATFORM_POWERVR_X11=1
|
||||
|
||||
CLUTTER_WINSYS=egl
|
||||
CLUTTER_WINSYS=cogl
|
||||
CLUTTER_WINSYS_BASE=x11
|
||||
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
|
||||
# I think this winsys can be API and ABI compatible with the
|
||||
@ -275,7 +275,7 @@ AS_CASE([$CLUTTER_FLAVOUR],
|
||||
SUPPORT_EGL=1
|
||||
SUPPORT_EGL_PLATFORM_POWERVR_X11=1
|
||||
|
||||
CLUTTER_WINSYS=egl
|
||||
CLUTTER_WINSYS=cogl
|
||||
CLUTTER_WINSYS_BASE=x11
|
||||
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
|
||||
CLUTTER_SONAME_INFIX=eglx
|
||||
@ -310,7 +310,7 @@ AS_CASE([$CLUTTER_FLAVOUR],
|
||||
FLAVOUR_LIBS="$FLAVOUR_LIBS $TSLIB_LIBS $EVDEV_LIBS"
|
||||
FLAVOUR_CFLAGS="$FLAVOUR_CFLAGS $TSLIB_CFLAGS $EVDEV_CFLAGS"
|
||||
|
||||
CLUTTER_WINSYS=egl
|
||||
CLUTTER_WINSYS=cogl
|
||||
CLUTTER_SONAME_INFIX=eglnative
|
||||
],
|
||||
|
||||
@ -323,7 +323,7 @@ AS_CASE([$CLUTTER_FLAVOUR],
|
||||
SUPPORT_EGL_PLATFORM_GDL=1
|
||||
|
||||
# The cex100 is a small specialization of the EGL backend
|
||||
CLUTTER_WINSYS=egl
|
||||
CLUTTER_WINSYS=cogl
|
||||
CLUTTER_SONAME_INFIX=cex100
|
||||
|
||||
found_gdl=no
|
||||
@ -939,7 +939,7 @@ AC_CONFIG_FILES([
|
||||
|
||||
clutter/cally/cally-$CLUTTER_API_VERSION.pc:clutter/cally/cally.pc.in
|
||||
|
||||
clutter/egl/clutter-cex100.h
|
||||
clutter/cogl/clutter-cex100.h
|
||||
|
||||
tests/Makefile
|
||||
tests/accessibility/Makefile
|
||||
|
Loading…
Reference in New Issue
Block a user