[vlc-commits] [Git][videolan/vlc][master] 2 commits: glx: add intermediate X11 window controlled by GLX

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Thu May 26 12:06:57 UTC 2022



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
d0836b10 by Jeffrey Knockel at 2022-05-26T11:48:39+00:00
glx: add intermediate X11 window controlled by GLX

Asynchronous window resizes cannot be kept in sync with GLX.  To keep
the underlying X11 window and the GLX drawable sizes in sync, embed a
new X11 window so that GLX can synchronously resize.

At a high level, to resize, we (1) wait until GLX is done drawing, (2)
resize the X11 window, and (3) wait for the window to be resized before
GLX resumes drawing.

With Nvidia, glXWaitX() is sufficient to wait for the window to be
resized.  With Mesa, it is not, so after glXWaitX() we check if Xlib
knows if the X server has already processed the resize and, if not,
XSync().

Refs #26734 for GLX.

- - - - -
2fe4871b by Jeffrey Knockel at 2022-05-26T11:48:39+00:00
egl: add intermediate X11 window controlled by EGL

Asynchronous window resizes cannot be kept in sync with EGL.
To keep the underlying X11 window and the EGL drawable sizes in sync,
embed a new X11 window so that EGL can synchronously resize.

At a high level, to resize, we (1) wait until EGL is done drawing, (2)
resize the X11 window, and (3) wait for the window to be resized before
EGL resumes drawing.

With Nvidia, eglWaitNative() is sufficient to wait for the window to be
resized.  With Mesa, it is not, so after eglWaitNative() we (for the
Xlib backend) check if Xlib knows if the X server has already processed
the resize and, if not, XSync(), or (for the XCB backend) wait on the
void cookie corresponding to our resize request.

To work around an issue with Mesa, we also call
eglQuerySurface(EGL_HEIGHT) to coerce Mesa to observe the new X11 window
size and resize its EGL surface.  On Nvidia, this is not required, but
we call it in any case.

Refs #26734 for EGL.

- - - - -


2 changed files:

- modules/video_output/glx.c
- modules/video_output/opengl/egl.c


Changes:

=====================================
modules/video_output/glx.c
=====================================
@@ -44,7 +44,7 @@ typedef struct vlc_gl_sys_t
     Display *display;
     GLXWindow win;
     GLXContext ctx;
-    bool restore_forget_gravity;
+    Window x11_win;
 } vlc_gl_sys_t;
 
 static int MakeCurrent (vlc_gl_t *gl)
@@ -63,6 +63,22 @@ static void ReleaseCurrent (vlc_gl_t *gl)
     glXMakeContextCurrent (sys->display, None, None, NULL);
 }
 
+static void Resize (vlc_gl_t *gl, unsigned width, unsigned height)
+{
+    vlc_gl_sys_t *sys = gl->sys;
+
+    if (MakeCurrent(gl) == VLC_SUCCESS) {
+        glXWaitGL();
+        unsigned long init_serial = LastKnownRequestProcessed(sys->display);
+        unsigned long resize_serial = NextRequest(sys->display);
+        XResizeWindow(sys->display, sys->x11_win, width, height);
+        glXWaitX();
+        if (LastKnownRequestProcessed(sys->display) - init_serial < resize_serial - init_serial)
+            XSync(sys->display, False);
+        ReleaseCurrent(gl);
+    }
+}
+
 static void SwapBuffers (vlc_gl_t *gl)
 {
     vlc_gl_sys_t *sys = gl->sys;
@@ -121,12 +137,6 @@ static void Close(vlc_gl_t *gl)
 
     glXDestroyContext(dpy, sys->ctx);
     glXDestroyWindow(dpy, sys->win);
-    if (sys->restore_forget_gravity) {
-        XSetWindowAttributes swa;
-        swa.bit_gravity = ForgetGravity;
-        XChangeWindowAttributes (dpy, gl->surface->handle.xid, CWBitGravity,
-                                 &swa);
-    }
     XCloseDisplay(dpy);
     free(sys);
 }
