Add a vtable of indirection to the winsys code

So that we can dynamically select what winsys backend to use at runtime
we need to have some indirection to how code accesses the winsys instead
of simply calling _cogl_winsys* functions that would collide if we
wanted to compile more than one backend into Cogl.
This commit is contained in:
Robert Bragg 2011-02-25 11:29:08 +00:00
parent d52e3f0cc2
commit dc7383b714
12 changed files with 484 additions and 242 deletions

View File

@ -68,6 +68,12 @@ cogl_onscreen_clutter_backend_set_size (int width, int height)
XVisualInfo *
cogl_clutter_winsys_xlib_get_visual_info (void)
{
return _cogl_winsys_xlib_get_visual_info ();
const CoglWinsysVtable *winsys;
_COGL_GET_CONTEXT (ctx, NULL);
winsys = _cogl_context_get_winsys (ctx);
return winsys->xlib_get_visual_info ();
}
#endif

View File

@ -268,6 +268,9 @@ struct _CoglContext
CoglContext *
_cogl_context_get_default ();
const CoglWinsysVtable *
_cogl_context_get_winsys (CoglContext *context);
/* Obtains the context and returns retval if NULL */
#define _COGL_GET_CONTEXT(ctxvar, retval) \
CoglContext *ctxvar = _cogl_context_get_default (); \

View File

