diff options
author | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2020-09-12 20:01:06 +0300 |
---|---|---|
committer | Alberts Muktupāvels <alberts.muktupavels@gmail.com> | 2020-09-12 20:01:06 +0300 |
commit | bbf6760f9eab421bd558cbb45872ceafa033b21c (patch) | |
tree | 6bd813d9f73e949815da57e57425f35f752f1fab /src | |
parent | af8278f7f222dcfa3e3a5d1895e21ce5aa55c084 (diff) | |
download | metacity-bbf6760f9eab421bd558cbb45872ceafa033b21c.tar.gz |
compositor: add MetaCompositorXPresent
https://gitlab.gnome.org/GNOME/metacity/-/issues/13
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/compositor/meta-compositor-vulkan.c | 1 | ||||
-rw-r--r-- | src/compositor/meta-compositor-xpresent.c | 281 | ||||
-rw-r--r-- | src/compositor/meta-compositor-xpresent.h | 34 | ||||
-rw-r--r-- | src/core/display.c | 7 | ||||
-rw-r--r-- | src/include/meta-compositor.h | 1 |
6 files changed, 326 insertions, 0 deletions
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; |