@@ -160,6 +170,22 @@ static int Open(vlc_gl_t *gl, unsigned width, unsigned height)
     if (!XGetWindowAttributes (dpy, gl->surface->handle.xid, &wa))
         goto error;
 
+    XSetWindowAttributes swa;
+    unsigned long mask =
+        CWBackPixel |
+        CWBorderPixel |
+        CWBitGravity |
+        CWColormap;
+    swa.background_pixel = BlackPixelOfScreen(wa.screen);
+    swa.border_pixel = BlackPixelOfScreen(wa.screen);
+    swa.bit_gravity = NorthWestGravity;
+    swa.colormap = DefaultColormapOfScreen(wa.screen);
+    sys->x11_win = XCreateWindow(dpy, gl->surface->handle.xid, 0, 0,
+                                 width, height, 0,
+                                 DefaultDepthOfScreen(wa.screen), InputOutput,
+                                 DefaultVisualOfScreen(wa.screen), mask, &swa);
+    XMapWindow(dpy, sys->x11_win);
+
     const int snum = XScreenNumberOfScreen (wa.screen);
     const VisualID visual = XVisualIDFromVisual (wa.visual);
     static const int attr[] = {
@@ -203,7 +229,7 @@ static int Open(vlc_gl_t *gl, unsigned width, unsigned height)
     }
 
     /* Create a drawing surface */
-    sys->win = glXCreateWindow (dpy, conf, gl->surface->handle.xid, NULL);
+    sys->win = glXCreateWindow (dpy, conf, sys->x11_win, NULL);
     if (sys->win == None)
     {
         msg_Err (obj, "cannot create GLX window");
@@ -219,22 +245,12 @@ static int Open(vlc_gl_t *gl, unsigned width, unsigned height)
         goto error;
     }
 
-    /* Set bit gravity if necessary */
-    if (wa.bit_gravity == ForgetGravity) {
-        XSetWindowAttributes swa;
-        swa.bit_gravity = NorthWestGravity;
-        XChangeWindowAttributes (dpy, gl->surface->handle.xid, CWBitGravity,
-                                 &swa);
-        sys->restore_forget_gravity = true;
-    } else
-        sys->restore_forget_gravity = false;
-
     /* Initialize OpenGL callbacks */
     static const struct vlc_gl_operations gl_ops =
     {
         .make_current = MakeCurrent,
         .release_current = ReleaseCurrent,
-        .resize = NULL,
+        .resize = Resize,
         .swap = SwapBuffers,
         .get_proc_address = GetSymbol,
         .close = Close,
@@ -278,7 +294,6 @@ static int Open(vlc_gl_t *gl, unsigned width, unsigned height)
         var_SetString(gl->surface, "gl", "glx");
     }
 
-    (void) width; (void) height;
     return VLC_SUCCESS;
 
 error:


=====================================
modules/video_output/opengl/egl.c
=====================================
@@ -54,11 +54,11 @@ typedef struct vlc_gl_sys_t
     EGLContext context;
 #if defined (USE_PLATFORM_X11)
     Display *x11;
-    bool restore_forget_gravity;
+    Window x11_win;
 #endif
 #if defined (USE_PLATFORM_XCB)
     xcb_connection_t *conn;
-    bool restore_forget_gravity;
+    xcb_window_t xcb_win;
 #endif
 #if defined (USE_PLATFORM_WAYLAND)
     struct wl_egl_window *window;
@@ -107,6 +107,41 @@ static void Resize (vlc_gl_t *gl, unsigned width, unsigned height)
 
     wl_egl_window_resize(sys->window, width, height, 0, 0);
 }
