Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package picom for openSUSE:Factory checked 
in at 2024-02-13 22:44:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/picom (Old)
 and      /work/SRC/openSUSE:Factory/.picom.new.1815 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "picom"

Tue Feb 13 22:44:40 2024 rev:10 rq:1146416 version:11.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/picom/picom.changes      2024-02-06 
16:36:41.567702615 +0100
+++ /work/SRC/openSUSE:Factory/.picom.new.1815/picom.changes    2024-02-13 
22:45:08.942254978 +0100
@@ -1,0 +2,16 @@
+Tue Feb 13 13:23:17 UTC 2024 - Alexei Sorokin <sor.ale...@meowr.ru>
+
+- Update to version 11.2:
+  * picom now depends on libepoxy for OpenGL symbol management.
+  * Workaround a NVIDIA problem that causes high CPU usage after
+    suspend/resume.
+  * Fix occasional freezes.
+  * Fix corner-radius-rules not applying sometimes.
+  * Fix window shader not having an effect when frame opacity is
+    enabled.
+  * Fix binding root pixmap in case of depth mismatch
+    (boo#1217786).
+- Remove picom-11.1-fix-nvidia-high-cpu-usage.patch: fixed
+  upstream.
+
+-------------------------------------------------------------------

Old:
----
  picom-11.1-fix-nvidia-high-cpu-usage.patch
  picom-11.1.tar.gz

New:
----
  picom-11.2.tar.gz

BETA DEBUG BEGIN:
  Old:    (boo#1217786).
- Remove picom-11.1-fix-nvidia-high-cpu-usage.patch: fixed
  upstream.
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ picom.spec ++++++
--- /var/tmp/diff_new_pack.ugmAC8/_old  2024-02-13 22:45:09.626279593 +0100
+++ /var/tmp/diff_new_pack.ugmAC8/_new  2024-02-13 22:45:09.630279737 +0100
@@ -17,15 +17,13 @@
 
 
 Name:           picom
-Version:        11.1
+Version:        11.2
 Release:        0
 Summary:        Stand-alone compositor for X11
 License:        MIT AND MPL-2.0
 Group:          System/X11/Utilities
 URL:            https://github.com/yshui/picom
 Source:         
https://github.com/yshui/picom/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
-# PATCH-FIX-UPSTREAM picom-11.1-fix-nvidia-high-cpu-usage.patch 
yshu...@gmail.com -- Workaround a NVIDIA problem that causes high CPU usage 
after suspend/resume
-Patch0:         picom-11.1-fix-nvidia-high-cpu-usage.patch
 BuildRequires:  asciidoc
 BuildRequires:  c_compiler
 BuildRequires:  hicolor-icon-theme
@@ -34,6 +32,7 @@
 BuildRequires:  uthash-devel
 BuildRequires:  pkgconfig(dbus-1)
 BuildRequires:  pkgconfig(egl)
+BuildRequires:  pkgconfig(epoxy)
 BuildRequires:  pkgconfig(gl)
 BuildRequires:  pkgconfig(libconfig)
 BuildRequires:  pkgconfig(libdrm)

++++++ picom-11.1.tar.gz -> picom-11.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/.builds/freebsd.yml 
new/picom-11.2/.builds/freebsd.yml
--- old/picom-11.1/.builds/freebsd.yml  2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/.builds/freebsd.yml  2024-02-13 11:36:02.000000000 +0100
@@ -12,6 +12,7 @@
   - uthash
   - libconfig
   - libglvnd
+  - libepoxy
   - dbus
   - pcre
 sources:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/.editorconfig new/picom-11.2/.editorconfig
--- old/picom-11.1/.editorconfig        2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/.editorconfig        2024-02-13 11:36:02.000000000 +0100
@@ -3,3 +3,6 @@
 indent_style = tab
 indent_size = 8
 max_line_length = 90
+[*.nix]
+indent_style = space
+indent_size = 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/README.md new/picom-11.2/README.md
--- old/picom-11.1/README.md    2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/README.md    2024-02-13 11:36:02.000000000 +0100
@@ -39,7 +39,7 @@
 * pixman
 * libdbus (optional, disable with the `-Ddbus=false` meson configure flag)
 * libconfig (optional, disable with the `-Dconfig_file=false` meson configure 
flag)
-* libGL, libEGL (optional, disable with the `-Dopengl=false` meson configure 
flag)
+* libGL, libEGL, libepoxy (optional, disable with the `-Dopengl=false` meson 
configure flag)
 * libpcre2 (optional, disable with the `-Dregex=false` meson configure flag)
 * libev
 * uthash
@@ -47,13 +47,13 @@
 On Debian based distributions (e.g. Ubuntu), the needed packages are
 
 ```
-libconfig-dev libdbus-1-dev libegl-dev libev-dev libgl-dev libpcre2-dev 
libpixman-1-dev libx11-xcb-dev libxcb1-dev libxcb-composite0-dev 
libxcb-damage0-dev libxcb-dpms0-dev libxcb-glx0-dev libxcb-image0-dev 
libxcb-present-dev libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev 
libxcb-shape0-dev libxcb-util-dev libxcb-xfixes0-dev libxext-dev meson 
ninja-build uthash-dev
+libconfig-dev libdbus-1-dev libegl-dev libev-dev libgl-dev libepoxy-dev 
libpcre2-dev libpixman-1-dev libx11-xcb-dev libxcb1-dev libxcb-composite0-dev 
libxcb-damage0-dev libxcb-dpms0-dev libxcb-glx0-dev libxcb-image0-dev 
libxcb-present-dev libxcb-randr0-dev libxcb-render0-dev libxcb-render-util0-dev 
libxcb-shape0-dev libxcb-util-dev libxcb-xfixes0-dev libxext-dev meson 
ninja-build uthash-dev
 ```
 
 On Fedora, the needed packages are
 
 ```
-dbus-devel gcc git libconfig-devel libdrm-devel libev-devel libX11-devel 
libX11-xcb libXext-devel libxcb-devel libGL-devel libEGL-devel meson 
pcre2-devel pixman-devel uthash-devel xcb-util-image-devel 
xcb-util-renderutil-devel xorg-x11-proto-devel
+dbus-devel gcc git libconfig-devel libdrm-devel libev-devel libX11-devel 
libX11-xcb libXext-devel libxcb-devel libGL-devel libEGL-devel libepoxy-devel 
meson pcre2-devel pixman-devel uthash-devel xcb-util-image-devel 
xcb-util-renderutil-devel xorg-x11-proto-devel xcb-util-devel
 ```
 
 To build the documents, you need `asciidoc`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/flake.lock new/picom-11.2/flake.lock
--- old/picom-11.1/flake.lock   2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/flake.lock   2024-02-13 11:36:02.000000000 +0100
@@ -5,11 +5,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1689068808,
-        "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
+        "lastModified": 1705309234,
+        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
+        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
         "type": "github"
       },
       "original": {
@@ -25,11 +25,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1660459072,
-        "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
+        "lastModified": 1703887061,
+        "narHash": "sha256-gGPa9qWNc6eCXT/+Z5/zMkyYOuRZqeFZBDbopNZQkuY=",
         "owner": "hercules-ci",
         "repo": "gitignore.nix",
-        "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
+        "rev": "43e1aa1308018f37118e34d3a9cb4f5e75dc11d5",
         "type": "github"
       },
       "original": {
@@ -41,11 +41,12 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1691186842,
-        "narHash": "sha256-wxBVCvZUwq+XS4N4t9NqsHV4E64cPVqQ2fdDISpjcw0=",
-        "path": "/nix/store/d42v5grfq77vr10r336kks0qjp0wij8d-source",
-        "rev": "18036c0be90f4e308ae3ebcab0e14aae0336fe42",
-        "type": "path"
+        "lastModified": 1707689078,
+        "narHash": "sha256-UUGmRa84ZJHpGZ1WZEBEUOzaPOWG8LZ0yPg1pdDF/yM=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "f9d39fb9aff0efee4a3d5f4a6d7c17701d38a1d8",
+        "type": "github"
       },
       "original": {
         "id": "nixpkgs",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/flake.nix new/picom-11.2/flake.nix
--- old/picom-11.1/flake.nix    2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/flake.nix    2024-02-13 11:36:02.000000000 +0100
@@ -24,12 +24,22 @@
     overlays = [ overlay ];
   in rec {
     inherit overlay overlays;
-    defaultPackage = pkgs.picom;
+    defaultPackage = pkgs.picom.overrideAttrs (o: {
+      version = "11";
+      src = ./.;
+      buildInputs = o.buildInputs ++ [ pkgs.libepoxy ];
+    });
     devShell = defaultPackage.overrideAttrs {
-      buildInputs = defaultPackage.buildInputs ++ [
-        pkgs.clang-tools
-        pkgs.llvmPackages_14.clang-unwrapped.python
-      ];
+      buildInputs = defaultPackage.buildInputs ++ (with pkgs; [
+        clang-tools_17
+        llvmPackages_17.clang-unwrapped.python
+      ]);
+      hardeningDisable = [ "fortify" ];
+      shellHook = ''
+        # Workaround a NixOS limitation on sanitizers:
+        # See: https://github.com/NixOS/nixpkgs/issues/287763
+        export LD_LIBRARY_PATH+=":/run/opengl-driver/lib"
+      '';
     };
   });
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/backend/driver.c 
new/picom-11.2/src/backend/driver.c
--- old/picom-11.1/src/backend/driver.c 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/backend/driver.c 2024-02-13 11:36:02.000000000 +0100
@@ -20,10 +20,13 @@
 }
 
 enum vblank_scheduler_type choose_vblank_scheduler(enum driver driver) {
+       enum vblank_scheduler_type type = VBLANK_SCHEDULER_PRESENT;
+#ifdef CONFIG_OPENGL
        if (driver & DRIVER_NVIDIA) {
-               return VBLANK_SCHEDULER_SGI_VIDEO_SYNC;
+               type = VBLANK_SCHEDULER_SGI_VIDEO_SYNC;
        }
-       return VBLANK_SCHEDULER_PRESENT;
+#endif
+       return type;
 }
 
 enum driver detect_driver(xcb_connection_t *c, backend_t *backend_data, 
xcb_window_t window) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/backend/gl/egl.c 
new/picom-11.2/src/backend/gl/egl.c
--- old/picom-11.1/src/backend/gl/egl.c 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/backend/gl/egl.c 2024-02-13 11:36:02.000000000 +0100
@@ -36,12 +36,6 @@
        EGLContext ctx;
 };
 