@ -33,6 +33,8 @@
#include "cogl-profile.h"
#include "cogl-util.h"
#include "cogl-context-private.h"
#include "cogl-display-private.h"
#include "cogl-renderer-private.h"
#include "cogl-journal-private.h"
#include "cogl-texture-private.h"
#include "cogl-pipeline-private.h"
@ -83,6 +85,12 @@ _cogl_init_feature_overrides (CoglContext *ctx)
COGL_FEATURE_TEXTURE_NPOT_REPEAT);
}
const CoglWinsysVtable *
_cogl_context_get_winsys (CoglContext *context)
{
return context->display->renderer->winsys_vtable;
}
/* For reference: There was some deliberation over whether to have a
* constructor that could throw an exception but looking at standard
* practices with several high level OO languages including python, C++,
@ -99,6 +107,7 @@ cogl_context_new (CoglDisplay *display,
CoglContext *context;
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
unsigned long enable_flags = 0;
const CoglWinsysVtable *winsys;
int i;
#ifdef CLUTTER_ENABLE_PROFILE
@ -155,7 +164,8 @@ cogl_context_new (CoglDisplay *display,
#ifdef COGL_HAS_FULL_WINSYS
context->stub_winsys = FALSE;
if (!_cogl_winsys_context_init (context, error))
winsys = _cogl_context_get_winsys (context);
if (!winsys->context_init (context, error))
{
cogl_object_unref (display);
g_free (context);
@ -365,7 +375,9 @@ cogl_context_new (CoglDisplay *display,
static void
_cogl_context_free (CoglContext *context)
{
_cogl_winsys_context_deinit (context);
const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context);
winsys->context_deinit (context);
_cogl_destroy_texture_units ();
@ -480,7 +492,8 @@ cogl_set_default_context (CoglContext *context)
EGLDisplay
cogl_context_egl_get_egl_display (CoglContext *context)
{
return _cogl_winsys_context_egl_get_egl_display (context);
const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context);
return winsys->context_egl_get_egl_display (context);
}
#endif

View File

@ -32,6 +32,7 @@
#include "cogl-object.h"
#include "cogl-display-private.h"
#include "cogl-renderer-private.h"
#include "cogl-winsys-private.h"
static void _cogl_display_free (CoglDisplay *display);
@ -93,15 +94,26 @@ cogl_display_new (CoglRenderer *renderer,
return _cogl_display_object_new (display);
}
static const CoglWinsysVtable *
_cogl_display_get_winsys (CoglDisplay *display)
{
return display->renderer->winsys_vtable;
}
gboolean
cogl_display_setup (CoglDisplay *display,
GError **error)
{
#ifdef COGL_HAS_FULL_WINSYS
const CoglWinsysVtable *winsys;
#endif
if (display->setup)
return TRUE;
#ifdef COGL_HAS_FULL_WINSYS
if (!_cogl_winsys_display_setup (display, error))
winsys = _cogl_display_get_winsys (display);
if (!winsys->display_setup (display, error))
return FALSE;
#endif

View File

@ -29,6 +29,8 @@
#include "cogl-debug.h"
#include "cogl-internal.h"
#include "cogl-context-private.h"
#include "cogl-display-private.h"
#include "cogl-renderer-private.h"
#include "cogl-handle.h"
#include "cogl-object-private.h"
#include "cogl-util.h"
@ -231,6 +233,12 @@ _cogl_framebuffer_free (CoglFramebuffer *framebuffer)
cogl_object_unref (ctx);
}
static const CoglWinsysVtable *
_cogl_framebuffer_get_winsys (CoglFramebuffer *framebuffer)
{
return framebuffer->context->display->renderer->winsys_vtable;
}
/* This version of cogl_clear can be used internally as an alternative
* to avoid flushing the journal or the framebuffer state. This is
* needed when doing operations that may be called whiling flushing
@ -1012,6 +1020,7 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
GError **error)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
if (framebuffer->allocated)
return TRUE;
@ -1021,7 +1030,7 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN,
TRUE);
if (!_cogl_winsys_onscreen_init (onscreen, error))
if (!winsys->onscreen_init (onscreen, error))
return FALSE;
framebuffer->allocated = TRUE;
@ -1032,10 +1041,14 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
static void
_cogl_onscreen_free (CoglOnscreen *onscreen)
{
_cogl_winsys_onscreen_deinit (onscreen);
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_deinit (onscreen);
g_return_if_fail (onscreen->winsys == NULL);
/* Chain up to parent */
_cogl_framebuffer_free (COGL_FRAMEBUFFER (onscreen));
_cogl_framebuffer_free (framebuffer);
g_free (onscreen);
}
@ -1350,7 +1363,9 @@ bind_gl_framebuffer (CoglContext *ctx,
else
{
#ifdef COGL_HAS_FULL_WINSYS
_cogl_winsys_onscreen_bind (COGL_ONSCREEN (framebuffer));
const CoglWinsysVtable *winsys =
_cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_bind (COGL_ONSCREEN (framebuffer));
#endif
GE (glBindFramebuffer (target, 0));
}
@ -1582,7 +1597,11 @@ cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer)
/* FIXME: we shouldn't need to flush *all* journals here! */
cogl_flush ();
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
_cogl_winsys_onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
{
const CoglWinsysVtable *winsys =
_cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
}
}
void
@ -1593,9 +1612,13 @@ cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
/* FIXME: we shouldn't need to flush *all* journals here! */
cogl_flush ();
if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
_cogl_winsys_onscreen_swap_region (COGL_ONSCREEN (framebuffer),
{
const CoglWinsysVtable *winsys =
_cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
rectangles,
n_rectangles);
}
}
#ifdef COGL_HAS_X11_SUPPORT
@ -1609,15 +1632,20 @@ cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
guint32
cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
{
return _cogl_winsys_onscreen_x11_get_window_xid (onscreen);
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
return winsys->onscreen_x11_get_window_xid (onscreen);
}
guint32
cogl_onscreen_x11_get_visual_xid (CoglOnscreen *onscreen)
{
guint32 id;
XVisualInfo *visinfo = _cogl_winsys_xlib_get_visual_info ();
id = (guint32)visinfo->visualid;
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
XVisualInfo *visinfo = winsys->xlib_get_visual_info ();
guint32 id = (guint32)visinfo->visualid;
XFree (visinfo);
return id;
}
@ -1629,11 +1657,12 @@ cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
void *user_data)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
/* Should this just be cogl_onscreen API instead? */
g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN, 0);
return _cogl_winsys_onscreen_add_swap_buffers_callback (onscreen,
return winsys->onscreen_add_swap_buffers_callback (onscreen,
callback,
user_data);
}
@ -1643,15 +1672,21 @@ cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
unsigned int id)
{
CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
_cogl_winsys_onscreen_remove_swap_buffers_callback (onscreen, id);
winsys->onscreen_remove_swap_buffers_callback (onscreen, id);
}
void
cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
gboolean throttled)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
onscreen->swap_throttled = throttled;
if (COGL_FRAMEBUFFER (onscreen)->allocated)
_cogl_winsys_onscreen_update_swap_throttled (onscreen);
if (framebuffer->allocated)
{
const CoglWinsysVtable *winsys =
_cogl_framebuffer_get_winsys (framebuffer);
winsys->onscreen_update_swap_throttled (onscreen);
}
}

View File