+#elif defined(USE_PLATFORM_X11)
+static void Resize (vlc_gl_t *gl, unsigned width, unsigned height)
+{
+    vlc_gl_sys_t *sys = gl->sys;
+    EGLint val;
+
+    if (MakeCurrent(gl) == VLC_SUCCESS) {
+        eglWaitClient();
+        unsigned long init_serial = LastKnownRequestProcessed(sys->x11);
+        unsigned long resize_serial = NextRequest(sys->x11);
+        XResizeWindow(sys->x11, sys->x11_win, width, height);
+        eglQuerySurface(sys->display, sys->surface, EGL_HEIGHT, &val); /* force Mesa to see new size in time for next draw */
+        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+        if (LastKnownRequestProcessed(sys->x11) - init_serial < resize_serial - init_serial)
+            XSync(sys->x11, False);
+        ReleaseCurrent(gl);
+    }
+}
+#elif defined(USE_PLATFORM_XCB)
+static void Resize (vlc_gl_t *gl, unsigned width, unsigned height)
+{
+    vlc_gl_sys_t *sys = gl->sys;
+    EGLint val;
+
+    if (MakeCurrent(gl) == VLC_SUCCESS) {
+        eglWaitClient();
+        uint16_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
+        const uint32_t values[] = { width, height };
+        xcb_void_cookie_t cookie = xcb_configure_window_checked(sys->conn, sys->xcb_win, mask, values);
+        eglQuerySurface(sys->display, sys->surface, EGL_HEIGHT, &val); /* force Mesa to see new size in time for next draw */
+        eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+        free(xcb_request_check(sys->conn, cookie));
+        ReleaseCurrent(gl);
+    }
+}
 #else
 # define Resize (NULL)
 #endif
@@ -200,26 +235,11 @@ static void Close(vlc_gl_t *gl)
         eglTerminate(sys->display);
     }
 #ifdef USE_PLATFORM_X11
-    if (sys->x11 != NULL) {
-        if (sys->restore_forget_gravity) {
-            vlc_window_t *wnd = gl->surface;
-            XSetWindowAttributes swa;
-            swa.bit_gravity = ForgetGravity;
-            XChangeWindowAttributes(sys->x11, wnd->handle.xid, CWBitGravity,
-                                    &swa);
-        }
+    if (sys->x11 != NULL)
         XCloseDisplay(sys->x11);
-    }
 #elif defined (USE_PLATFORM_XCB)
-    if (sys->conn != NULL) {
-        if (sys->restore_forget_gravity) {
-            const uint32_t values[] = { XCB_GRAVITY_BIT_FORGET };
-
-            xcb_change_window_attributes(sys->conn, gl->surface->handle.xid,
-                                         XCB_CW_BIT_GRAVITY, values);
-        }
+    if (sys->conn != NULL)
         xcb_disconnect(sys->conn);
-    }
 #endif
 #ifdef USE_PLATFORM_WAYLAND
     if (sys->window != NULL)