-static PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC glEGLImageTargetTexStorage = NULL;
-static PFNEGLCREATEIMAGEKHRPROC eglCreateImageProc = NULL;
-static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageProc = NULL;
-static PFNEGLGETPLATFORMDISPLAYPROC eglGetPlatformDisplayProc = NULL;
-static PFNEGLCREATEPLATFORMWINDOWSURFACEPROC 
eglCreatePlatformWindowSurfaceProc = NULL;
-
 const char *eglGetErrorString(EGLint error) {
 #define CASE_STR(value)                                                        
          \
        case value: return #value;
@@ -74,7 +68,7 @@
        struct egl_pixmap *p = tex->user_data;
        // Release binding
        if (p->image != EGL_NO_IMAGE) {
-               eglDestroyImageProc(gd->display, p->image);
+               eglDestroyImage(gd->display, p->image);
                p->image = EGL_NO_IMAGE;
        }
 
@@ -134,18 +128,6 @@
        bool success = false;
        struct egl_data *gd = NULL;
 
-#define get_proc(name, type)                                                   
          \
-       name##Proc = (type)eglGetProcAddress(#name);                            
         \
-       if (!name##Proc) {                                                      
         \
-               log_error("Failed to get EGL function " #name);                 
         \
-               goto end;                                                       
         \
-       }
-       get_proc(eglCreateImage, PFNEGLCREATEIMAGEKHRPROC);
-       get_proc(eglDestroyImage, PFNEGLDESTROYIMAGEKHRPROC);
-       get_proc(eglGetPlatformDisplay, PFNEGLGETPLATFORMDISPLAYPROC);
-       get_proc(eglCreatePlatformWindowSurface, 
PFNEGLCREATEPLATFORMWINDOWSURFACEPROC);
-#undef get_proc
-
        // Check if we have the X11 platform
        const char *exts = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
        if (strstr(exts, "EGL_EXT_platform_x11") == NULL) {
@@ -154,12 +136,12 @@
        }
 
        gd = ccalloc(1, struct egl_data);
-       gd->display = eglGetPlatformDisplayProc(EGL_PLATFORM_X11_EXT, ps->c.dpy,
-                                               (EGLAttrib[]){
-                                                   EGL_PLATFORM_X11_SCREEN_EXT,
-                                                   ps->c.screen,
-                                                   EGL_NONE,
-                                               });
+       gd->display = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, ps->c.dpy,
+                                              (EGLint[]){
+                                                  EGL_PLATFORM_X11_SCREEN_EXT,
+                                                  ps->c.screen,
+                                                  EGL_NONE,
+                                              });
        if (gd->display == EGL_NO_DISPLAY) {
                log_error("Failed to get EGL display.");
                goto end;
@@ -212,7 +194,7 @@
        // clang-format on
 
        gd->target_win =
-           eglCreatePlatformWindowSurfaceProc(gd->display, config, &target, 
NULL);
+           eglCreatePlatformWindowSurfaceEXT(gd->display, config, &target, 
NULL);
        if (gd->target_win == EGL_NO_SURFACE) {
                log_error("Failed to create EGL surface.");
                goto end;
@@ -243,14 +225,6 @@
                goto end;
        }
 
-       glEGLImageTargetTexStorage =
-           
(PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC)eglGetProcAddress("glEGLImageTargetTexS"
-                                                                   
"torageEXT");
-       if (glEGLImageTargetTexStorage == NULL) {
-               log_error("Failed to get glEGLImageTargetTexStorageEXT.");
-               goto end;
-       }
-
        gd->gl.decouple_texture_user_data = egl_decouple_user_data;
        gd->gl.release_user_data = egl_release_image;
 
@@ -302,9 +276,8 @@
 
        eglpixmap = cmalloc(struct egl_pixmap);
        eglpixmap->pixmap = pixmap;
-       eglpixmap->image =
-           eglCreateImageProc(gd->display, EGL_NO_CONTEXT, 
EGL_NATIVE_PIXMAP_KHR,
-                              (EGLClientBuffer)(uintptr_t)pixmap, NULL);
+       eglpixmap->image = eglCreateImage(gd->display, EGL_NO_CONTEXT, 
EGL_NATIVE_PIXMAP_KHR,
+                                         (EGLClientBuffer)(uintptr_t)pixmap, 
NULL);
        eglpixmap->owned = owned;
 
        if (eglpixmap->image == EGL_NO_IMAGE) {
@@ -324,14 +297,14 @@
        wd->dim = 0;
        wd->inner->refcount = 1;
        glBindTexture(GL_TEXTURE_2D, inner->texture);
-       glEGLImageTargetTexStorage(GL_TEXTURE_2D, eglpixmap->image, NULL);
+       glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, eglpixmap->image, NULL);
        glBindTexture(GL_TEXTURE_2D, 0);
 
        gl_check_err();
        return wd;
 err:
        if (eglpixmap && eglpixmap->image) {
-               eglDestroyImageProc(gd->display, eglpixmap->image);
+               eglDestroyImage(gd->display, eglpixmap->image);
        }
        free(eglpixmap);
 
@@ -422,41 +395,6 @@
     .max_buffer_age = 5,        // Why?
 };
 
-PFNEGLGETDISPLAYDRIVERNAMEPROC eglGetDisplayDriverName;
-/**
- * Check if a EGL extension exists.
- */
-static inline bool egl_has_extension(EGLDisplay dpy, const char *ext) {
-       const char *egl_exts = eglQueryString(dpy, EGL_EXTENSIONS);
-       if (!egl_exts) {
-               log_error("Failed get EGL extension list.");
-               return false;
-       }
-
-       auto inlen = strlen(ext);
-       const char *curr = egl_exts;
-       bool match = false;
-       while (curr && !match) {
-               const char *end = strchr(curr, ' ');
-               if (!end) {
-                       // Last extension string
-                       match = strcmp(ext, curr) == 0;
-               } else if (curr + inlen == end) {
-                       // Length match, do match string
-                       match = strncmp(ext, curr, (unsigned long)(end - curr)) 
== 0;
-               }
-               curr = end ? end + 1 : NULL;
-       }
-
-       if (!match) {
-               log_info("Missing EGL extension %s.", ext);
-       } else {
-               log_info("Found EGL extension %s.", ext);
-       }
-
-       return match;
-}
-
 struct eglext_info eglext = {0};
 
 void eglext_init(EGLDisplay dpy) {
@@ -464,7 +402,10 @@
                return;
        }
        eglext.initialized = true;
-#define check_ext(name) eglext.has_##name = egl_has_extension(dpy, #name)
+#define check_ext(name)                                                        
          \
+       eglext.has_##name = epoxy_has_egl_extension(dpy, #name);                
         \
+       log_info("Extension " #name " - %s", eglext.has_##name ? "present" : 
"absent")
+
        check_ext(EGL_EXT_buffer_age);
        check_ext(EGL_EXT_create_context_robustness);
        check_ext(EGL_KHR_image_pixmap);
@@ -472,16 +413,4 @@
        check_ext(EGL_MESA_query_driver);
 #endif
 #undef check_ext
-
-       // Checking if the returned function pointer is NULL is not really 
necessary,
-       // or maybe not even useful, since eglGetProcAddress might always return
-       // something. We are doing it just for completeness' sake.
-
-#ifdef EGL_MESA_query_driver
-       eglGetDisplayDriverName =
-           
(PFNEGLGETDISPLAYDRIVERNAMEPROC)eglGetProcAddress("eglGetDisplayDriverName");
-       if (!eglGetDisplayDriverName) {
-               eglext.has_EGL_MESA_query_driver = false;
-       }
-#endif
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/backend/gl/egl.h 
new/picom-11.2/src/backend/gl/egl.h
--- old/picom-11.1/src/backend/gl/egl.h 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/backend/gl/egl.h 2024-02-13 11:36:02.000000000 +0100
@@ -1,10 +1,8 @@
 // SPDX-License-Identifier: MPL-2.0
 // Copyright (c) Yuxuan Shui <yshu...@gmail.com>
 #pragma once
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GL/gl.h>
-#include <GL/glext.h>
+#include <epoxy/egl.h>
+#include <epoxy/gl.h>
 #include <stdbool.h>
 #include <xcb/render.h>
 #include <xcb/xcb.h>
@@ -24,8 +22,4 @@
 
 extern struct eglext_info eglext;
 
-#ifdef EGL_MESA_query_driver
-extern PFNEGLGETDISPLAYDRIVERNAMEPROC eglGetDisplayDriverName;
-#endif
-
 void eglext_init(EGLDisplay);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/backend/gl/gl_common.c 
new/picom-11.2/src/backend/gl/gl_common.c
--- old/picom-11.1/src/backend/gl/gl_common.c   2024-01-28 19:17:19.000000000 
+0100
+++ new/picom-11.2/src/backend/gl/gl_common.c   2024-02-13 11:36:02.000000000 
+0100
@@ -1,7 +1,6 @@
 // SPDX-License-Identifier: MPL-2.0
 // Copyright (c) Yuxuan Shui <yshu...@gmail.com>
-#include <GL/gl.h>
-#include <GL/glext.h>
+#include <epoxy/gl.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
@@ -961,8 +960,8 @@
        } else {
                gd->is_nvidia = false;
        }
