Commit 3ed9eb36 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

xcb/glx: reuse the GLX provider code and eliminate a lot of code

parent 26a023d8
...@@ -29,12 +29,9 @@ ...@@ -29,12 +29,9 @@
#include <assert.h> #include <assert.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_plugin.h> #include <vlc_plugin.h>
#include <vlc_xlib.h>
#include <vlc_vout_display.h> #include <vlc_vout_display.h>
#include <vlc_opengl.h> #include <vlc_opengl.h>
#include "../opengl.h" #include "../opengl.h"
...@@ -60,17 +57,13 @@ vlc_module_end () ...@@ -60,17 +57,13 @@ vlc_module_end ()
struct vout_display_sys_t struct vout_display_sys_t
{ {
Display *display; /* Xlib instance */
xcb_connection_t *conn; /**< XCB connection */ xcb_connection_t *conn; /**< XCB connection */
vout_window_t *embed; /* VLC window (when windowed) */ vout_window_t *embed; /* VLC window (when windowed) */
vlc_gl_t *gl;
xcb_cursor_t cursor; /* blank cursor */ xcb_cursor_t cursor; /* blank cursor */
xcb_window_t window; /* drawable X window */
xcb_window_t glwin; /* GLX window */
bool visible; /* whether to draw */ bool visible; /* whether to draw */
GLXContext ctx;
vlc_gl_t gl;
vout_display_opengl_t *vgl; vout_display_opengl_t *vgl;
picture_pool_t *pool; /* picture pool */ picture_pool_t *pool; /* picture pool */
}; };
...@@ -81,100 +74,19 @@ static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *); ...@@ -81,100 +74,19 @@ static void PictureDisplay (vout_display_t *, picture_t *, subpicture_t *);
static int Control (vout_display_t *, int, va_list); static int Control (vout_display_t *, int, va_list);
static void Manage (vout_display_t *); static void Manage (vout_display_t *);
static void SwapBuffers (vlc_gl_t *gl);
static void *GetProcAddress (vlc_gl_t *gl, const char *);
static unsigned GetScreenNumber (xcb_connection_t *conn,
const xcb_screen_t *screen)
{
const xcb_setup_t *setup = xcb_get_setup (conn);
unsigned num = 0;
for (xcb_screen_iterator_t i = xcb_setup_roots_iterator (setup);;
xcb_screen_next (&i))
{
if (i.data->root == screen->root)
return num;
num++;
}
}
static bool CheckGLX (vout_display_t *vd, Display *dpy)
{
int major, minor;
bool ok = false;
if (!glXQueryVersion (dpy, &major, &minor))
msg_Dbg (vd, "GLX extension not available");
else
if (major != 1)
msg_Dbg (vd, "GLX extension version %d.%d unknown", major, minor);
else
if (minor < 3)
msg_Dbg (vd, "GLX extension version %d.%d too old", major, minor);
else
{
msg_Dbg (vd, "using GLX extension version %d.%d", major, minor);
ok = true;
}
return ok;
}
static int CreateWindow (vout_display_t *vd, xcb_connection_t *conn,
const xcb_screen_t *screen,
uint_fast16_t width, uint_fast16_t height)
{
vout_display_sys_t *sys = vd->sys;
xcb_pixmap_t pixmap = xcb_generate_id (conn);
const uint32_t mask =
XCB_CW_BACK_PIXMAP |
XCB_CW_BACK_PIXEL |
XCB_CW_BORDER_PIXMAP |
XCB_CW_BORDER_PIXEL |
XCB_CW_EVENT_MASK |
XCB_CW_COLORMAP;
const uint32_t values[] = {
pixmap,
screen->black_pixel,
pixmap,
screen->black_pixel,
XCB_EVENT_MASK_VISIBILITY_CHANGE,
screen->default_colormap,
};
xcb_void_cookie_t cc, cm;
xcb_create_pixmap (conn, screen->root_depth, pixmap, screen->root, 1, 1);
cc = xcb_create_window_checked (conn, screen->root_depth, sys->window,
sys->embed->handle.xid, 0, 0,
width, height, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
screen->root_visual, mask, values);
cm = xcb_map_window_checked (conn, sys->window);
if (XCB_error_Check (vd, conn, "cannot create X11 window", cc)
|| XCB_error_Check (vd, conn, "cannot map X11 window", cm))
return VLC_EGENERIC;
msg_Dbg (vd, "using X11 window %08"PRIx32, sys->window);
return VLC_SUCCESS;
}
/** /**
* Probe the X server. * Probe the X server.
*/ */
static int Open (vlc_object_t *obj) static int Open (vlc_object_t *obj)
{ {
if (!vlc_xlib_init (obj))
return VLC_EGENERIC;
vout_display_t *vd = (vout_display_t *)obj; vout_display_t *vd = (vout_display_t *)obj;
vout_display_sys_t *sys = malloc (sizeof (*sys)); vout_display_sys_t *sys = malloc (sizeof (*sys));
if (sys == NULL) if (sys == NULL)
return VLC_ENOMEM; return VLC_ENOMEM;
vd->sys = sys; sys->vgl = NULL;
sys->pool = NULL; sys->pool = NULL;
sys->gl.sys = NULL;
/* Get window, connect to X server (via XCB) */ /* Get window, connect to X server (via XCB) */
xcb_connection_t *conn; xcb_connection_t *conn;
...@@ -186,142 +98,30 @@ static int Open (vlc_object_t *obj) ...@@ -186,142 +98,30 @@ static int Open (vlc_object_t *obj)
free (sys); free (sys);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
const unsigned snum = GetScreenNumber (conn, scr);
sys->conn = conn; sys->conn = conn;
sys->gl = vlc_gl_Create (sys->embed, VLC_OPENGL, "glx");
Display *dpy = XOpenDisplay (sys->embed->display.x11); if (sys->gl == NULL)
if (dpy == NULL)
{
xcb_disconnect (conn);
vout_display_DeleteWindow (vd, sys->embed);
free (sys);
return VLC_EGENERIC;
}
sys->display = dpy;
sys->ctx = NULL;
if (!CheckGLX (vd, dpy))
goto error;
sys->window = xcb_generate_id (conn);
/* Determine our pixel format */
static const int attr[] = {
GLX_RED_SIZE, 5,
GLX_GREEN_SIZE, 5,
GLX_BLUE_SIZE, 5,
GLX_DOUBLEBUFFER, True,
GLX_X_RENDERABLE, True,
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
None
};
xcb_get_window_attributes_reply_t *wa =
xcb_get_window_attributes_reply (conn,
xcb_get_window_attributes (conn, sys->embed->handle.xid), NULL);
if (wa == NULL)
goto error;
xcb_visualid_t visual = wa->visual;
free (wa);
int nelem;
GLXFBConfig *confs = glXChooseFBConfig (dpy, snum, attr, &nelem);
if (confs == NULL)
{
msg_Err (vd, "no GLX frame buffer configurations");
goto error;
}
GLXFBConfig conf;
bool found = false;
for (int i = 0; i < nelem && !found; i++)
{
conf = confs[i];
XVisualInfo *vi = glXGetVisualFromFBConfig (dpy, conf);
if (vi == NULL)
continue;
if (vi->visualid == visual)
found = true;
XFree (vi);
}
XFree (confs);
if (!found)
{
msg_Err (vd, "no matching GLX frame buffer configuration");
goto error; goto error;
}
sys->glwin = None; const vlc_fourcc_t *spu_chromas;
if (!CreateWindow (vd, conn, scr, width, height))
sys->glwin = glXCreateWindow (dpy, conf, sys->window, NULL );
if (sys->glwin == None)
{
msg_Err (vd, "cannot create GLX window");
goto error;
}
/* Create an OpenGL context */
sys->ctx = glXCreateNewContext (dpy, conf, GLX_RGBA_TYPE, NULL, True);
if (sys->ctx == NULL)
{
msg_Err (vd, "cannot create GLX context");
goto error;
}
if (!glXMakeContextCurrent (dpy, sys->glwin, sys->glwin, sys->ctx)) if (vlc_gl_MakeCurrent (sys->gl))
goto error; goto error;
const char *glx_extensions = glXQueryExtensionsString (dpy, snum); sys->vgl = vout_display_opengl_New (&vd->fmt, &spu_chromas, sys->gl);
vlc_gl_ReleaseCurrent (sys->gl);
bool is_swap_interval_set = false;
#ifdef GLX_SGI_swap_control
if (HasExtension (glx_extensions, "GLX_SGI_swap_control")) {
PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)GetProcAddress (NULL, "glXSwapIntervalSGI");
if (!is_swap_interval_set && SwapIntervalSGI)
is_swap_interval_set = !SwapIntervalSGI (1);
}
#endif
#ifdef GLX_EXT_swap_control
if (HasExtension (glx_extensions, "GLX_EXT_swap_control")) {
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)GetProcAddress (NULL, "glXSwapIntervalEXT");
if (!is_swap_interval_set && SwapIntervalEXT)
{
SwapIntervalEXT (dpy, sys->glwin, 1);
is_swap_interval_set = true;
}
}
#endif
/* Initialize common OpenGL video display */
sys->gl.lock = NULL;
sys->gl.unlock = NULL;
sys->gl.swap = SwapBuffers;
sys->gl.getProcAddress = GetProcAddress;
sys->gl.sys = sys;
vout_display_info_t info = vd->info;
info.has_pictures_invalid = false;
info.has_event_thread = true;
sys->vgl = vout_display_opengl_New (&vd->fmt, &info.subpicture_chromas,
&sys->gl);
glXMakeContextCurrent (dpy, None, None, NULL);
if (sys->vgl == NULL) if (sys->vgl == NULL)
{
sys->gl.sys = NULL;
goto error; goto error;
}
sys->cursor = XCB_cursor_Create (conn, scr); sys->cursor = XCB_cursor_Create (conn, scr);
sys->visible = false; sys->visible = false;
/* Setup vout_display_t once everything is fine */ /* Setup vout_display_t once everything is fine */
vd->info = info; vd->sys = sys;
vd->info.has_pictures_invalid = false;
vd->info.has_event_thread = true;
vd->info.subpicture_chromas = spu_chromas;
vd->pool = Pool; vd->pool = Pool;
vd->prepare = PictureRender; vd->prepare = PictureRender;
vd->display = PictureDisplay; vd->display = PictureDisplay;
...@@ -338,7 +138,11 @@ static int Open (vlc_object_t *obj) ...@@ -338,7 +138,11 @@ static int Open (vlc_object_t *obj)
return VLC_SUCCESS; return VLC_SUCCESS;
error: error:
Close (obj); if (sys->gl != NULL)
vlc_gl_Destroy (sys->gl);
xcb_disconnect (sys->conn);
vout_display_DeleteWindow (vd, sys->embed);
free (sys);
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -350,20 +154,11 @@ static void Close (vlc_object_t *obj) ...@@ -350,20 +154,11 @@ static void Close (vlc_object_t *obj)
{ {
vout_display_t *vd = (vout_display_t *)obj; vout_display_t *vd = (vout_display_t *)obj;
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
Display *dpy = sys->display;
if (sys->gl.sys != NULL) vlc_gl_MakeCurrent (sys->gl);
{
glXMakeContextCurrent (dpy, sys->glwin, sys->glwin, sys->ctx);
vout_display_opengl_Delete (sys->vgl); vout_display_opengl_Delete (sys->vgl);
glXMakeContextCurrent (dpy, None, None, NULL); vlc_gl_ReleaseCurrent (sys->gl);
} vlc_gl_Destroy (sys->gl);
if (sys->ctx != NULL)
{
glXDestroyContext (dpy, sys->ctx);
glXDestroyWindow (dpy, sys->glwin);
}
XCloseDisplay (dpy);
/* show the default cursor */ /* show the default cursor */
xcb_change_window_attributes (sys->conn, sys->embed->handle.xid, xcb_change_window_attributes (sys->conn, sys->embed->handle.xid,
...@@ -375,23 +170,6 @@ static void Close (vlc_object_t *obj) ...@@ -375,23 +170,6 @@ static void Close (vlc_object_t *obj)
free (sys); free (sys);
} }
static void SwapBuffers (vlc_gl_t *gl)
{
vout_display_sys_t *sys = gl->sys;
glXSwapBuffers (sys->display, sys->glwin);
}
static void *GetProcAddress (vlc_gl_t *gl, const char *name)
{
(void)gl;
#ifdef GLX_ARB_get_proc_address
return glXGetProcAddressARB ((const GLubyte *)name);
#else
return NULL;
#endif
}
/** /**
* Return a direct buffer * Return a direct buffer
*/ */
...@@ -401,11 +179,9 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count) ...@@ -401,11 +179,9 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
if (!sys->pool) if (!sys->pool)
{ {
Display *dpy = sys->display; vlc_gl_MakeCurrent (sys->gl);
glXMakeContextCurrent (dpy, sys->glwin, sys->glwin, sys->ctx);
sys->pool = vout_display_opengl_GetPool (sys->vgl, requested_count); sys->pool = vout_display_opengl_GetPool (sys->vgl, requested_count);
glXMakeContextCurrent (dpy, None, None, NULL); vlc_gl_ReleaseCurrent (sys->gl);
} }
return sys->pool; return sys->pool;
} }
...@@ -413,21 +189,19 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count) ...@@ -413,21 +189,19 @@ static picture_pool_t *Pool (vout_display_t *vd, unsigned requested_count)
static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture) static void PictureRender (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
Display *dpy = sys->display;
glXMakeContextCurrent (dpy, sys->glwin, sys->glwin, sys->ctx); vlc_gl_MakeCurrent (sys->gl);
vout_display_opengl_Prepare (sys->vgl, pic, subpicture); vout_display_opengl_Prepare (sys->vgl, pic, subpicture);
glXMakeContextCurrent (dpy, None, None, NULL); vlc_gl_ReleaseCurrent (sys->gl);
} }
static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture) static void PictureDisplay (vout_display_t *vd, picture_t *pic, subpicture_t *subpicture)
{ {
vout_display_sys_t *sys = vd->sys; vout_display_sys_t *sys = vd->sys;
Display *dpy = sys->display;
glXMakeContextCurrent (dpy, sys->glwin, sys->glwin, sys->ctx); vlc_gl_MakeCurrent (sys->gl);
vout_display_opengl_Display (sys->vgl, &vd->source); vout_display_opengl_Display (sys->vgl, &vd->source);
glXMakeContextCurrent (dpy, None, None, NULL); vlc_gl_ReleaseCurrent (sys->gl);
picture_Release (pic); picture_Release (pic);
if (subpicture) if (subpicture)
...@@ -484,22 +258,9 @@ static int Control (vout_display_t *vd, int query, va_list ap) ...@@ -484,22 +258,9 @@ static int Control (vout_display_t *vd, int query, va_list ap)
vout_display_place_t place; vout_display_place_t place;
vout_display_PlacePicture (&place, source, cfg, false); vout_display_PlacePicture (&place, source, cfg, false);
/* Move the picture within the window */ vlc_gl_MakeCurrent (sys->gl);
const uint32_t values[] = { place.x, place.y,
place.width, place.height, };
xcb_void_cookie_t ck =
xcb_configure_window_checked (sys->conn, sys->window,
XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y
| XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT,
values);
if (XCB_error_Check (vd, sys->conn, "cannot resize X11 window", ck))
return VLC_EGENERIC;
Display *dpy = sys->display;
glXMakeContextCurrent (dpy, sys->glwin, sys->glwin, sys->ctx);
glViewport (0, 0, place.width, place.height); glViewport (0, 0, place.width, place.height);
glXMakeContextCurrent (dpy, None, None, NULL); vlc_gl_ReleaseCurrent (sys->gl);
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -514,7 +275,7 @@ static int Control (vout_display_t *vd, int query, va_list ap) ...@@ -514,7 +275,7 @@ static int Control (vout_display_t *vd, int query, va_list ap)
case VOUT_DISPLAY_GET_OPENGL: case VOUT_DISPLAY_GET_OPENGL:
{ {
vlc_gl_t **gl = va_arg (ap, vlc_gl_t **); vlc_gl_t **gl = va_arg (ap, vlc_gl_t **);
*gl = &sys->gl; *gl = sys->gl;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment