summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlberts Muktupāvels <alberts.muktupavels@gmail.com>2020-09-12 20:01:06 +0300
committerAlberts Muktupāvels <alberts.muktupavels@gmail.com>2020-09-12 20:01:06 +0300
commitbbf6760f9eab421bd558cbb45872ceafa033b21c (patch)
tree6bd813d9f73e949815da57e57425f35f752f1fab
parentaf8278f7f222dcfa3e3a5d1895e21ce5aa55c084 (diff)
downloadmetacity-bbf6760f9eab421bd558cbb45872ceafa033b21c.tar.gz
compositor: add MetaCompositorXPresent
https://gitlab.gnome.org/GNOME/metacity/-/issues/13
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/compositor/meta-compositor-vulkan.c1
-rw-r--r--src/compositor/meta-compositor-xpresent.c281
-rw-r--r--src/compositor/meta-compositor-xpresent.h34
-rw-r--r--src/core/display.c7
-rw-r--r--src/include/meta-compositor.h1
8 files changed, 328 insertions, 1 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 205995ba..7a967c5b 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -30,6 +30,7 @@ variables:
libxext-dev
libxfixes-dev
libxinerama-dev
+ libxpresent-dev
libxrandr-dev
libxrender-dev
libxres-dev
diff --git a/configure.ac b/configure.ac
index e09b938d..9d15bdde 100644
--- a/configure.ac
+++ b/configure.ac
@@ -155,7 +155,7 @@ AC_CHECK_SIZEOF(__int64)
## byte order
AC_C_BIGENDIAN
-METACITY_PC_MODULES="gtk+-3.0 >= $GTK_REQUIRED_VERSION gio-2.0 >= $GLIB_REQUIRED_VERSION pango >= $PANGO_REQUIRED_VERSION gsettings-desktop-schemas >= 3.3.0 xcomposite >= $XCOMPOSITE_REQUIRED_VERSION xfixes xrender xdamage xres"
+METACITY_PC_MODULES="gtk+-3.0 >= $GTK_REQUIRED_VERSION gio-2.0 >= $GLIB_REQUIRED_VERSION pango >= $PANGO_REQUIRED_VERSION gsettings-desktop-schemas >= 3.3.0 xcomposite >= $XCOMPOSITE_REQUIRED_VERSION xfixes xrender xdamage xres xpresent"
GLIB_GSETTINGS
diff --git a/src/Makefile.am b/src/Makefile.am
index 029e50b5..4f703eb3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,6 +33,8 @@ metacity_SOURCES = \
compositor/meta-compositor-none.c \
compositor/meta-compositor-none.h \
compositor/meta-compositor-private.h \
+ compositor/meta-compositor-xpresent.c \
+ compositor/meta-compositor-xpresent.h \
compositor/meta-compositor-xrender.c \
compositor/meta-compositor-xrender.h \
compositor/meta-shadow-xrender.c \
diff --git a/src/compositor/meta-compositor-vulkan.c b/src/compositor/meta-compositor-vulkan.c
index d543bbb2..44ab0d8d 100644
--- a/src/compositor/meta-compositor-vulkan.c
+++ b/src/compositor/meta-compositor-vulkan.c
@@ -1204,6 +1204,7 @@ not_implemented_cb (MetaCompositorVulkan *vulkan)
compositor = "xrender";
break;
+ case META_COMPOSITOR_TYPE_XPRESENT:
case META_COMPOSITOR_TYPE_EXTERNAL:
case META_COMPOSITOR_TYPE_VULKAN:
default:
diff --git a/src/compositor/meta-compositor-xpresent.c b/src/compositor/meta-compositor-xpresent.c
new file mode 100644
index 00000000..3e610a9d
--- /dev/null
+++ b/src/compositor/meta-compositor-xpresent.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2020 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "meta-compositor-xpresent.h"
+
+#include <X11/extensions/Xpresent.h>
+
+#include "display-private.h"
+#include "errors.h"
+#include "screen-private.h"
+
+#define NUM_BUFFER 2
+
+struct _MetaCompositorXPresent
+{
+ MetaCompositorXRender parent;
+
+ int major_opcode;
+ int event_base;
+ int error_base;
+
+ Picture root_buffers[NUM_BUFFER];
+ Pixmap root_pixmaps[NUM_BUFFER];
+ int root_current;
+
+ gboolean present_pending;
+};
+
+G_DEFINE_TYPE (MetaCompositorXPresent,
+ meta_compositor_xpresent,
+ META_TYPE_COMPOSITOR_XRENDER)
+
+static gboolean
+meta_compositor_xpresent_manage (MetaCompositor *compositor,
+ GError **error)
+{
+ MetaCompositorClass *compositor_class;
+ MetaCompositorXPresent *self;
+ MetaDisplay *display;
+ Display *xdisplay;
+
+ compositor_class = META_COMPOSITOR_CLASS (meta_compositor_xpresent_parent_class);
+
+ if (!compositor_class->manage (compositor, error))
+ return FALSE;
+
+ self = META_COMPOSITOR_XPRESENT (compositor);
+
+ display = meta_compositor_get_display (compositor);
+ xdisplay = meta_display_get_xdisplay (display);
+
+ if (!XPresentQueryExtension (xdisplay,
+ &self->major_opcode,
+ &self->event_base,
+ &self->error_base))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Missing present extension required for compositing");
+
+ return FALSE;
+ }
+
+ XPresentSelectInput (xdisplay,
+ meta_compositor_get_overlay_window (compositor),
+ PresentCompleteNotifyMask);
+
+ return TRUE;
+}
+
+static void
+meta_compositor_xpresent_process_event (MetaCompositor *compositor,
+ XEvent *event,
+ MetaWindow *window)
+{
+ MetaCompositorXPresent *self;
+ MetaCompositorClass *compositor_class;
+
+ self = META_COMPOSITOR_XPRESENT (compositor);
+
+ if (event->type == GenericEvent)
+ {
+ XGenericEvent *generic_event;
+ XGenericEventCookie *generic_event_cookie;
+ MetaDisplay *display;
+ Display *xdisplay;
+
+ generic_event = (XGenericEvent *) event;
+ generic_event_cookie = (XGenericEventCookie *) generic_event;
+
+ display = meta_compositor_get_display (compositor);
+ xdisplay = meta_display_get_xdisplay (display);
+
+ if (generic_event_cookie->extension == self->major_opcode)
+ {
+ XGetEventData (xdisplay, generic_event_cookie);
+
+ if (generic_event_cookie->evtype == PresentCompleteNotify)
+ {
+ meta_compositor_queue_redraw (compositor);
+ self->present_pending = FALSE;
+ }
+
+ XFreeEventData (xdisplay, generic_event_cookie);
+ }
+ }
+
+ compositor_class = META_COMPOSITOR_CLASS (meta_compositor_xpresent_parent_class);
+ compositor_class->process_event (compositor, event, window);
+}
+
+static gboolean
+meta_compositor_xpresent_ready_to_redraw (MetaCompositor *compositor)
+{
+ MetaCompositorXPresent *self;
+
+ self = META_COMPOSITOR_XPRESENT (compositor);
+
+ return !self->present_pending;
+}
+
+static void
+meta_compositor_xpresent_redraw (MetaCompositor *compositor,
+ XserverRegion all_damage)
+{
+ MetaCompositorXPresent *self;
+ MetaDisplay *display;
+ Display *xdisplay;
+ int result;
+
+ self = META_COMPOSITOR_XPRESENT (compositor);
+
+ display = meta_compositor_get_display (META_COMPOSITOR (self));
+ xdisplay = meta_display_get_xdisplay (display);
+
+ meta_compositor_xrender_draw (META_COMPOSITOR_XRENDER (compositor),
+ self->root_buffers[self->root_current],
+ all_damage);
+
+ meta_error_trap_push (display);
+
+ XPresentPixmap (xdisplay,
+ meta_compositor_get_overlay_window (compositor),
+ self->root_pixmaps[self->root_current],
+ 0,
+ all_damage,
+ all_damage,
+ 0,
+ 0,
+ None,
+ None,
+ None,
+ PresentOptionNone,
+ 0,
+ 1,
+ 0,
+ NULL,
+ 0);
+
+ result = meta_error_trap_pop_with_return (display);
+
+ if (result != Success)
+ {
+ char error_text[64];
+
+ XGetErrorText (xdisplay, result, error_text, 63);
+
+ g_warning ("XPresentPixmap failed with error %i (%s)",
+ result, error_text);
+
+ g_unsetenv ("META_COMPOSITOR");
+ meta_display_update_compositor (display);
+
+ return;
+ }
+
+ self->root_current = !self->root_current;
+ self->present_pending = TRUE;
+}
+
+static void
+meta_compositor_xpresent_ensure_root_buffers (MetaCompositorXRender *xrender)
+{
+ MetaCompositorXPresent *self;
+ int i;
+
+ self = META_COMPOSITOR_XPRESENT (xrender);
+
+ for (i = 0; i < NUM_BUFFER; i++)
+ {
+ if (self->root_buffers[i] == None &&
+ self->root_pixmaps[i] == None)
+ {
+ meta_compositor_xrender_create_root_buffer (xrender,
+ &self->root_pixmaps[i],
+ &self->root_buffers[i]);
+ }
+ }
+}
+
+static void
+meta_compositor_xpresent_free_root_buffers (MetaCompositorXRender *xrender)
+{
+ MetaCompositorXPresent *self;
+ MetaDisplay *display;
+ Display *xdisplay;
+ int i;
+
+ self = META_COMPOSITOR_XPRESENT (xrender);
+
+ display = meta_compositor_get_display (META_COMPOSITOR (self));
+ xdisplay = meta_display_get_xdisplay (display);
+
+ for (i = 0; i < NUM_BUFFER; i++)
+ {
+ if (self->root_buffers[i] != None)
+ {
+ XRenderFreePicture (xdisplay, self->root_buffers[i]);
+ self->root_buffers[i] = None;
+ }
+
+ if (self->root_pixmaps[i] != None)
+ {
+ XFreePixmap (xdisplay, self->root_pixmaps[i]);
+ self->root_pixmaps[i] = None;
+ }
+ }
+}
+
+static void
+meta_compositor_xpresent_class_init (MetaCompositorXPresentClass *self_class)
+{
+ MetaCompositorClass *compositor_class;
+ MetaCompositorXRenderClass *xrender_class;
+
+ compositor_class = META_COMPOSITOR_CLASS (self_class);
+ xrender_class = META_COMPOSITOR_XRENDER_CLASS (self_class);
+
+ compositor_class->manage = meta_compositor_xpresent_manage;
+ compositor_class->process_event = meta_compositor_xpresent_process_event;
+ compositor_class->ready_to_redraw = meta_compositor_xpresent_ready_to_redraw;
+ compositor_class->redraw = meta_compositor_xpresent_redraw;
+
+ xrender_class->ensure_root_buffers = meta_compositor_xpresent_ensure_root_buffers;
+ xrender_class->free_root_buffers = meta_compositor_xpresent_free_root_buffers;
+}
+
+static void
+meta_compositor_xpresent_init (MetaCompositorXPresent *self)
+{
+ int i;
+
+ for (i = 0; i < NUM_BUFFER; i++)
+ {
+ self->root_buffers[i] = None;
+ self->root_pixmaps[i] = None;
+ }
+}
+
+MetaCompositor *
+meta_compositor_xpresent_new (MetaDisplay *display,
+ GError **error)
+{
+ return g_initable_new (META_TYPE_COMPOSITOR_XPRESENT, NULL, error,
+ "display", display,
+ NULL);
+}
diff --git a/src/compositor/meta-compositor-xpresent.h b/src/compositor/meta-compositor-xpresent.h
new file mode 100644
index 00000000..1c7bf5d4
--- /dev/null
+++ b/src/compositor/meta-compositor-xpresent.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_COMPOSITOR_XPRESENT_H
+#define META_COMPOSITOR_XPRESENT_H
+
+#include "meta-compositor-xrender.h"
+
+G_BEGIN_DECLS
+
+#define META_TYPE_COMPOSITOR_XPRESENT (meta_compositor_xpresent_get_type ())
+G_DECLARE_FINAL_TYPE (MetaCompositorXPresent, meta_compositor_xpresent,
+ META, COMPOSITOR_XPRESENT, MetaCompositorXRender)
+
+MetaCompositor *meta_compositor_xpresent_new (MetaDisplay *display,
+ GError **error);
+
+G_END_DECLS
+
+#endif
diff --git a/src/core/display.c b/src/core/display.c
index e05ea467..75db10a8 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -68,6 +68,7 @@
#include "compositor/meta-compositor-none.h"
#include "compositor/meta-compositor-xrender.h"
+#include "compositor/meta-compositor-xpresent.h"
#include "compositor/meta-compositor-external.h"
#ifdef HAVE_VULKAN
@@ -278,6 +279,8 @@ get_compositor_type (MetaDisplay *display)
type = META_COMPOSITOR_TYPE_VULKAN;
else if (g_strcmp0 (compositor, "xrender") == 0)
type = META_COMPOSITOR_TYPE_XRENDER;
+ else if (g_strcmp0 (compositor, "xpresent") == 0)
+ type = META_COMPOSITOR_TYPE_XPRESENT;
else if (g_strcmp0 (compositor, "external") == 0)
type = META_COMPOSITOR_TYPE_EXTERNAL;
else
@@ -310,6 +313,10 @@ create_compositor (MetaDisplay *display,
compositor = meta_compositor_xrender_new (display, error);
break;
+ case META_COMPOSITOR_TYPE_XPRESENT:
+ compositor = meta_compositor_xpresent_new (display, error);
+ break;
+
case META_COMPOSITOR_TYPE_EXTERNAL:
compositor = meta_compositor_external_new (display, error);
break;
diff --git a/src/include/meta-compositor.h b/src/include/meta-compositor.h
index ee84f907..9e0778a6 100644
--- a/src/include/meta-compositor.h
+++ b/src/include/meta-compositor.h
@@ -35,6 +35,7 @@ typedef enum
{
META_COMPOSITOR_TYPE_NONE,
META_COMPOSITOR_TYPE_XRENDER,
+ META_COMPOSITOR_TYPE_XPRESENT, /*< skip >*/
META_COMPOSITOR_TYPE_EXTERNAL, /*< skip >*/
META_COMPOSITOR_TYPE_VULKAN /*< skip >*/
} MetaCompositorType;