-       gd->has_robustness = gl_has_extension("GL_ARB_robustness");
-       gd->has_egl_image_storage = 
gl_has_extension("GL_EXT_EGL_image_storage");
+       gd->has_robustness = epoxy_has_gl_extension("GL_ARB_robustness");
+       gd->has_egl_image_storage = 
epoxy_has_gl_extension("GL_EXT_EGL_image_storage");
        gl_check_err();
 
        return true;
@@ -1013,9 +1012,11 @@
        auto new_tex = ccalloc(1, struct gl_texture);
 
        new_tex->texture = gl_new_texture(GL_TEXTURE_2D);
-       new_tex->y_inverted = true;
+       new_tex->y_inverted = inner->y_inverted;
+       new_tex->has_alpha = inner->has_alpha;
        new_tex->height = inner->height;
        new_tex->width = inner->width;
+       new_tex->shader = inner->shader;
        new_tex->refcount = 1;
        new_tex->user_data = gd->decouple_texture_user_data(base, 
inner->user_data);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/backend/gl/gl_common.h 
new/picom-11.2/src/backend/gl/gl_common.h
--- old/picom-11.1/src/backend/gl/gl_common.h   2024-01-28 19:17:19.000000000 
+0100
+++ new/picom-11.2/src/backend/gl/gl_common.h   2024-02-13 11:36:02.000000000 
+0100
@@ -1,8 +1,7 @@
 // SPDX-License-Identifier: MPL-2.0
 // Copyright (c) Yuxuan Shui <yshu...@gmail.com>
 #pragma once
-#include <GL/gl.h>
-#include <GL/glext.h>
+#include <epoxy/gl.h>
 #include <stdbool.h>
 #include <string.h>
 
@@ -265,26 +264,6 @@
 
 #define gl_check_fb_complete(fb) gl_check_fb_complete_(__func__, __LINE__, 
(fb))
 
-/**
- * Check if a GL extension exists.
- */
-static inline bool gl_has_extension(const char *ext) {
-       int nexts = 0;
-       glGetIntegerv(GL_NUM_EXTENSIONS, &nexts);
-       for (int i = 0; i < nexts || !nexts; i++) {
-               const char *exti = (const char *)glGetStringi(GL_EXTENSIONS, 
(GLuint)i);
-               if (exti == NULL) {
-                       break;
-               }
-               if (strcmp(ext, exti) == 0) {
-                       return true;
-               }
-       }
-       gl_clear_err();
-       log_info("Missing GL extension %s.", ext);
-       return false;
-}
-
 static const GLuint vert_coord_loc = 0;
 static const GLuint vert_in_texcoord_loc = 1;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/backend/gl/glx.c 