@ -25,6 +25,7 @@
#define __COGL_RENDERER_PRIVATE_H
#include "cogl-object-private.h"
#include "cogl-winsys-private.h"
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xlib.h>
@ -34,6 +35,7 @@ struct _CoglRenderer
{
CoglObject _parent;
gboolean connected;
const CoglWinsysVtable *winsys_vtable;
#ifdef COGL_HAS_XLIB_SUPPORT
Display *foreign_xdpy;
#endif

View File

@ -37,6 +37,29 @@
#include "cogl-display-private.h"
#include "cogl-winsys-private.h"
#ifdef COGL_HAS_FULL_WINSYS
#ifdef COGL_HAS_GLX_SUPPORT
extern const CoglWinsysVtable *_cogl_winsys_glx_get_vtable (void);
#endif
#ifdef COGL_HAS_EGL_SUPPORT
extern const CoglWinsysVtable *_cogl_winsys_egl_get_vtable (void);
#endif
typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void);
static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] =
{
#ifdef COGL_HAS_GLX_SUPPORT
_cogl_winsys_glx_get_vtable,
#endif
#ifdef COGL_HAS_EGL_SUPPORT
_cogl_winsys_egl_get_vtable
#endif
};
#endif /* COGL_HAS_FULL_WINSYS */
static void _cogl_renderer_free (CoglRenderer *renderer);
COGL_OBJECT_DEFINE (Renderer, renderer);
@ -53,6 +76,12 @@ cogl_renderer_error_quark (void)
return g_quark_from_static_string ("cogl-renderer-error-quark");
}
static const CoglWinsysVtable *
_cogl_renderer_get_winsys (CoglRenderer *renderer)
{
return renderer->winsys_vtable;
}
static void
native_filter_closure_free (CoglNativeFilterClosure *closure)
{
@ -63,7 +92,8 @@ static void
_cogl_renderer_free (CoglRenderer *renderer)
{
#ifdef COGL_HAS_FULL_WINSYS
_cogl_winsys_renderer_disconnect (renderer);
const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
winsys->renderer_disconnect (renderer);
#endif
g_slist_foreach (renderer->event_filters,
@ -114,8 +144,9 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
{
#ifdef COGL_HAS_FULL_WINSYS
CoglDisplay *display;
const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
if (!_cogl_winsys_renderer_connect (renderer, error))
if (!winsys->renderer_connect (renderer, error))
return FALSE;
display = cogl_display_new (renderer, onscreen_template);
@ -135,16 +166,51 @@ cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
gboolean
cogl_renderer_connect (CoglRenderer *renderer, GError **error)
{
#ifdef COGL_HAS_FULL_WINSYS
int i;
#endif
GString *error_message;
if (renderer->connected)
return TRUE;
#ifdef COGL_HAS_FULL_WINSYS
if (!_cogl_winsys_renderer_connect (renderer, error))
return FALSE;
#endif
error_message = g_string_new ("");
for (i = 0; i < G_N_ELEMENTS (_cogl_winsys_vtable_getters); i++)
{
const CoglWinsysVtable *winsys = _cogl_winsys_vtable_getters[i]();
GError *tmp_error = NULL;
if (!winsys->renderer_connect (renderer, &tmp_error))
{
g_string_append_c (error_message, '\n');
g_string_append (error_message, tmp_error->message);
g_error_free (tmp_error);
}
else
{
renderer->winsys_vtable = winsys;
renderer->connected = TRUE;
g_string_free (error_message, TRUE);
return TRUE;
}
}
if (!renderer->connected)
{
renderer->winsys_vtable = NULL;
g_set_error (error, COGL_WINSYS_ERROR,
COGL_WINSYS_ERROR_INIT,
"Failed to connected to any renderer: %s",
error_message->str);
g_string_free (error_message, TRUE);
return FALSE;
}
return TRUE;
#else
renderer->connected = TRUE;
return TRUE;
#endif
}
CoglFilterReturn

View File

@ -93,8 +93,17 @@ cogl_get_proc_address (const char* name)
{
void *address;
static GModule *module = NULL;
#ifdef COGL_HAS_FULL_WINSYS
const CoglWinsysVtable *winsys;
_COGL_GET_CONTEXT (ctx, NULL);
winsys = _cogl_context_get_winsys (ctx);
address = winsys->get_proc_address (name);
#else
address = _cogl_winsys_get_proc_address (name);
#endif
if (address)
return address;

View File

@ -42,6 +42,8 @@
#include "cogl-texture-2d-private.h"
#include "cogl-texture-rectangle-private.h"
#include "cogl-context-private.h"
#include "cogl-display-private.h"
#include "cogl-renderer-private.h"
#include "cogl-handle.h"
#include "cogl-winsys-private.h"
#include "cogl-pipeline-opengl-private.h"
@ -101,12 +103,23 @@ cogl_damage_rectangle_is_whole (const CoglDamageRectangle *damage_rect,
&& damage_rect->x2 == width && damage_rect->y2 == height);
}
static const CoglWinsysVtable *
_cogl_texture_pixmap_x11_get_winsys (CoglTexturePixmapX11 *tex_pixmap)
{
/* FIXME: A CoglContext should be reachable from a CoglTexture
* pointer */
_COGL_GET_CONTEXT (ctx, NULL);
return ctx->display->renderer->winsys_vtable;
}
static void
process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
XDamageNotifyEvent *damage_event)
{
Display *display;
enum { DO_NOTHING, NEEDS_SUBTRACT, NEED_BOUNDING_BOX } handle_mode;
const CoglWinsysVtable *winsys;
_COGL_GET_CONTEXT (ctxt, NO_RETVAL);
@ -195,7 +208,8 @@ process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
/* If we're using the texture from pixmap extension then there's no
point in getting the region and we can just mark that the texture
needs updating */
_cogl_winsys_texture_pixmap_x11_damage_notify (tex_pixmap);
winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
}
static CoglFilterReturn
@ -254,6 +268,7 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
XWindowAttributes window_attributes;
int damage_base;
const CoglWinsysVtable *winsys;
_COGL_GET_CONTEXT (ctxt, COGL_INVALID_HANDLE);
@ -307,7 +322,9 @@ cogl_texture_pixmap_x11_new (guint32 pixmap,
tex_pixmap->damage_rect.y1 = 0;
tex_pixmap->damage_rect.y2 = tex_pixmap->height;
_cogl_winsys_texture_pixmap_x11_create (tex_pixmap);
winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
if (winsys->texture_pixmap_x11_create)
winsys->texture_pixmap_x11_create (tex_pixmap);
return _cogl_texture_pixmap_x11_handle_new (tex_pixmap);
}
@ -390,6 +407,7 @@ cogl_texture_pixmap_x11_update_area (CoglHandle handle,
int height)
{
CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
const CoglWinsysVtable *winsys;
if (!cogl_is_texture_pixmap_x11 (handle))
return;
@ -398,7 +416,8 @@ cogl_texture_pixmap_x11_update_area (CoglHandle handle,
texture because we can't determine which will be needed until we
actually render something */
_cogl_winsys_texture_pixmap_x11_damage_notify (tex_pixmap);
winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
x, y, width, height);
@ -617,7 +636,10 @@ _cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
{
if (tex_pixmap->winsys)
{
if (_cogl_winsys_texture_pixmap_x11_update (tex_pixmap, needs_mipmap))
const CoglWinsysVtable *winsys =
_cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
if (winsys->texture_pixmap_x11_update (tex_pixmap, needs_mipmap))
{
_cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE);
return;
@ -649,7 +671,11 @@ _cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
for (i = 0; i < 2; i++)
{
if (tex_pixmap->use_winsys_texture)
tex = _cogl_winsys_texture_pixmap_x11_get_texture (tex_pixmap);
{
const CoglWinsysVtable *winsys =
_cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap);
}
else
tex = tex_pixmap->tex;
@ -912,7 +938,11 @@ _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
cogl_handle_unref (tex_pixmap->tex);
if (tex_pixmap->winsys)
_cogl_winsys_texture_pixmap_x11_free (tex_pixmap);
{
const CoglWinsysVtable *winsys =
_cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
winsys->texture_pixmap_x11_free (tex_pixmap);
}
/* Chain up */
_cogl_texture_free (COGL_TEXTURE (tex_pixmap));

View File

@ -168,7 +168,7 @@ static const CoglFeatureData winsys_feature_data[] =
#include "cogl-winsys-egl-feature-functions.h"
};
CoglFuncPtr
static CoglFuncPtr
_cogl_winsys_get_proc_address (const char *name)
{
return (CoglFuncPtr) eglGetProcAddress (name);
@ -237,7 +237,21 @@ event_filter_cb (void *event, void *data)
}
#endif /* COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT */
gboolean
static void
_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
{
CoglRendererEGL *egl_renderer = renderer->winsys;
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
_cogl_renderer_xlib_disconnect (renderer);
#endif
eglTerminate (egl_renderer->edpy);
g_slice_free (CoglRendererEGL, egl_renderer);
}
static gboolean
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
GError **error)
{
@ -285,21 +299,7 @@ error:
return FALSE;
}
void
_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
{
CoglRendererEGL *egl_renderer = renderer->winsys;
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
_cogl_renderer_xlib_disconnect (renderer);
#endif
eglTerminate (egl_renderer->edpy);
g_slice_free (CoglRendererEGL, egl_renderer);
}
void
static void
update_winsys_features (CoglContext *context)
{
CoglDisplayEGL *egl_display = context->display->winsys;
@ -675,7 +675,20 @@ create_context (CoglDisplay *display, GError **error)
return status;
}
gboolean
static void
_cogl_winsys_display_destroy (CoglDisplay *display)
{
CoglDisplayEGL *egl_display = display->winsys;
g_return_if_fail (egl_display != NULL);
cleanup_context (display);
g_slice_free (CoglDisplayEGL, display->winsys);
display->winsys = NULL;
}
static gboolean
_cogl_winsys_display_setup (CoglDisplay *display,
GError **error)
{
@ -698,20 +711,7 @@ error:
return FALSE;
}
void
_cogl_winsys_display_destroy (CoglDisplay *display)
{
CoglDisplayEGL *egl_display = display->winsys;
g_return_if_fail (egl_display != NULL);
cleanup_context (display);
g_slice_free (CoglDisplayEGL, display->winsys);
display->winsys = NULL;
}
gboolean
static gboolean
_cogl_winsys_context_init (CoglContext *context, GError **error)
{
context->winsys = g_new0 (CoglContextEGL, 1);
@ -726,7 +726,7 @@ _cogl_winsys_context_init (CoglContext *context, GError **error)
return TRUE;
}
void
static void
_cogl_winsys_context_deinit (CoglContext *context)
{
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
@ -737,7 +737,7 @@ _cogl_winsys_context_deinit (CoglContext *context)
g_free (context->winsys);
}
gboolean
static gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
GError **error)
{
@ -896,7 +896,7 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
return TRUE;
}
void
static void
_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@ -941,7 +941,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
#endif
}
void
static void
_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@ -982,7 +982,7 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
eglSwapInterval (egl_renderer->edpy, 0);
}
void
static void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
int *rectangles,
int n_rectangles)
@ -998,14 +998,14 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
g_warning ("Error reported by eglSwapBuffersRegion");
}
guint32
static guint32
_cogl_winsys_get_vsync_counter (void)
{
/* Unsupported feature */
return 0;
}
void
static void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@ -1015,14 +1015,14 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
}
guint32
static guint32
_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
{
CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
return xlib_onscreen->xwin;
}
unsigned int
static unsigned int
_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
CoglSwapBuffersNotify callback,
void *user_data)
@ -1031,14 +1031,14 @@ _cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
return 0;
}
void
static void
_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
unsigned int id)
{
/* Unsupported feature */
}
void
static void
_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@ -1054,7 +1054,7 @@ _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
/* XXX: This is a particularly hacky _cogl_winsys interface... */
XVisualInfo *
static XVisualInfo *
_cogl_winsys_xlib_get_visual_info (void)
{
CoglDisplayEGL *egl_display;
@ -1072,7 +1072,7 @@ _cogl_winsys_xlib_get_visual_info (void)
}
#endif
EGLDisplay
static EGLDisplay
_cogl_winsys_context_egl_get_egl_display (CoglContext *context)
{
CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
@ -1080,37 +1080,47 @@ _cogl_winsys_context_egl_get_egl_display (CoglContext *context)
return egl_renderer->edpy;
}
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
gboolean
_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
{
/* Unsupported feature */
tex_pixmap->winsys = NULL;
return FALSE;
}
void
_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
{
/* Unsupported feature */
}
gboolean
_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
gboolean needs_mipmap)
{
/* Unsupported feature */
}
void
_cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
{
/* Unsupported feature */
}
CoglHandle
_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
{
/* Unsupported feature */
}
static CoglWinsysVtable _cogl_winsys_vtable =
{
.get_proc_address = _cogl_winsys_get_proc_address,
.renderer_connect = _cogl_winsys_renderer_connect,
.renderer_disconnect = _cogl_winsys_renderer_disconnect,
.display_setup = _cogl_winsys_display_setup,
.display_destroy = _cogl_winsys_display_destroy,
.context_init = _cogl_winsys_context_init,
.context_deinit = _cogl_winsys_context_deinit,
.context_egl_get_egl_display =
_cogl_winsys_context_egl_get_egl_display,
#ifdef COGL_HAS_XLIB_SUPPORT
.xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info,
#endif
.onscreen_init = _cogl_winsys_onscreen_init,
.onscreen_deinit = _cogl_winsys_onscreen_deinit,
.onscreen_bind = _cogl_winsys_onscreen_bind,
.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
.onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
.onscreen_update_swap_throttled =
_cogl_winsys_onscreen_update_swap_throttled,
.onscreen_x11_get_window_xid =
_cogl_winsys_onscreen_x11_get_window_xid,
.onscreen_add_swap_buffers_callback =
_cogl_winsys_onscreen_add_swap_buffers_callback,
.onscreen_remove_swap_buffers_callback =
_cogl_winsys_onscreen_remove_swap_buffers_callback,
.get_vsync_counter = _cogl_winsys_get_vsync_counter
};
/* XXX: we use a function because no doubt someone will complain
* about using c99 member initializers because they aren't portable
* to windows. We want to avoid having to rigidly follow the real
* order of members since some members are #ifdefd and we'd have
* to mirror the #ifdefing to add padding etc. For any winsys that
* can assume the platform has a sane compiler then we can just use
* c99 initializers for insane platforms they can initialize
* the members by name in a function.
*/
const CoglWinsysVtable *
_cogl_winsys_egl_get_vtable (void)
{
return &_cogl_winsys_vtable;
}