@@ -271,7 +291,6 @@ static int Open(vlc_gl_t *gl, const struct gl_api *api,
     if (wnd->type != VLC_WINDOW_TYPE_XID || !vlc_xlib_init(obj))
         goto error;
 
-    window = &wnd->handle.xid;
     sys->x11 = XOpenDisplay(wnd->display.x11);
     if (sys->x11 == NULL)
         goto error;
@@ -281,17 +300,25 @@ static int Open(vlc_gl_t *gl, const struct gl_api *api,
         XWindowAttributes wa;
         XSetWindowAttributes swa;
 
-        sys->restore_forget_gravity = false;
         if (!XGetWindowAttributes(sys->x11, wnd->handle.xid, &wa))
             goto error;
         snum = XScreenNumberOfScreen(wa.screen);
-        if (wa.bit_gravity == ForgetGravity) {
-            swa.bit_gravity = NorthWestGravity;
-            XChangeWindowAttributes(sys->x11, wnd->handle.xid, CWBitGravity,
-                                    &swa);
-            sys->restore_forget_gravity = true;
-        }
+        unsigned long mask =
+            CWBackPixel |
+            CWBorderPixel |
+            CWBitGravity |
+            CWColormap;
+        swa.background_pixel = BlackPixelOfScreen(wa.screen);
+        swa.border_pixel = BlackPixelOfScreen(wa.screen);
+        swa.bit_gravity = NorthWestGravity;
+        swa.colormap = DefaultColormapOfScreen(wa.screen);
+        sys->x11_win = XCreateWindow(
+                sys->x11, wnd->handle.xid, 0, 0, width, height, 0,
+                DefaultDepthOfScreen(wa.screen), InputOutput,
+                DefaultVisualOfScreen(wa.screen), mask, &swa);
+        XMapWindow(sys->x11, sys->x11_win);
     }
+    window = &sys->x11_win;
 # ifdef EGL_EXT_platform_x11
     if (CheckClientExt("EGL_EXT_platform_x11"))
     {
@@ -310,14 +337,12 @@ static int Open(vlc_gl_t *gl, const struct gl_api *api,
             sys->display = eglGetDisplay(sys->x11);
 # endif
     }
-    (void) width; (void) height;
 
 #elif defined (USE_PLATFORM_XCB)
     xcb_connection_t *conn;
     const xcb_screen_t *scr;
 
     sys->conn = NULL;
-    sys->restore_forget_gravity = false;
 
     if (wnd->type != VLC_WINDOW_TYPE_XID)
         goto error;
@@ -329,16 +354,32 @@ static int Open(vlc_gl_t *gl, const struct gl_api *api,
     ret = vlc_xcb_parent_Create(gl->obj.logger, wnd, &conn, &scr);
     if (ret == VLC_SUCCESS)
     {
+        sys->xcb_win = xcb_generate_id(conn);
         xcb_get_window_attributes_reply_t *r =
             xcb_get_window_attributes_reply(conn,
                 xcb_get_window_attributes(conn, wnd->handle.xid), NULL);
 
-        if (r != NULL && r->bit_gravity == XCB_GRAVITY_BIT_FORGET) {
-            const uint32_t values[] = { XCB_GRAVITY_NORTH_WEST };
-
-            xcb_change_window_attributes(sys->conn, gl->surface->handle.xid,
-                                         XCB_CW_BIT_GRAVITY, values);
-            sys->restore_forget_gravity = true;
+        if (r != NULL) {
+            uint32_t mask =
+                XCB_CW_BACK_PIXEL |
+                XCB_CW_BORDER_PIXEL |
+                XCB_CW_BIT_GRAVITY |
+                XCB_CW_COLORMAP;
+            const uint32_t values[] = {
+                /* XCB_CW_BACK_PIXEL */
+                scr->black_pixel,
+                /* XCB_CW_BORDER_PIXEL */
+                scr->black_pixel,
+                /* XCB_CW_BIT_GRAVITY */
+                XCB_GRAVITY_NORTH_WEST,
+                /* XCB_CW_COLORMAP */
+                scr->default_colormap,
+            };
+            xcb_create_window(conn, scr->root_depth, sys->xcb_win,
+                              wnd->handle.xid, 0, 0, width, height, 0,
+                              XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual,
+                              mask, values);
+            xcb_map_window(conn, sys->xcb_win);
         }
         free(r);
     }
@@ -346,7 +387,7 @@ static int Open(vlc_gl_t *gl, const struct gl_api *api,
         goto error;
 
     sys->conn = conn;
-    window = &wnd->handle.xid;
+    window = &sys->xcb_win;
 
     {
         const EGLint attrs[] = {
@@ -357,7 +398,6 @@ static int Open(vlc_gl_t *gl, const struct gl_api *api,
         createSurface = CreateWindowSurfaceEXT;
     }
 # endif
-    (void) width; (void) height;
 
 #elif defined (USE_PLATFORM_WAYLAND)
     sys->window = NULL;



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f7434e60fc38e78b9356600d1452e850eb5ec2d9...2fe4871ba33d3b3b7d7bf38c2a4be80c517d70d6

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/f7434e60fc38e78b9356600d1452e850eb5ec2d9...2fe4871ba33d3b3b7d7bf38c2a4be80c517d70d6
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list