CoglTexturePixmapX11: add support for stereo content

Add cogl_texture_pixmap_x11_new_left() and
cogl_texture_pixmap_x11_new_right() (which takes the left texture
as an argument) for texture pixmap rendering with stereo content.
The underlying GLXPixmap is created using a stereo visual and shared
between the left and right textures.

Reviewed-by: Robert Bragg <robert.bragg@intel.com>
This commit is contained in:
Owen W. Taylor 2014-04-26 16:38:58 -04:00
parent 1b5beef5e5
commit 4d8771a8c2
7 changed files with 253 additions and 44 deletions

View File

@ -39,10 +39,11 @@ typedef struct _CoglGLXCachedConfig
int depth; int depth;
CoglBool found; CoglBool found;
GLXFBConfig fb_config; GLXFBConfig fb_config;
CoglBool stereo;
CoglBool can_mipmap; CoglBool can_mipmap;
} CoglGLXCachedConfig; } CoglGLXCachedConfig;
#define COGL_GLX_N_CACHED_CONFIGS 3 #define COGL_GLX_N_CACHED_CONFIGS 6
typedef struct _CoglGLXDisplay typedef struct _CoglGLXDisplay
{ {

View File

@ -55,10 +55,27 @@ struct _CoglDamageRectangle
unsigned int y2; unsigned int y2;
}; };
/* For stereo, there are a pair of textures, but we want to share most
* other state (the GLXPixmap, visual, etc.) The way we do this is that
* the left-eye texture has all the state (there is in fact, no internal
* difference between the a MONO and a LEFT texture ), and the
* right-eye texture simply points to the left eye texture, with all
* other fields ignored.
*/
typedef enum
{
COGL_TEXTURE_PIXMAP_MONO,
COGL_TEXTURE_PIXMAP_LEFT,
COGL_TEXTURE_PIXMAP_RIGHT
} CoglTexturePixmapStereoMode;
struct _CoglTexturePixmapX11 struct _CoglTexturePixmapX11
{ {
CoglTexture _parent; CoglTexture _parent;
CoglTexturePixmapStereoMode stereo_mode;
CoglTexturePixmapX11 *left; /* Set only if stereo_mode=RIGHT */
Pixmap pixmap; Pixmap pixmap;
CoglTexture *tex; CoglTexture *tex;
@ -82,4 +99,5 @@ struct _CoglTexturePixmapX11
CoglBool use_winsys_texture; CoglBool use_winsys_texture;
}; };
#endif /* __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H */ #endif /* __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H */

View File