new/picom-11.2/src/backend/gl/glx.c
--- old/picom-11.1/src/backend/gl/glx.c 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/backend/gl/glx.c 2024-02-13 11:36:02.000000000 +0100
@@ -545,62 +545,17 @@
     .max_buffer_age = 5,        // Why?
 };
 
-/**
- * Check if a GLX extension exists.
- */
-static inline bool glx_has_extension(Display *dpy, int screen, const char 
*ext) {
-       const char *glx_exts = glXQueryExtensionsString(dpy, screen);
-       if (!glx_exts) {
-               log_error("Failed get GLX extension list.");
-               return false;
-       }
-
-       auto inlen = strlen(ext);
-       const char *curr = glx_exts;
-       bool match = false;
-       while (curr && !match) {
-               const char *end = strchr(curr, ' ');
-               if (!end) {
-                       // Last extension string
-                       match = strcmp(ext, curr) == 0;
-               } else if (curr + inlen == end) {
-                       // Length match, do match string
-                       match = strncmp(ext, curr, (unsigned long)(end - curr)) 
== 0;
-               }
-               curr = end ? end + 1 : NULL;
-       }
-
-       if (!match) {
-               log_info("Missing GLX extension %s.", ext);
-       } else {
-               log_info("Found GLX extension %s.", ext);
-       }
-
-       return match;
-}
-
 struct glxext_info glxext = {0};
-PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI;
-PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI;
-PFNGLXGETSYNCVALUESOMLPROC glXGetSyncValuesOML;
-PFNGLXWAITFORMSCOMLPROC glXWaitForMscOML;
-PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
-PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
-PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA;
-PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
-PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
-PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
-
-#ifdef GLX_MESA_query_renderer
-PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC glXQueryCurrentRendererIntegerMESA;
-#endif
 
 void glxext_init(Display *dpy, int screen) {
        if (glxext.initialized) {
                return;
        }
        glxext.initialized = true;
-#define check_ext(name) glxext.has_##name = glx_has_extension(dpy, screen, 
#name)
+#define check_ext(name)                                                        
          \
+       glxext.has_##name = epoxy_has_glx_extension(dpy, screen, #name);        
         \
+       log_info("Extension " #name " - %s", glxext.has_##name ? "present" : 
"absent")
+
        check_ext(GLX_SGI_video_sync);
        check_ext(GLX_SGI_swap_control);
        check_ext(GLX_OML_sync_control);
@@ -614,36 +569,4 @@
        check_ext(GLX_MESA_query_renderer);
 #endif
 #undef check_ext
-
-#define lookup(name) ((name) = (__typeof__(name))glXGetProcAddress((GLubyte 
*)#name))
-       // Checking if the returned function pointer is NULL is not really 
necessary,
-       // or maybe not even useful, since glXGetProcAddress might always return
-       // something. We are doing it just for completeness' sake.
-       if (!lookup(glXGetVideoSyncSGI) || !lookup(glXWaitVideoSyncSGI)) {
-               glxext.has_GLX_SGI_video_sync = false;
-       }
-       if (!lookup(glXSwapIntervalEXT)) {
-               glxext.has_GLX_EXT_swap_control = false;
-       }
-       if (!lookup(glXSwapIntervalMESA)) {
-               glxext.has_GLX_MESA_swap_control = false;
-       }
-       if (!lookup(glXSwapIntervalSGI)) {
-               glxext.has_GLX_SGI_swap_control = false;
-       }
-       if (!lookup(glXWaitForMscOML) || !lookup(glXGetSyncValuesOML)) {
-               glxext.has_GLX_OML_sync_control = false;
-       }
-       if (!lookup(glXBindTexImageEXT) || !lookup(glXReleaseTexImageEXT)) {
-               glxext.has_GLX_EXT_texture_from_pixmap = false;
-       }
-       if (!lookup(glXCreateContextAttribsARB)) {
-               glxext.has_GLX_ARB_create_context = false;
-       }
-#ifdef GLX_MESA_query_renderer
-       if (!lookup(glXQueryCurrentRendererIntegerMESA)) {
-               glxext.has_GLX_MESA_query_renderer = false;
-       }
-#endif
-#undef lookup
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/backend/gl/glx.h 
new/picom-11.2/src/backend/gl/glx.h
--- old/picom-11.1/src/backend/gl/glx.h 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/backend/gl/glx.h 2024-02-13 11:36:02.000000000 +0100
@@ -1,17 +1,9 @@
 // SPDX-License-Identifier: MPL-2.0
 // Copyright (c) Yuxuan Shui <yshu...@gmail.com>
 #pragma once
-#include <stdbool.h>
-// Older version of glx.h defines function prototypes for these extensions...
-// Rename them to avoid conflicts
-#define glXSwapIntervalMESA glXSwapIntervalMESA_
-#define glXBindTexImageEXT glXBindTexImageEXT_
-#define glXReleaseTexImageEXT glXReleaseTexImageEXT
-#include <GL/glx.h>
-#undef glXSwapIntervalMESA
-#undef glXBindTexImageEXT
-#undef glXReleaseTexImageEXT
 #include <X11/Xlib.h>
+#include <epoxy/glx.h>
+#include <stdbool.h>
 #include <xcb/render.h>
 #include <xcb/xcb.h>
 
@@ -59,19 +51,4 @@
 
 extern struct glxext_info glxext;
 
-extern PFNGLXGETVIDEOSYNCSGIPROC glXGetVideoSyncSGI;
-extern PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI;
-extern PFNGLXGETSYNCVALUESOMLPROC glXGetSyncValuesOML;
-extern PFNGLXWAITFORMSCOMLPROC glXWaitForMscOML;
-extern PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT;
-extern PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
-extern PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA;
-extern PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT;
-extern PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT;
-extern PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB;
-
-#ifdef GLX_MESA_query_renderer
-extern PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC 
glXQueryCurrentRendererIntegerMESA;
-#endif
-
 void glxext_init(Display *, int screen);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/event.c new/picom-11.2/src/event.c
--- old/picom-11.1/src/event.c  2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/event.c  2024-02-13 11:36:02.000000000 +0100
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: MPL-2.0
 // Copyright (c) 2019, Yuxuan Shui <yshu...@gmail.com>
 
+#include <stdint.h>
 #include <stdio.h>
 
 #include <X11/Xlibint.h>
@@ -47,8 +48,14 @@
 /// When top half finished, we enter the render stage, where no server state 
should be
 /// queried. All rendering should be done with our internal knowledge of the 
server state.
 ///