View File

@ -277,7 +277,15 @@ glx_event_filter_cb (void *native_event, void *data)
return COGL_FILTER_CONTINUE;
}
gboolean
static void
_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
{
_cogl_renderer_xlib_disconnect (renderer);
g_slice_free (CoglRendererGLX, renderer->winsys);
}
static gboolean
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
GError **error)
{
@ -325,15 +333,7 @@ error:
return FALSE;
}
void
_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
{
_cogl_renderer_xlib_disconnect (renderer);
g_slice_free (CoglRendererGLX, renderer->winsys);
}
void
static void
update_winsys_features (CoglContext *context)
{
CoglDisplayGLX *glx_display = context->display->winsys;
@ -625,32 +625,7 @@ create_context (CoglDisplay *display, GError **error)
return TRUE;
}
gboolean
_cogl_winsys_display_setup (CoglDisplay *display,
GError **error)
{
CoglDisplayGLX *glx_display;
int i;
g_return_val_if_fail (display->winsys == NULL, FALSE);
glx_display = g_slice_new0 (CoglDisplayGLX);
display->winsys = glx_display;
if (!create_context (display, error))
goto error;
for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
glx_display->glx_cached_configs[i].depth = -1;
return TRUE;
error:
_cogl_winsys_display_destroy (display);
return FALSE;
}
void
static void
_cogl_winsys_display_destroy (CoglDisplay *display)
{
CoglDisplayGLX *glx_display = display->winsys;
@ -682,7 +657,32 @@ _cogl_winsys_display_destroy (CoglDisplay *display)
display->winsys = NULL;
}
gboolean
static gboolean
_cogl_winsys_display_setup (CoglDisplay *display,
GError **error)
{
CoglDisplayGLX *glx_display;
int i;
g_return_val_if_fail (display->winsys == NULL, FALSE);
glx_display = g_slice_new0 (CoglDisplayGLX);
display->winsys = glx_display;
if (!create_context (display, error))
goto error;
for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
glx_display->glx_cached_configs[i].depth = -1;
return TRUE;
error:
_cogl_winsys_display_destroy (display);
return FALSE;
}
static gboolean
_cogl_winsys_context_init (CoglContext *context, GError **error)
{
context->winsys = g_new0 (CoglContextGLX, 1);
@ -695,7 +695,7 @@ _cogl_winsys_context_init (CoglContext *context, GError **error)
return TRUE;
}
void
static void
_cogl_winsys_context_deinit (CoglContext *context)
{
cogl_renderer_remove_native_filter (context->display->renderer,
@ -704,7 +704,7 @@ _cogl_winsys_context_deinit (CoglContext *context)
g_free (context->winsys);
}
gboolean
static gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
GError **error)
{
@ -859,7 +859,7 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
return TRUE;
}
void
static void
_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@ -890,7 +890,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
_cogl_xlib_untrap_errors (&old_state);
}
void
static void
_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@ -1002,7 +1002,7 @@ drm_wait_vblank (int fd, drm_wait_vblank_t *vbl)
}
#endif /* HAVE_DRM */
void
static void
_cogl_winsys_wait_for_vblank (void)
{
CoglRendererGLX *glx_renderer;
@ -1034,7 +1034,22 @@ _cogl_winsys_wait_for_vblank (void)
#endif /* HAVE_DRM */
}
void
static guint32
_cogl_winsys_get_vsync_counter (void)
{
guint32 video_sync_count;
CoglRendererGLX *glx_renderer;
_COGL_GET_CONTEXT (ctx, 0);
glx_renderer = ctx->display->renderer->winsys;
glx_renderer->pf_glXGetVideoSync (&video_sync_count);
return video_sync_count;
}
static void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
int *rectangles,
int n_rectangles)
@ -1167,22 +1182,7 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
glx_onscreen->last_swap_vsync_counter = end_frame_vsync_counter;
}
guint32
_cogl_winsys_get_vsync_counter (void)
{
guint32 video_sync_count;
CoglRendererGLX *glx_renderer;
_COGL_GET_CONTEXT (ctx, 0);
glx_renderer = ctx->display->renderer->winsys;
glx_renderer->pf_glXGetVideoSync (&video_sync_count);
return video_sync_count;
}
void
static void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@ -1259,14 +1259,14 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
glx_onscreen->last_swap_vsync_counter = _cogl_winsys_get_vsync_counter ();
}
guint32
static guint32
_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
{
CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
return xlib_onscreen->xwin;
}
unsigned int
static unsigned int
_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
CoglSwapBuffersNotify callback,
void *user_data)
@ -1285,7 +1285,7 @@ _cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
return entry->id;
}
void
static void
_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
unsigned int id)
{
@ -1305,7 +1305,7 @@ _cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
}
}
void
static void
_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
@ -1323,7 +1323,7 @@ _cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
}
/* XXX: This is a particularly hacky _cogl_winsys interface... */
XVisualInfo *
static XVisualInfo *
_cogl_winsys_xlib_get_visual_info (void)
{
CoglDisplayGLX *glx_display;
@ -1616,7 +1616,7 @@ try_create_glx_pixmap (CoglContext *context,
return TRUE;
}
gboolean
static gboolean
_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
{
CoglTexturePixmapGLX *glx_tex_pixmap;
@ -1697,7 +1697,7 @@ free_glx_pixmap (CoglContext *context,
glx_tex_pixmap->pixmap_bound = FALSE;
}
void
static void
_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
{
CoglTexturePixmapGLX *glx_tex_pixmap;
@ -1720,7 +1720,7 @@ _cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
g_free (glx_tex_pixmap);
}
gboolean
static gboolean
_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
gboolean needs_mipmap)
{
@ -1861,7 +1861,7 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
return TRUE;
}
void
static void
_cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
{
CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
@ -1869,10 +1869,66 @@ _cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
glx_tex_pixmap->bind_tex_image_queued = TRUE;
}
CoglHandle
static CoglHandle
_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
{
CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
return glx_tex_pixmap->glx_tex;
}
static CoglWinsysVtable _cogl_winsys_vtable =
{
.get_proc_address = _cogl_winsys_get_proc_address,
.renderer_connect = _cogl_winsys_renderer_connect,
.renderer_disconnect = _cogl_winsys_renderer_disconnect,
.display_setup = _cogl_winsys_display_setup,
.display_destroy = _cogl_winsys_display_destroy,
.context_init = _cogl_winsys_context_init,
.context_deinit = _cogl_winsys_context_deinit,
.xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info,
.onscreen_init = _cogl_winsys_onscreen_init,
.onscreen_deinit = _cogl_winsys_onscreen_deinit,
.onscreen_bind = _cogl_winsys_onscreen_bind,
.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
.onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
.onscreen_update_swap_throttled =
_cogl_winsys_onscreen_update_swap_throttled,
.onscreen_x11_get_window_xid =
_cogl_winsys_onscreen_x11_get_window_xid,
.onscreen_add_swap_buffers_callback =
_cogl_winsys_onscreen_add_swap_buffers_callback,
.onscreen_remove_swap_buffers_callback =
_cogl_winsys_onscreen_remove_swap_buffers_callback,
.get_vsync_counter = _cogl_winsys_get_vsync_counter,
/* X11 tfp support... */
/* XXX: instead of having a rather monolithic winsys vtable we could
* perhaps look for a way to separate these... */
.texture_pixmap_x11_create =
_cogl_winsys_texture_pixmap_x11_create,
.texture_pixmap_x11_free =
_cogl_winsys_texture_pixmap_x11_free,
.texture_pixmap_x11_update =
_cogl_winsys_texture_pixmap_x11_update,
.texture_pixmap_x11_damage_notify =
_cogl_winsys_texture_pixmap_x11_damage_notify,
.texture_pixmap_x11_get_texture =
_cogl_winsys_texture_pixmap_x11_get_texture,
};
/* XXX: we use a function because no doubt someone will complain
* about using c99 member initializers because they aren't portable
* to windows. We want to avoid having to rigidly follow the real
* order of members since some members are #ifdefd and we'd have
* to mirror the #ifdefing to add padding etc. For any winsys that
* can assume the platform has a sane compiler then we can just use
* c99 initializers for insane platforms they can initialize
* the members by name in a function.
*/
const CoglWinsysVtable *
_cogl_winsys_glx_get_vtable (void)
{
return &_cogl_winsys_vtable;
}

View File

@ -31,6 +31,7 @@
#ifdef COGL_HAS_XLIB_SUPPORT
#include <X11/Xutil.h>
#include "cogl-texture-pixmap-x11-private.h"
#endif
GQuark
@ -51,95 +52,94 @@ typedef enum
COGL_WINSYS_RECTANGLE_STATE_ENABLE
} CoglWinsysRectangleState;
CoglFuncPtr
_cogl_winsys_get_proc_address (const char *name);
typedef struct _CoglWinsysVtable
{
CoglFuncPtr
(*get_proc_address) (const char *name);
gboolean
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
GError **error);
gboolean
(*renderer_connect) (CoglRenderer *renderer, GError **error);
void
_cogl_winsys_renderer_disconnect (CoglRenderer *renderer);
void
(*renderer_disconnect) (CoglRenderer *renderer);
gboolean
_cogl_winsys_display_setup (CoglDisplay *display,
GError **error);
gboolean
(*display_setup) (CoglDisplay *display, GError **error);
void
_cogl_winsys_display_destroy (CoglDisplay *display);
void
(*display_destroy) (CoglDisplay *display);
gboolean
_cogl_winsys_context_init (CoglContext *context, GError **error);
gboolean
(*context_init) (CoglContext *context, GError **error);
void
_cogl_winsys_context_deinit (CoglContext *context);
void
(*context_deinit) (CoglContext *context);
#ifdef COGL_HAS_EGL_SUPPORT
EGLDisplay
_cogl_winsys_context_egl_get_egl_display (CoglContext *context);
EGLDisplay
(*context_egl_get_egl_display) (CoglContext *context);
#endif
gboolean
_cogl_winsys_has_feature (CoglWinsysFeature feature);
gboolean
(*has_feature) (CoglWinsysFeature feature);
#ifdef COGL_HAS_XLIB_SUPPORT
XVisualInfo *
_cogl_winsys_xlib_get_visual_info (void);
XVisualInfo *
(*xlib_get_visual_info) (void);
#endif
gboolean
_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
GError **error);
gboolean
(*onscreen_init) (CoglOnscreen *onscreen, GError **error);
void
_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen);
void
(*onscreen_deinit) (CoglOnscreen *onscreen);
void
_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen);
void
(*onscreen_bind) (CoglOnscreen *onscreen);
void
_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen);
void
(*onscreen_swap_buffers) (CoglOnscreen *onscreen);
void
_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
void
(*onscreen_swap_region) (CoglOnscreen *onscreen,
int *rectangles,
int n_rectangles);
void
_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen);
void
(*onscreen_update_swap_throttled) (CoglOnscreen *onscreen);
guint32
_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen);
guint32
(*onscreen_x11_get_window_xid) (CoglOnscreen *onscreen);
guint32
_cogl_winsys_get_vsync_counter (void);
unsigned int
_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
unsigned int
(*onscreen_add_swap_buffers_callback) (CoglOnscreen *onscreen,
CoglSwapBuffersNotify callback,
void *user_data);
void
_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
void
(*onscreen_remove_swap_buffers_callback) (CoglOnscreen *onscreen,
unsigned int id);
guint32
(*get_vsync_counter) (void);
#ifdef COGL_HAS_XLIB_SUPPORT
gboolean
_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap);
gboolean
(*texture_pixmap_x11_create) (CoglTexturePixmapX11 *tex_pixmap);
void
(*texture_pixmap_x11_free) (CoglTexturePixmapX11 *tex_pixmap);
void
_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap);
gboolean
_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
gboolean
(*texture_pixmap_x11_update) (CoglTexturePixmapX11 *tex_pixmap,
gboolean needs_mipmap);
void
_cogl_winsys_texture_pixmap_x11_damage_notify (
CoglTexturePixmapX11 *tex_pixmap);
void
(*texture_pixmap_x11_damage_notify) (CoglTexturePixmapX11 *tex_pixmap);
CoglHandle
_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap);
CoglHandle
(*texture_pixmap_x11_get_texture) (CoglTexturePixmapX11 *tex_pixmap);
#endif
} CoglWinsysVtable;
#endif /* __COGL_WINSYS_PRIVATE_H */