@ -284,10 +284,11 @@ set_damage_object_internal (CoglContext *ctx,
tex_pixmap); tex_pixmap);
} }
CoglTexturePixmapX11 * static CoglTexturePixmapX11 *
cogl_texture_pixmap_x11_new (CoglContext *ctxt, _cogl_texture_pixmap_x11_new (CoglContext *ctxt,
uint32_t pixmap, uint32_t pixmap,
CoglBool automatic_updates, CoglBool automatic_updates,
CoglTexturePixmapStereoMode stereo_mode,
CoglError **error) CoglError **error)
{ {
CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1); CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1);
@ -327,6 +328,8 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
&cogl_texture_pixmap_x11_vtable); &cogl_texture_pixmap_x11_vtable);
tex_pixmap->pixmap = pixmap; tex_pixmap->pixmap = pixmap;
tex_pixmap->stereo_mode = stereo_mode;
tex_pixmap->left = NULL;
tex_pixmap->image = NULL; tex_pixmap->image = NULL;
tex_pixmap->shm_info.shmid = -1; tex_pixmap->shm_info.shmid = -1;
tex_pixmap->tex = NULL; tex_pixmap->tex = NULL;
@ -387,6 +390,59 @@ cogl_texture_pixmap_x11_new (CoglContext *ctxt,
return _cogl_texture_pixmap_x11_object_new (tex_pixmap); return _cogl_texture_pixmap_x11_object_new (tex_pixmap);
} }
CoglTexturePixmapX11 *
cogl_texture_pixmap_x11_new (CoglContext *ctxt,
uint32_t pixmap,
CoglBool automatic_updates,
CoglError **error)
{
return _cogl_texture_pixmap_x11_new (ctxt, pixmap,
automatic_updates, COGL_TEXTURE_PIXMAP_MONO,
error);
}
CoglTexturePixmapX11 *
cogl_texture_pixmap_x11_new_left (CoglContext *ctxt,
uint32_t pixmap,
CoglBool automatic_updates,
CoglError **error)
{
return _cogl_texture_pixmap_x11_new (ctxt, pixmap,
automatic_updates, COGL_TEXTURE_PIXMAP_LEFT,
error);
}
CoglTexturePixmapX11 *
cogl_texture_pixmap_x11_new_right (CoglTexturePixmapX11 *tfp_left)
{
CoglTexture *texture_left = COGL_TEXTURE (tfp_left);
CoglTexturePixmapX11 *tfp_right;
CoglPixelFormat internal_format;
g_return_val_if_fail (tfp_left->stereo_mode == COGL_TEXTURE_PIXMAP_LEFT, NULL);
tfp_right = g_new0 (CoglTexturePixmapX11, 1);
tfp_right->stereo_mode = COGL_TEXTURE_PIXMAP_RIGHT;
tfp_right->left = cogl_object_ref (tfp_left);
internal_format = (tfp_left->depth >= 32
? COGL_PIXEL_FORMAT_RGBA_8888_PRE
: COGL_PIXEL_FORMAT_RGB_888);
_cogl_texture_init (COGL_TEXTURE (tfp_right),
texture_left->context,
texture_left->width,
texture_left->height,
internal_format,
NULL, /* no loader */
&cogl_texture_pixmap_x11_vtable);
_cogl_texture_set_allocated (COGL_TEXTURE (tfp_right), internal_format,
texture_left->width, texture_left->height);
return _cogl_texture_pixmap_x11_object_new (tfp_right);
}
static CoglBool static CoglBool
_cogl_texture_pixmap_x11_allocate (CoglTexture *tex, _cogl_texture_pixmap_x11_allocate (CoglTexture *tex,
CoglError **error) CoglError **error)
@ -478,6 +534,9 @@ cogl_texture_pixmap_x11_update_area (CoglTexturePixmapX11 *tex_pixmap,
texture because we can't determine which will be needed until we texture because we can't determine which will be needed until we
actually render something */ actually render something */
if (tex_pixmap->stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
tex_pixmap = tex_pixmap->left;
if (tex_pixmap->winsys) if (tex_pixmap->winsys)
{ {
const CoglWinsysVtable *winsys; const CoglWinsysVtable *winsys;
@ -492,6 +551,9 @@ cogl_texture_pixmap_x11_update_area (CoglTexturePixmapX11 *tex_pixmap,
CoglBool CoglBool
cogl_texture_pixmap_x11_is_using_tfp_extension (CoglTexturePixmapX11 *tex_pixmap) cogl_texture_pixmap_x11_is_using_tfp_extension (CoglTexturePixmapX11 *tex_pixmap)
{ {
if (tex_pixmap->stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
tex_pixmap = tex_pixmap->left;
return !!tex_pixmap->winsys; return !!tex_pixmap->winsys;
} }
@ -505,6 +567,8 @@ cogl_texture_pixmap_x11_set_damage_object (CoglTexturePixmapX11 *tex_pixmap,
_COGL_GET_CONTEXT (ctxt, NO_RETVAL); _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
g_return_if_fail (tex_pixmap->stereo_mode != COGL_TEXTURE_PIXMAP_RIGHT);
damage_base = _cogl_xlib_get_damage_base (); damage_base = _cogl_xlib_get_damage_base ();
if (damage_base >= 0) if (damage_base >= 0)
set_damage_object_internal (ctxt, tex_pixmap, damage, report_level); set_damage_object_internal (ctxt, tex_pixmap, damage, report_level);
@ -717,12 +781,16 @@ static void
_cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap, _cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
CoglBool needs_mipmap) CoglBool needs_mipmap)
{ {
CoglTexturePixmapStereoMode stereo_mode = tex_pixmap->stereo_mode;
if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
tex_pixmap = tex_pixmap->left;
if (tex_pixmap->winsys) if (tex_pixmap->winsys)
{ {
const CoglWinsysVtable *winsys = const CoglWinsysVtable *winsys =
_cogl_texture_pixmap_x11_get_winsys (tex_pixmap); _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
if (winsys->texture_pixmap_x11_update (tex_pixmap, needs_mipmap)) if (winsys->texture_pixmap_x11_update (tex_pixmap, stereo_mode, needs_mipmap))
{ {
_cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE); _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE);
return; return;
@ -739,8 +807,13 @@ _cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
static CoglTexture * static CoglTexture *
_cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap) _cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
{ {
CoglTexturePixmapX11 *original_pixmap = tex_pixmap;
CoglTexture *tex; CoglTexture *tex;
int i; int i;
CoglTexturePixmapStereoMode stereo_mode = tex_pixmap->stereo_mode;
if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
tex_pixmap = tex_pixmap->left;
/* We try getting the texture twice, once without flushing the /* We try getting the texture twice, once without flushing the
updates and once with. If pre_paint has been called already then updates and once with. If pre_paint has been called already then
@ -757,7 +830,7 @@ _cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
{ {
const CoglWinsysVtable *winsys = const CoglWinsysVtable *winsys =
_cogl_texture_pixmap_x11_get_winsys (tex_pixmap); _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap); tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap, stereo_mode);
} }
else else
tex = tex_pixmap->tex; tex = tex_pixmap->tex;
@ -765,7 +838,7 @@ _cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
if (tex) if (tex)
return tex; return tex;
_cogl_texture_pixmap_x11_update (tex_pixmap, FALSE); _cogl_texture_pixmap_x11_update (original_pixmap, FALSE);
} }
g_assert_not_reached (); g_assert_not_reached ();
@ -1047,6 +1120,16 @@ _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
_COGL_GET_CONTEXT (ctxt, NO_RETVAL); _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
if (tex_pixmap->stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
{
cogl_object_unref (tex_pixmap->left);
/* Chain up */
_cogl_texture_free (COGL_TEXTURE (tex_pixmap));
return;
}
display = cogl_xlib_renderer_get_display (ctxt->display->renderer); display = cogl_xlib_renderer_get_display (ctxt->display->renderer);
set_damage_object_internal (ctxt, tex_pixmap, 0, 0); set_damage_object_internal (ctxt, tex_pixmap, 0, 0);

View File

@ -137,6 +137,62 @@ cogl_texture_pixmap_x11_new (CoglContext *context,
CoglBool automatic_updates, CoglBool automatic_updates,
CoglError **error); CoglError **error);
/**
* cogl_texture_pixmap_x11_new_left:
* @context: A #CoglContext
* @pixmap: A X11 pixmap ID
* @automatic_updates: Whether to automatically copy the contents of
* the pixmap to the texture.
* @error: A #CoglError for exceptions
*
* Creates one of a pair of textures to contain the contents of @pixmap,
* which has stereo content. (Different images for the right and left eyes.)
* The left image is drawn using this texture; the right image is drawn
* using a texture created by calling
* cogl_texture_pixmap_x11_new_right() and passing in this texture as an
* argument.
*
* In general, you should not use this function unless you have
* queried the %GLX_STEREO_TREE_EXT attribute of the corresponding
* window using glXQueryDrawable() and determined that the window is
* stereo. Note that this attribute can change over time and
* notification is also provided through events defined in the
* EXT_stereo_tree GLX extension. As long as the system has support for
* stereo content, drawing using the left and right pixmaps will not
* produce an error even if the window doesn't have stereo
* content any more, but drawing with the right pixmap will produce
* undefined output, so you need to listen for these events and
* re-render to avoid race conditions. (Recreating a non-stereo
* pixmap is not necessary, but may save resources.)
*
* Return value: a new #CoglTexturePixmapX11 instance
*
* Since: 1.20
* Stability: Unstable
*/
CoglTexturePixmapX11 *
cogl_texture_pixmap_x11_new_left (CoglContext *context,
uint32_t pixmap,
CoglBool automatic_updates,
CoglError **error);
/**
* cogl_texture_pixmap_x11_new_right:
* @left_texture: A #CoglTexturePixmapX11 instance created with
* cogl_texture_pixmap_x11_new_left().
*
* Creates a texture object that corresponds to the right-eye image
* of a pixmap with stereo content. @left_texture must have been
* created using cogl_texture_pixmap_x11_new_left().
*
* Return value: a new #CoglTexturePixmapX11 instance
*
* Since: 1.20
* Stability: Unstable
*/
CoglTexturePixmapX11 *
cogl_texture_pixmap_x11_new_right (CoglTexturePixmapX11 *left_texture);
/** /**
* cogl_texture_pixmap_x11_update_area: * cogl_texture_pixmap_x11_update_area:
* @texture: A #CoglTexturePixmapX11 instance * @texture: A #CoglTexturePixmapX11 instance

View File

@ -784,6 +784,7 @@ _cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
static CoglBool static CoglBool
_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap, _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
CoglBool right,
CoglBool needs_mipmap) CoglBool needs_mipmap)
{ {
if (needs_mipmap) if (needs_mipmap)
@ -798,7 +799,8 @@ _cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
} }
static CoglTexture * static CoglTexture *
_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap) _cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap,
CoglBool right)
{ {
CoglTexturePixmapEGL *egl_tex_pixmap = tex_pixmap->winsys; CoglTexturePixmapEGL *egl_tex_pixmap = tex_pixmap->winsys;

View File

@ -97,16 +97,21 @@ typedef struct _CoglOnscreenGLX
CoglBool pending_resize_notify; CoglBool pending_resize_notify;
} CoglOnscreenGLX; } CoglOnscreenGLX;
typedef struct _CoglPixmapTextureEyeGLX
{
CoglTexture *glx_tex;
CoglBool bind_tex_image_queued;
CoglBool pixmap_bound;
} CoglPixmapTextureEyeGLX;
typedef struct _CoglTexturePixmapGLX typedef struct _CoglTexturePixmapGLX
{ {
GLXPixmap glx_pixmap; GLXPixmap glx_pixmap;
CoglBool has_mipmap_space; CoglBool has_mipmap_space;
CoglBool can_mipmap; CoglBool can_mipmap;
CoglTexture *glx_tex; CoglPixmapTextureEyeGLX left;
CoglPixmapTextureEyeGLX right;
CoglBool bind_tex_image_queued;
CoglBool pixmap_bound;
} CoglTexturePixmapGLX; } CoglTexturePixmapGLX;
/* Define a set of arrays containing the functions required from GL /* Define a set of arrays containing the functions required from GL
@ -2101,6 +2106,7 @@ _cogl_winsys_xlib_get_visual_info (void)
static CoglBool static CoglBool
get_fbconfig_for_depth (CoglContext *context, get_fbconfig_for_depth (CoglContext *context,
unsigned int depth, unsigned int depth,
CoglBool stereo,
GLXFBConfig *fbconfig_ret, GLXFBConfig *fbconfig_ret,
CoglBool *can_mipmap_ret) CoglBool *can_mipmap_ret)
{ {
@ -2118,11 +2124,12 @@ get_fbconfig_for_depth (CoglContext *context,
glx_renderer = context->display->renderer->winsys; glx_renderer = context->display->renderer->winsys;
glx_display = context->display->winsys; glx_display = context->display->winsys;
/* Check if we've already got a cached config for this depth */ /* Check if we've already got a cached config for this depth and stereo */
for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++) for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
if (glx_display->glx_cached_configs[i].depth == -1) if (glx_display->glx_cached_configs[i].depth == -1)
spare_cache_slot = i; spare_cache_slot = i;
else if (glx_display->glx_cached_configs[i].depth == depth) else if (glx_display->glx_cached_configs[i].depth == depth &&
glx_display->glx_cached_configs[i].stereo == stereo)
{ {
*fbconfig_ret = glx_display->glx_cached_configs[i].fb_config; *fbconfig_ret = glx_display->glx_cached_configs[i].fb_config;
*can_mipmap_ret = glx_display->glx_cached_configs[i].can_mipmap; *can_mipmap_ret = glx_display->glx_cached_configs[i].can_mipmap;
@ -2166,6 +2173,13 @@ get_fbconfig_for_depth (CoglContext *context,
if (value != depth && (value - alpha) != depth) if (value != depth && (value - alpha) != depth)
continue; continue;
glx_renderer->glXGetFBConfigAttrib (dpy,
fbconfigs[i],
GLX_STEREO,
&value);
if (!!value != !!stereo)
continue;
if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 4) if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 4)
{ {
glx_renderer->glXGetFBConfigAttrib (dpy, glx_renderer->glXGetFBConfigAttrib (dpy,
@ -2323,7 +2337,9 @@ try_create_glx_pixmap (CoglContext *context,
glx_renderer = renderer->winsys; glx_renderer = renderer->winsys;
dpy = xlib_renderer->xdpy; dpy = xlib_renderer->xdpy;
if (!get_fbconfig_for_depth (context, depth, &fb_config, if (!get_fbconfig_for_depth (context, depth,
tex_pixmap->stereo_mode != COGL_TEXTURE_PIXMAP_MONO,
&fb_config,
&glx_tex_pixmap->can_mipmap)) &glx_tex_pixmap->can_mipmap))
{ {
COGL_NOTE (TEXTURE_PIXMAP, "No suitable FBConfig found for depth %i", COGL_NOTE (TEXTURE_PIXMAP, "No suitable FBConfig found for depth %i",
@ -2412,10 +2428,13 @@ _cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
glx_tex_pixmap->can_mipmap = FALSE; glx_tex_pixmap->can_mipmap = FALSE;
glx_tex_pixmap->has_mipmap_space = FALSE; glx_tex_pixmap->has_mipmap_space = FALSE;
glx_tex_pixmap->glx_tex = NULL; glx_tex_pixmap->left.glx_tex = NULL;
glx_tex_pixmap->right.glx_tex = NULL;
glx_tex_pixmap->bind_tex_image_queued = TRUE; glx_tex_pixmap->left.bind_tex_image_queued = TRUE;
glx_tex_pixmap->pixmap_bound = FALSE; glx_tex_pixmap->right.bind_tex_image_queued = TRUE;
glx_tex_pixmap->left.pixmap_bound = FALSE;
glx_tex_pixmap->right.pixmap_bound = FALSE;
tex_pixmap->winsys = glx_tex_pixmap; tex_pixmap->winsys = glx_tex_pixmap;
@ -2442,10 +2461,14 @@ free_glx_pixmap (CoglContext *context,
xlib_renderer = _cogl_xlib_renderer_get_data (renderer); xlib_renderer = _cogl_xlib_renderer_get_data (renderer);
glx_renderer = renderer->winsys; glx_renderer = renderer->winsys;
if (glx_tex_pixmap->pixmap_bound) if (glx_tex_pixmap->left.pixmap_bound)
glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy, glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy,
glx_tex_pixmap->glx_pixmap, glx_tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT); GLX_FRONT_LEFT_EXT);
if (glx_tex_pixmap->right.pixmap_bound)
glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy,
glx_tex_pixmap->glx_pixmap,
GLX_FRONT_RIGHT_EXT);
/* FIXME - we need to trap errors and synchronize here because /* FIXME - we need to trap errors and synchronize here because
* of ordering issues between the XPixmap destruction and the * of ordering issues between the XPixmap destruction and the
@ -2470,7 +2493,8 @@ free_glx_pixmap (CoglContext *context,
_cogl_xlib_renderer_untrap_errors (renderer, &trap_state); _cogl_xlib_renderer_untrap_errors (renderer, &trap_state);
glx_tex_pixmap->glx_pixmap = None; glx_tex_pixmap->glx_pixmap = None;
glx_tex_pixmap->pixmap_bound = FALSE; glx_tex_pixmap->left.pixmap_bound = FALSE;
glx_tex_pixmap->right.pixmap_bound = FALSE;
} }
static void static void
@ -2485,8 +2509,11 @@ _cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
free_glx_pixmap (COGL_TEXTURE (tex_pixmap)->context, glx_tex_pixmap); free_glx_pixmap (COGL_TEXTURE (tex_pixmap)->context, glx_tex_pixmap);
if (glx_tex_pixmap->glx_tex) if (glx_tex_pixmap->left.glx_tex)
cogl_object_unref (glx_tex_pixmap->glx_tex); cogl_object_unref (glx_tex_pixmap->left.glx_tex);
if (glx_tex_pixmap->right.glx_tex)
cogl_object_unref (glx_tex_pixmap->right.glx_tex);
tex_pixmap->winsys = NULL; tex_pixmap->winsys = NULL;
g_free (glx_tex_pixmap); g_free (glx_tex_pixmap);
@ -2494,13 +2521,27 @@ _cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
static CoglBool static CoglBool
_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap, _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
CoglTexturePixmapStereoMode stereo_mode,
CoglBool needs_mipmap) CoglBool needs_mipmap)
{ {
CoglTexture *tex = COGL_TEXTURE (tex_pixmap); CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
CoglContext *ctx = COGL_TEXTURE (tex_pixmap)->context; CoglContext *ctx = COGL_TEXTURE (tex_pixmap)->context;
CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
CoglPixmapTextureEyeGLX *texture_info;
int buffer;
CoglGLXRenderer *glx_renderer; CoglGLXRenderer *glx_renderer;
if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
{
texture_info = &glx_tex_pixmap->right;
buffer = GLX_FRONT_RIGHT_EXT;
}
else
{
texture_info = &glx_tex_pixmap->left;
buffer = GLX_FRONT_LEFT_EXT;
}
/* If we don't have a GLX pixmap then fallback */ /* If we don't have a GLX pixmap then fallback */
if (glx_tex_pixmap->glx_pixmap == None) if (glx_tex_pixmap->glx_pixmap == None)
return FALSE; return FALSE;
@ -2508,7 +2549,7 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
glx_renderer = ctx->display->renderer->winsys; glx_renderer = ctx->display->renderer->winsys;
/* Lazily create a texture to hold the pixmap */ /* Lazily create a texture to hold the pixmap */
if (glx_tex_pixmap->glx_tex == NULL) if (texture_info->glx_tex == NULL)
{ {
CoglPixelFormat texture_format; CoglPixelFormat texture_format;
CoglError *error = NULL; CoglError *error = NULL;
@ -2519,14 +2560,14 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
if (should_use_rectangle (ctx)) if (should_use_rectangle (ctx))
{ {
glx_tex_pixmap->glx_tex = COGL_TEXTURE ( texture_info->glx_tex = COGL_TEXTURE (
cogl_texture_rectangle_new_with_size (ctx, cogl_texture_rectangle_new_with_size (ctx,
tex->width, tex->width,
tex->height)); tex->height));
_cogl_texture_set_internal_format (tex, texture_format); _cogl_texture_set_internal_format (tex, texture_format);
if (cogl_texture_allocate (glx_tex_pixmap->glx_tex, &error)) if (cogl_texture_allocate (texture_info->glx_tex, &error))
COGL_NOTE (TEXTURE_PIXMAP, "Created a texture rectangle for %p", COGL_NOTE (TEXTURE_PIXMAP, "Created a texture rectangle for %p",
tex_pixmap); tex_pixmap);
else else
@ -2541,14 +2582,14 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
} }
else else
{ {
glx_tex_pixmap->glx_tex = COGL_TEXTURE ( texture_info->glx_tex = COGL_TEXTURE (
cogl_texture_2d_new_with_size (ctx, cogl_texture_2d_new_with_size (ctx,
tex->width, tex->width,
tex->height)); tex->height));
_cogl_texture_set_internal_format (tex, texture_format); _cogl_texture_set_internal_format (tex, texture_format);
if (cogl_texture_allocate (glx_tex_pixmap->glx_tex, &error)) if (cogl_texture_allocate (texture_info->glx_tex, &error))
COGL_NOTE (TEXTURE_PIXMAP, "Created a texture 2d for %p", COGL_NOTE (TEXTURE_PIXMAP, "Created a texture 2d for %p",
tex_pixmap); tex_pixmap);
else else
@ -2586,36 +2627,37 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
"updates for %p because creating the GLXPixmap " "updates for %p because creating the GLXPixmap "
"with mipmap support failed", tex_pixmap); "with mipmap support failed", tex_pixmap);
if (glx_tex_pixmap->glx_tex) if (texture_info->glx_tex)
cogl_object_unref (glx_tex_pixmap->glx_tex); cogl_object_unref (texture_info->glx_tex);
return FALSE; return FALSE;
} }
glx_tex_pixmap->bind_tex_image_queued = TRUE; glx_tex_pixmap->left.bind_tex_image_queued = TRUE;
glx_tex_pixmap->right.bind_tex_image_queued = TRUE;
} }
} }
if (glx_tex_pixmap->bind_tex_image_queued) if (texture_info->bind_tex_image_queued)
{ {
GLuint gl_handle, gl_target; GLuint gl_handle, gl_target;
CoglXlibRenderer *xlib_renderer = CoglXlibRenderer *xlib_renderer =
_cogl_xlib_renderer_get_data (ctx->display->renderer); _cogl_xlib_renderer_get_data (ctx->display->renderer);
cogl_texture_get_gl_texture (glx_tex_pixmap->glx_tex, cogl_texture_get_gl_texture (texture_info->glx_tex,
&gl_handle, &gl_target); &gl_handle, &gl_target);
COGL_NOTE (TEXTURE_PIXMAP, "Rebinding GLXPixmap for %p", tex_pixmap); COGL_NOTE (TEXTURE_PIXMAP, "Rebinding GLXPixmap for %p", tex_pixmap);
_cogl_bind_gl_texture_transient (gl_target, gl_handle, FALSE); _cogl_bind_gl_texture_transient (gl_target, gl_handle, FALSE);
if (glx_tex_pixmap->pixmap_bound) if (texture_info->pixmap_bound)
glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy, glx_renderer->glXReleaseTexImage (xlib_renderer->xdpy,
glx_tex_pixmap->glx_pixmap, glx_tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT); buffer);
glx_renderer->glXBindTexImage (xlib_renderer->xdpy, glx_renderer->glXBindTexImage (xlib_renderer->xdpy,
glx_tex_pixmap->glx_pixmap, glx_tex_pixmap->glx_pixmap,
GLX_FRONT_LEFT_EXT, buffer,
NULL); NULL);
/* According to the recommended usage in the spec for /* According to the recommended usage in the spec for
@ -2628,10 +2670,10 @@ _cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
* on Mesa and NVidia drivers and it is also what Compiz does so * on Mesa and NVidia drivers and it is also what Compiz does so
* it is probably ok */ * it is probably ok */
glx_tex_pixmap->bind_tex_image_queued = FALSE; texture_info->bind_tex_image_queued = FALSE;
glx_tex_pixmap->pixmap_bound = TRUE; texture_info->pixmap_bound = TRUE;
_cogl_texture_2d_externally_modified (glx_tex_pixmap->glx_tex); _cogl_texture_2d_externally_modified (texture_info->glx_tex);
} }
return TRUE; return TRUE;
@ -2642,15 +2684,20 @@ _cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
{ {
CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
glx_tex_pixmap->bind_tex_image_queued = TRUE; glx_tex_pixmap->left.bind_tex_image_queued = TRUE;
glx_tex_pixmap->right.bind_tex_image_queued = TRUE;
} }
static CoglTexture * static CoglTexture *
_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap) _cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap,
CoglTexturePixmapStereoMode stereo_mode)
{ {
CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys; CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
return glx_tex_pixmap->glx_tex; if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
return glx_tex_pixmap->right.glx_tex;
else
return glx_tex_pixmap->left.glx_tex;
} }
static CoglWinsysVtable _cogl_winsys_vtable = static CoglWinsysVtable _cogl_winsys_vtable =

View File

@ -166,13 +166,15 @@ typedef struct _CoglWinsysVtable
CoglBool CoglBool
(*texture_pixmap_x11_update) (CoglTexturePixmapX11 *tex_pixmap, (*texture_pixmap_x11_update) (CoglTexturePixmapX11 *tex_pixmap,
CoglTexturePixmapStereoMode stereo_mode,
CoglBool needs_mipmap); CoglBool needs_mipmap);
void void
(*texture_pixmap_x11_damage_notify) (CoglTexturePixmapX11 *tex_pixmap); (*texture_pixmap_x11_damage_notify) (CoglTexturePixmapX11 *tex_pixmap);
CoglTexture * CoglTexture *
(*texture_pixmap_x11_get_texture) (CoglTexturePixmapX11 *tex_pixmap); (*texture_pixmap_x11_get_texture) (CoglTexturePixmapX11 *tex_pixmap,
CoglTexturePixmapStereoMode stereo_mode);
#endif #endif
void void