-
-// TODO(yshui) the things described above
+/// P.S. There is another reason to avoid sending any request to the server as 
much as
+/// possible. To make sure requests are sent, flushes are needed. And 
`xcb_flush`/`XFlush`
+/// functions may read more events from the server into their queues. This is
+/// undesirable, see the comments on `handle_queued_x_events` in picom.c for 
more details.
+
+// TODO(yshui) the things described above. This is mostly done, maybe some of
+//             the functions here is still making unnecessary queries, we need
+//             to do some auditing to be sure.
 
 /**
  * Get a window's name from window ID.
@@ -350,19 +357,14 @@
                }
 
                // Reset event mask in case something wrong happens
-               xcb_change_window_attributes(
-                   ps->c.c, ev->window, XCB_CW_EVENT_MASK,
-                   (const uint32_t[]){determine_evmask(ps, ev->window, 
WIN_EVMODE_UNKNOWN)});
+               uint32_t evmask = determine_evmask(ps, ev->window, 
WIN_EVMODE_UNKNOWN);
 
                if (!wid_has_prop(ps, ev->window, ps->atoms->aWM_STATE)) {
                        log_debug("Window %#010x doesn't have WM_STATE 
property, it is "
                                  "probably not a client window. But we will 
listen for "
                                  "property change in case it gains one.",
                                  ev->window);
-                       xcb_change_window_attributes(
-                           ps->c.c, ev->window, XCB_CW_EVENT_MASK,
-                           (const uint32_t[]){determine_evmask(ps, ev->window, 
WIN_EVMODE_UNKNOWN) |
-                                              XCB_EVENT_MASK_PROPERTY_CHANGE});
+                       evmask |= XCB_EVENT_MASK_PROPERTY_CHANGE;
                } else {
                        auto w_real_top = find_managed_window_or_parent(ps, 
ev->parent);
                        if (w_real_top && w_real_top->state != WSTATE_UNMAPPED 
&&
@@ -386,6 +388,8 @@
                                }
                        }
                }
+               XCB_AWAIT_VOID(xcb_change_window_attributes, ps->c.c, 
ev->window,
+                              XCB_CW_EVENT_MASK, (const uint32_t[]){evmask});
        }
 }
 
@@ -475,9 +479,10 @@
                // Check whether it could be a client window
                if (!find_toplevel(ps, ev->window)) {
                        // Reset event mask anyway
-                       xcb_change_window_attributes(ps->c.c, ev->window, 
XCB_CW_EVENT_MASK,
-                                                    (const 
uint32_t[]){determine_evmask(
-                                                        ps, ev->window, 
WIN_EVMODE_UNKNOWN)});
+                       const uint32_t evmask =
+                           determine_evmask(ps, ev->window, 
WIN_EVMODE_UNKNOWN);
+                       XCB_AWAIT_VOID(xcb_change_window_attributes, ps->c.c, 
ev->window,
+                                      XCB_CW_EVENT_MASK, (const 
uint32_t[]){evmask});
 
                        auto w_top = find_managed_window_or_parent(ps, 
ev->window);
                        // ev->window might have not been managed yet, in that 
case w_top
@@ -492,8 +497,8 @@
        // If _NET_WM_WINDOW_TYPE changes... God knows why this would happen, 
but
        // there are always some stupid applications. (#144)
        if (ev->atom == ps->atoms->a_NET_WM_WINDOW_TYPE) {
-               struct managed_win *w = NULL;
-               if ((w = find_toplevel(ps, ev->window))) {
+               struct managed_win *w = find_toplevel(ps, ev->window);
+               if (w) {
                        win_set_property_stale(w, ev->atom);
                }
        }
@@ -586,16 +591,28 @@
        region_t parts;
        pixman_region32_init(&parts);
 
+       // If this is the first time this window is damaged, we would redraw the
+       // whole window, so we don't need to fetch the damage region. But we 
still need
+       // to make sure the X server receives the DamageSubtract request, hence 
the
+       // `xcb_request_check` here.
+       // Otherwise, we fetch the damage regions. That means we will receive a 
reply
+       // from the X server, which implies it has received our DamageSubtract 
request.
        if (!w->ever_damaged) {
-               win_extents(w, &parts);
-               if (!ps->o.show_all_xerrors) {
-                       set_ignore_cookie(&ps->c, xcb_damage_subtract(ps->c.c, 
w->damage,
-                                                                     XCB_NONE, 
XCB_NONE));
+               auto e = xcb_request_check(
+                   ps->c.c, xcb_damage_subtract(ps->c.c, w->damage, XCB_NONE, 
XCB_NONE));
+               if (e) {
+                       if (ps->o.show_all_xerrors) {
+                               x_print_error(e->sequence, e->major_code, 
e->minor_code,
+                                             e->error_code);
+                       }
+                       free(e);
                }
+               win_extents(w, &parts);
        } else {
+               auto cookie =
+                   xcb_damage_subtract(ps->c.c, w->damage, XCB_NONE, 
ps->damaged_region);
                if (!ps->o.show_all_xerrors) {
-                       set_ignore_cookie(&ps->c, xcb_damage_subtract(ps->c.c, 
w->damage, XCB_NONE,
-                                                                     
ps->damaged_region));
+                       set_ignore_cookie(&ps->c, cookie);
                }
                x_fetch_region(&ps->c, ps->damaged_region, &parts);
                pixman_region32_translate(&parts, w->g.x + w->g.border_width,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/log.c new/picom-11.2/src/log.c
--- old/picom-11.1/src/log.c    2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/log.c    2024-02-13 11:36:02.000000000 +0100
@@ -9,7 +9,7 @@
 #include <unistd.h>
 
 #ifdef CONFIG_OPENGL
-#include <GL/gl.h>
+#include <epoxy/gl.h>
 #include "backend/gl/gl_common.h"
 #include "backend/gl/glx.h"
 #endif
@@ -338,21 +338,14 @@
 }
 
 #ifdef CONFIG_OPENGL
-/// An opengl logger that can be used for logging into opengl debugging tools,
-/// such as apitrace
-struct gl_string_marker_logger {
-       struct log_target tgt;
-       PFNGLSTRINGMARKERGREMEDYPROC gl_string_marker;
-};
 
-static void
-gl_string_marker_logger_write(struct log_target *tgt, const char *str, size_t 
len) {
-       auto g = (struct gl_string_marker_logger *)tgt;
+static void gl_string_marker_logger_write(struct log_target *tgt attr_unused,
+                                          const char *str, size_t len) {
        // strip newlines at the end of the string
        while (len > 0 && str[len - 1] == '\n') {
                len--;
        }
-       g->gl_string_marker((GLsizei)len, str);
+       glStringMarkerGREMEDY((GLsizei)len, str);
 }
 
 static const struct log_ops gl_string_marker_logger_ops = {
@@ -361,20 +354,16 @@
     .destroy = logger_trivial_destroy,
 };
 
+/// Create an opengl logger that can be used for logging into opengl debugging 
tools,
+/// such as apitrace
 struct log_target *gl_string_marker_logger_new(void) {
-       if (!gl_has_extension("GL_GREMEDY_string_marker")) {
+       if (!epoxy_has_gl_extension("GL_GREMEDY_string_marker")) {
                return NULL;
        }
 
-       void *fnptr = glXGetProcAddress((GLubyte *)"glStringMarkerGREMEDY");
-       if (!fnptr) {
-               return NULL;
-       }
-
-       auto ret = cmalloc(struct gl_string_marker_logger);
-       ret->tgt.ops = &gl_string_marker_logger_ops;
-       ret->gl_string_marker = fnptr;
-       return &ret->tgt;
+       auto ret = cmalloc(struct log_target);
+       ret->ops = &gl_string_marker_logger_ops;
+       return ret;
 }
 
 #else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/meson.build 
new/picom-11.2/src/meson.build
--- old/picom-11.1/src/meson.build      2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/meson.build      2024-02-13 11:36:02.000000000 +0100
@@ -58,8 +58,8 @@
 endif
 
 if get_option('opengl')
-       cflags += ['-DCONFIG_OPENGL', '-DGL_GLEXT_PROTOTYPES']
-       deps += [dependency('gl', required: true), dependency('egl', required: 
true), dependency('threads', required:true)]
+       cflags += ['-DCONFIG_OPENGL']
+       deps += [dependency('epoxy', required: true), dependency('threads', 
required:true)]
        srcs += [ 'opengl.c' ]
 endif
 
@@ -86,6 +86,10 @@
        cflags += ['-DHAS_KQUEUE']
 endif
 
+if host_system == 'openbsd'
+       deps += [dependency('threads', required: true)]
+endif
+
 subdir('backend')
 
 picom = executable('picom', srcs, c_args: cflags,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/opengl.c new/picom-11.2/src/opengl.c
--- old/picom-11.1/src/opengl.c 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/opengl.c 2024-02-13 11:36:02.000000000 +0100
@@ -181,7 +181,7 @@
        // must precede FBConfig fetching
        if (need_render) {
                psglx->has_texture_non_power_of_two =
-                   gl_has_extension("GL_ARB_texture_non_power_of_two");
+                   epoxy_has_gl_extension("GL_ARB_texture_non_power_of_two");
        }
 
        // Render preparations
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/opengl.h new/picom-11.2/src/opengl.h
--- old/picom-11.1/src/opengl.h 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/opengl.h 2024-02-13 11:36:02.000000000 +0100
@@ -18,9 +18,9 @@
 #include "render.h"
 #include "win.h"
 
-#include <GL/gl.h>
-#include <GL/glx.h>
 #include <ctype.h>
+#include <epoxy/gl.h>
+#include <epoxy/glx.h>
 #include <locale.h>
 #include <stdlib.h>
 #include <string.h>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/picom.c new/picom-11.2/src/picom.c
--- old/picom-11.1/src/picom.c  2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/picom.c  2024-02-13 11:36:02.000000000 +0100
@@ -33,6 +33,9 @@
 #include <xcb/render.h>
 #include <xcb/sync.h>
 #include <xcb/xfixes.h>
+#ifdef __OpenBSD__
+#include <pthread.h>
+#endif
 
 #include <ev.h>
 #include <test.h>
@@ -1158,14 +1161,43 @@
                }
                auto pixmap = x_get_root_back_pixmap(&ps->c, ps->atoms);
                if (pixmap != XCB_NONE) {
+                       xcb_get_geometry_reply_t *r = xcb_get_geometry_reply(
+                           ps->c.c, xcb_get_geometry(ps->c.c, pixmap), NULL);
+                       if (!r) {
+                               goto err;
+                       }
+
+                       // We used to assume that pixmaps pointed by the root 
background
+                       // pixmap atoms are owned by the root window and have 
the same
+                       // depth and hence the same visual that we can use to 
bind them.
+                       // However, some applications break this assumption, 
e.g. the
+                       // Xfce's desktop manager xfdesktop that sets the 
_XROOTPMAP_ID
+                       // atom to a pixmap owned by it that seems to always 
have 32 bpp
+                       // depth when the common root window's depth is 24 bpp. 
So use the
+                       // root window's visual only if the root background 
pixmap's depth
+                       // matches the root window's depth. Otherwise, find a 
suitable
+                       // visual for the root background pixmap's depth and 
use it.
+                       //
+                       // We can't obtain a suitable visual for the root 
background
+                       // pixmap the same way as the win_bind_pixmap function 
because it
+                       // requires a window and we have only a pixmap. We also 
can't not
+                       // bind the root background pixmap in case of depth 
mismatch
+                       // because some options rely on it's content, e.g.
+                       // transparent-clipping.
+                       xcb_visualid_t visual =
+                           r->depth == ps->c.screen_info->root_depth
+                               ? ps->c.screen_info->root_visual
+                               : x_get_visual_for_depth(&ps->c, r->depth);
+                       free(r);
+
                        ps->root_image = ps->backend_data->ops->bind_pixmap(
-                           ps->backend_data, pixmap,
-                           x_get_visual_info(&ps->c, 
ps->c.screen_info->root_visual), false);
+                           ps->backend_data, pixmap, x_get_visual_info(&ps->c, 
visual), false);
                        if (ps->root_image) {
                                ps->backend_data->ops->set_image_property(
                                    ps->backend_data, 
IMAGE_PROPERTY_EFFECTIVE_SIZE,
                                    ps->root_image, (int[]){ps->root_width, 
ps->root_height});
                        } else {
+                       err:
                                log_error("Failed to bind root back pixmap");
                        }
                }
@@ -1577,9 +1609,32 @@
        log_debug("Screen unredirected.");
 }
 
-// Handle queued events before we go to sleep
+/// Handle queued events before we go to sleep.
+///
+/// This function is called by ev_prepare watcher, which is called just before
+/// the event loop goes to sleep. X damage events are incremental, which means
+/// if we don't handle the ones X server already sent us, we won't get new 
ones.
+/// And if we don't get new ones, we won't render, i.e. we would freeze. libxcb
+/// keeps an internal queue of events, so we have to be 100% sure no events are
+/// left in that queue before we go to sleep.
 static void handle_queued_x_events(EV_P attr_unused, ev_prepare *w, int 
revents attr_unused) {
        session_t *ps = session_ptr(w, event_check);
+       // Flush because if we go into sleep when there is still requests in the
+       // outgoing buffer, they will not be sent for an indefinite amount of
+       // time. Use XFlush here too, we might still use some Xlib functions
+       // because OpenGL.
+       //
+       // Also note, after we have flushed here, we won't flush again in this
+       // function before going into sleep. This is because 
`xcb_flush`/`XFlush`
+       // may _read_ more events from the server (yes, this is ridiculous, I
+       // know). And we can't have that, see the comments above this function.
+       //
+       // This means if functions called ev_handle need to send some events,
+       // they need to carefully make sure those events are flushed, one way or
+       // another.
+       XFlush(ps->c.dpy);
+       xcb_flush(ps->c.c);
+
        if (ps->vblank_scheduler) {
                vblank_handle_x_events(ps->vblank_scheduler);
        }
@@ -1589,13 +1644,6 @@
                ev_handle(ps, ev);
                free(ev);
        };
-       // Flush because if we go into sleep when there is still
-       // requests in the outgoing buffer, they will not be sent
-       // for an indefinite amount of time.
-       // Use XFlush here too, we might still use some Xlib functions
-       // because OpenGL.
-       XFlush(ps->c.dpy);
-       xcb_flush(ps->c.c);
        int err = xcb_connection_has_error(ps->c.c);
        if (err) {
                log_fatal("X11 server connection broke (error %d)", err);
@@ -2220,6 +2268,7 @@
              c2_list_postprocess(ps, ps->o.window_shader_fg_rules) &&
              c2_list_postprocess(ps, ps->o.opacity_rules) &&
              c2_list_postprocess(ps, ps->o.rounded_corners_blacklist) &&
+             c2_list_postprocess(ps, ps->o.corner_radius_rules) &&
              c2_list_postprocess(ps, ps->o.focus_blacklist))) {
                log_error("Post-processing of conditionals failed, some of your 
rules "
                          "might not work");
@@ -2558,14 +2607,26 @@
        int ret;
        struct sched_param param;
 
+#ifndef __OpenBSD__
        ret = sched_getparam(0, &param);
+#else
+       int old_policy;
+       ret = pthread_getschedparam(pthread_self(), &old_policy, &param);
+#endif
+
        if (ret != 0) {
                log_debug("Failed to get old scheduling priority");
                return;
        }
 
        param.sched_priority = priority;
+
+#ifndef __OpenBSD__
        ret = sched_setscheduler(0, SCHED_RR, &param);
+#else
+       ret = pthread_setschedparam(pthread_self(), SCHED_RR, &param);
+#endif
+
        if (ret != 0) {
                log_info("Failed to set real-time scheduling priority to %d.", 
priority);
                return;
@@ -2633,6 +2694,7 @@
        c2_list_free(&ps->o.paint_blacklist, NULL);
        c2_list_free(&ps->o.unredir_if_possible_blacklist, NULL);
        c2_list_free(&ps->o.rounded_corners_blacklist, NULL);
+       c2_list_free(&ps->o.corner_radius_rules, NULL);
        c2_list_free(&ps->o.window_shader_fg_rules, free);
 
        // Free tracked atom list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/render.c new/picom-11.2/src/render.c
--- old/picom-11.1/src/render.c 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/render.c 2024-02-13 11:36:02.000000000 +0100
@@ -604,20 +604,27 @@
        bool fill = false;
        xcb_pixmap_t pixmap = x_get_root_back_pixmap(&ps->c, ps->atoms);
 
-       // Make sure the pixmap we got is valid
-       if (pixmap && !x_validate_pixmap(&ps->c, pixmap)) {
-               pixmap = XCB_NONE;
+       xcb_get_geometry_reply_t *r;
+       if (pixmap) {
+               r = xcb_get_geometry_reply(ps->c.c, xcb_get_geometry(ps->c.c, 
pixmap), NULL);
        }
 
        // Create a pixmap if there isn't any
-       if (!pixmap) {
+       xcb_visualid_t visual;
+       if (!pixmap || !r) {
                pixmap =
                    x_create_pixmap(&ps->c, 
(uint8_t)ps->c.screen_info->root_depth, 1, 1);
                if (pixmap == XCB_NONE) {
                        log_error("Failed to create pixmaps for root tile.");
                        return false;
                }
+               visual = ps->c.screen_info->root_visual;
                fill = true;
+       } else {
+               visual = r->depth == ps->c.screen_info->root_depth
+                            ? ps->c.screen_info->root_visual
+                            : x_get_visual_for_depth(&ps->c, r->depth);
+               free(r);
        }
 
        // Create Picture
@@ -625,7 +632,7 @@
            .repeat = true,
        };
        ps->root_tile_paint.pict = x_create_picture_with_visual_and_pixmap(
-           &ps->c, ps->c.screen_info->root_visual, pixmap, 
XCB_RENDER_CP_REPEAT, &pa);
+           &ps->c, visual, pixmap, XCB_RENDER_CP_REPEAT, &pa);
 
        // Fill pixmap if needed
        if (fill) {
@@ -646,8 +653,7 @@
        ps->root_tile_paint.pixmap = pixmap;
 #ifdef CONFIG_OPENGL
        if (BKEND_GLX == ps->o.backend) {
-               return paint_bind_tex(ps, &ps->root_tile_paint, 0, 0, true, 0,
-                                     ps->c.screen_info->root_visual, false);
+               return paint_bind_tex(ps, &ps->root_tile_paint, 0, 0, true, 0, 
visual, false);
        }
 #endif
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/vblank.c new/picom-11.2/src/vblank.c
--- old/picom-11.1/src/vblank.c 2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/vblank.c 2024-02-13 11:36:02.000000000 +0100
@@ -11,14 +11,13 @@
 
 #ifdef CONFIG_OPENGL
 // Enable sgi_video_sync_vblank_scheduler
-#include <GL/glx.h>
 #include <X11/X.h>
 #include <X11/Xlib-xcb.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <epoxy/glx.h>
 #include <pthread.h>
 
-#include "backend/gl/glx.h"
 #endif
 
 #include "compiler.h"
@@ -63,9 +62,9 @@
 
 struct vblank_scheduler_ops {
        size_t size;
-       void (*init)(struct vblank_scheduler *self);
+       bool (*init)(struct vblank_scheduler *self);
        void (*deinit)(struct vblank_scheduler *self);
-       void (*schedule)(struct vblank_scheduler *self);
+       bool (*schedule)(struct vblank_scheduler *self);
        bool (*handle_x_events)(struct vblank_scheduler *self);
 };
 
@@ -78,13 +77,14 @@
 
        // Since glXWaitVideoSyncSGI blocks, we need to run it in a separate 
thread.
        // ... and all the thread shenanigans that come with it.
-       _Atomic unsigned int last_msc;
-       _Atomic uint64_t last_ust;
+       _Atomic unsigned int current_msc;
+       _Atomic uint64_t current_ust;
        ev_async notify;
        pthread_t sync_thread;
        bool running, error;
+       unsigned int last_msc;
 
-       /// Protects `running`, `error` and `base.vblank_event_requested`
+       /// Protects `running`, and `base.vblank_event_requested`
        pthread_mutex_t vblank_requested_mtx;
        pthread_cond_t vblank_requested_cnd;
 };
@@ -110,11 +110,6 @@
                return false;
        }
 
-       glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)(void 
*)glXGetProcAddress(
-           (const GLubyte *)"glXWaitVideoSyncSGI");
-       if (!glXWaitVideoSyncSGI) {
-               return false;
-       }
        return true;
 }
 
@@ -207,8 +202,8 @@
 
                struct timespec now;
                clock_gettime(CLOCK_MONOTONIC, &now);
-               atomic_store(&self->last_msc, last_msc);
-               atomic_store(&self->last_ust,
+               atomic_store(&self->current_msc, last_msc);
+               atomic_store(&self->current_ust,
                             (uint64_t)(now.tv_sec * 1000000 + now.tv_nsec / 
1000));
                ev_async_send(self->base.loop, &self->notify);
                pthread_mutex_lock(&self->vblank_requested_mtx);
@@ -239,34 +234,30 @@
        return NULL;
 }
 
-static void sgi_video_sync_scheduler_schedule(struct vblank_scheduler *base) {
+static bool sgi_video_sync_scheduler_schedule(struct vblank_scheduler *base) {
        auto self = (struct sgi_video_sync_vblank_scheduler *)base;
-       log_verbose("Requesting vblank event for msc %d", self->last_msc + 1);
+       if (self->error) {
+               return false;
+       }
+       log_verbose("Requesting vblank event for msc %d", self->current_msc + 
1);
        pthread_mutex_lock(&self->vblank_requested_mtx);
        assert(!base->vblank_event_requested);
        base->vblank_event_requested = true;
        pthread_cond_signal(&self->vblank_requested_cnd);
        pthread_mutex_unlock(&self->vblank_requested_mtx);
+       return true;
 }
 
 static void
-sgi_video_sync_scheduler_callback(EV_P attr_unused, ev_async *w, int 
attr_unused revents) {
-       auto sched = container_of(w, struct sgi_video_sync_vblank_scheduler, 
notify);
-       auto event = (struct vblank_event){
-           .msc = atomic_load(&sched->last_msc),
-           .ust = atomic_load(&sched->last_ust),
-       };
-       sched->base.vblank_event_requested = false;
-       log_verbose("Received vblank event for msc %lu", event.msc);
-       vblank_scheduler_invoke_callbacks(&sched->base, &event);
-}
+sgi_video_sync_scheduler_callback(EV_P attr_unused, ev_async *w, int 
attr_unused revents);
 
-static void sgi_video_sync_scheduler_init(struct vblank_scheduler *base) {
+static bool sgi_video_sync_scheduler_init(struct vblank_scheduler *base) {
        auto self = (struct sgi_video_sync_vblank_scheduler *)base;
        auto args = (struct sgi_video_sync_thread_args){
            .self = self,
            .start_status = -1,
        };
+       bool succeeded = true;
        pthread_mutex_init(&args.start_mtx, NULL);
        pthread_cond_init(&args.start_cnd, NULL);
 
@@ -286,11 +277,15 @@
        if (args.start_status != 0) {
                log_fatal("Failed to start sgi_video_sync_thread, error code: 
%d",
                          args.start_status);
-               abort();
+               succeeded = false;
+       } else {
+               log_info("Started sgi_video_sync_thread");
        }
+       self->error = !succeeded;
+       self->last_msc = 0;
        pthread_mutex_destroy(&args.start_mtx);
        pthread_cond_destroy(&args.start_cnd);
-       log_info("Started sgi_video_sync_thread");
+       return succeeded;
 }
 
 static void sgi_video_sync_scheduler_deinit(struct vblank_scheduler *base) {
@@ -306,15 +301,45 @@
        pthread_mutex_destroy(&self->vblank_requested_mtx);
        pthread_cond_destroy(&self->vblank_requested_cnd);
 }
+
+static void
+sgi_video_sync_scheduler_callback(EV_P attr_unused, ev_async *w, int 
attr_unused revents) {
+       auto sched = container_of(w, struct sgi_video_sync_vblank_scheduler, 
notify);
+       auto msc = atomic_load(&sched->current_msc);
+       if (sched->last_msc == msc) {
+               // NVIDIA spams us with duplicate vblank events after a 
suspend/resume
+               // cycle. Recreating the X connection and GLX context seems to 
fix this.
+               // Oh NVIDIA.
+               log_warn("Duplicate vblank event found with msc %d. Possible 
NVIDIA bug?", msc);
+               log_warn("Resetting the vblank scheduler");
+               sgi_video_sync_scheduler_deinit(&sched->base);
+               sched->base.vblank_event_requested = false;
+               if (!sgi_video_sync_scheduler_init(&sched->base)) {
+                       log_error("Failed to reset the vblank scheduler");
+               } else {
+                       sgi_video_sync_scheduler_schedule(&sched->base);
+               }
+               return;
+       }
+       auto event = (struct vblank_event){
+           .msc = msc,
+           .ust = atomic_load(&sched->current_ust),
+       };
+       sched->base.vblank_event_requested = false;
+       sched->last_msc = msc;
+       log_verbose("Received vblank event for msc %lu", event.msc);
+       vblank_scheduler_invoke_callbacks(&sched->base, &event);
+}
 #endif
 
-static void present_vblank_scheduler_schedule(struct vblank_scheduler *base) {
+static bool present_vblank_scheduler_schedule(struct vblank_scheduler *base) {
        auto self = (struct present_vblank_scheduler *)base;
        log_verbose("Requesting vblank event for window 0x%08x, msc %" PRIu64,
                    base->target_window, self->last_msc + 1);
        assert(!base->vblank_event_requested);
        x_request_vblank_event(base->c, base->target_window, self->last_msc + 
1);
        base->vblank_event_requested = true;
+       return true;
 }
 
 static void present_vblank_callback(EV_P attr_unused, ev_timer *w, int 
attr_unused revents) {
@@ -327,7 +352,7 @@
        vblank_scheduler_invoke_callbacks(&sched->base, &event);
 }
 
-static void present_vblank_scheduler_init(struct vblank_scheduler *base) {
+static bool present_vblank_scheduler_init(struct vblank_scheduler *base) {
        auto self = (struct present_vblank_scheduler *)base;
        base->type = VBLANK_SCHEDULER_PRESENT;
        ev_timer_init(&self->callback_timer, present_vblank_callback, 0, 0);
@@ -339,6 +364,7 @@
        set_cant_fail_cookie(base->c, select_input);
        self->event =
            xcb_register_for_special_xge(base->c->c, &xcb_present_id, 
self->event_id, NULL);
+       return true;
 }
 
 static void present_vblank_scheduler_deinit(struct vblank_scheduler *base) {
@@ -439,17 +465,19 @@
 #endif
 };
 
-static void vblank_scheduler_schedule_internal(struct vblank_scheduler *self) {
+static bool vblank_scheduler_schedule_internal(struct vblank_scheduler *self) {
        assert(self->type < LAST_VBLANK_SCHEDULER);
        auto fn = vblank_scheduler_ops[self->type].schedule;
        assert(fn != NULL);
-       fn(self);
+       return fn(self);
 }
 
 bool vblank_scheduler_schedule(struct vblank_scheduler *self,
                                vblank_callback_t vblank_callback, void 
*user_data) {
        if (self->callback_count == 0 && self->wind_down == 0) {
-               vblank_scheduler_schedule_internal(self);
+               if (!vblank_scheduler_schedule_internal(self)) {
+                       return false;
+               }
        }
        if (self->callback_count == self->callback_capacity) {
                size_t new_capacity =
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/x.c new/picom-11.2/src/x.c
--- old/picom-11.1/src/x.c      2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/x.c      2024-02-13 11:36:02.000000000 +0100
@@ -321,6 +321,21 @@
        return x_get_visual_for_pictfmt(g_pictfmts, pictfmt->id);
 }
 
+xcb_visualid_t x_get_visual_for_depth(struct x_connection *c, uint8_t depth) {
+       xcb_screen_iterator_t screen_it = 
xcb_setup_roots_iterator(xcb_get_setup(c->c));
+       for (; screen_it.rem; xcb_screen_next(&screen_it)) {
+               xcb_depth_iterator_t depth_it =
+                   xcb_screen_allowed_depths_iterator(screen_it.data);
+               for (; depth_it.rem; xcb_depth_next(&depth_it)) {
+                       if (depth_it.data->depth == depth) {
+                               return 
xcb_depth_visuals_iterator(depth_it.data).data->visual_id;
+                       }
+               }
+       }
+
+       return XCB_NONE;
+}
+
 xcb_render_pictformat_t
 x_get_pictfmt_for_standard(struct x_connection *c, xcb_pict_standard_t std) {
        x_get_server_pictfmts(c);
@@ -717,27 +732,6 @@
        return XCB_NONE;
 }
 
-/**
- * Validate a pixmap.
- *
- * Detect whether the pixmap is valid with XGetGeometry. Well, maybe there
- * are better ways.
- */
-bool x_validate_pixmap(struct x_connection *c, xcb_pixmap_t pixmap) {
-       if (pixmap == XCB_NONE) {
-               return false;
-       }
-
-       auto r = xcb_get_geometry_reply(c->c, xcb_get_geometry(c->c, pixmap), 
NULL);
-       if (!r) {
-               return false;
-       }
-
-       bool ret = r->width && r->height;
-       free(r);
-       return ret;
-}
-
 /// We don't use the _XSETROOT_ID root window property as a source of the 
background
 /// pixmap because it most likely points to a dummy pixmap used to keep the 
colormap
 /// associated with the background pixmap alive but we listen for it's changes 
and update
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/picom-11.1/src/x.h new/picom-11.2/src/x.h
--- old/picom-11.1/src/x.h      2024-01-28 19:17:19.000000000 +0100
+++ new/picom-11.2/src/x.h      2024-02-13 11:36:02.000000000 +0100
@@ -359,8 +359,6 @@
 
 xcb_pixmap_t x_create_pixmap(struct x_connection *, uint8_t depth, int width, 
int height);
 
-bool x_validate_pixmap(struct x_connection *, xcb_pixmap_t pxmap);
-
 /**
  * Free a <code>winprop_t</code>.
  *
@@ -411,6 +409,8 @@
 
 xcb_visualid_t x_get_visual_for_standard(struct x_connection *c, 
xcb_pict_standard_t std);
 
+xcb_visualid_t x_get_visual_for_depth(struct x_connection *c, uint8_t depth);
+
 xcb_render_pictformat_t
 x_get_pictfmt_for_standard(struct x_connection *c, xcb_pict_standard_t std);
 

Reply via email to