swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit bd1a974fc2801c104a873b5820d80f695d4228b2
parent 351b43dc6d1583a402434f8f3a6bae432937ae81
Author: Michael Forney <mforney@mforney.org>
Date:   Wed, 28 Aug 2019 23:38:54 -0700

Use universal planes for cursor

Diffstat:
Dlibswc/cursor_plane.c | 121-------------------------------------------------------------------------------
Dlibswc/cursor_plane.h | 39---------------------------------------
Mlibswc/drm.c | 46++++++++++++++++++++++++++++++++++++++++------
Mlibswc/local.mk | 2+-
Alibswc/plane.c | 174+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alibswc/plane.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Mlibswc/pointer.c | 15++++++++++-----
Mlibswc/screen.c | 15+++++++--------
Mlibswc/screen.h | 6+++---
9 files changed, 280 insertions(+), 183 deletions(-)

diff --git a/libswc/cursor_plane.c b/libswc/cursor_plane.c @@ -1,121 +0,0 @@ -/* swc: cursor_plane.c - * - * Copyright (c) 2013, 2014 Michael Forney - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "cursor_plane.h" -#include "drm.h" -#include "event.h" -#include "internal.h" -#include "launch.h" -#include "screen.h" -#include "util.h" - -#include <errno.h> -#include <wld/wld.h> -#include <wld/drm.h> -#include <xf86drmMode.h> - -static bool -update(struct view *view) -{ - return true; -} - -static int -attach(struct view *view, struct wld_buffer *buffer) -{ - struct cursor_plane *plane = wl_container_of(view, plane, view); - - if (buffer) { - union wld_object object; - - if (!wld_export(buffer, WLD_DRM_OBJECT_HANDLE, &object)) { - ERROR("Could not get export buffer to DRM handle\n"); - /* XXX: Not the best error code, but we don't know better until wld - * returns an actual error code. */ - return -EINVAL; - } - - if (swc.active && drmModeSetCursor(swc.drm->fd, plane->crtc, object.u32, buffer->width, buffer->height) < 0) { - ERROR("Could not set cursor: %s\n", strerror(errno)); - return -errno; - } - } else if (swc.active && drmModeSetCursor(swc.drm->fd, plane->crtc, 0, 0, 0) < 0) { - ERROR("Could not unset cursor: %s\n", strerror(errno)); - return -errno; - } - - view_set_size_from_buffer(view, buffer); - return 0; -} - -static bool -move(struct view *view, int32_t x, int32_t y) -{ - struct cursor_plane *plane = wl_container_of(view, plane, view); - - if (swc.active && drmModeMoveCursor(swc.drm->fd, plane->crtc, x - plane->origin->x, y - plane->origin->y) != 0) { - ERROR("Could not move cursor: %s\n", strerror(errno)); - return false; - } - - view_set_position(view, x, y); - - return true; -} - -static const struct view_impl view_impl = { - .update = update, - .attach = attach, - .move = move, -}; - -static void -handle_swc_event(struct wl_listener *listener, void *data) -{ - struct event *event = data; - struct cursor_plane *plane = wl_container_of(listener, plane, swc_listener); - - switch (event->type) { - case SWC_EVENT_ACTIVATED: - move(&plane->view, plane->view.geometry.x, plane->view.geometry.y); - attach(&plane->view, plane->view.buffer); - break; - } -} - -bool -cursor_plane_initialize(struct cursor_plane *plane, uint32_t crtc, const struct swc_rectangle *origin) -{ - plane->origin = origin; - plane->crtc = crtc; - plane->swc_listener.notify = &handle_swc_event; - wl_signal_add(&swc.event_signal, &plane->swc_listener); - view_initialize(&plane->view, &view_impl); - - return true; -} - -void -cursor_plane_finalize(struct cursor_plane *plane) -{ -} diff --git a/libswc/cursor_plane.h b/libswc/cursor_plane.h @@ -1,39 +0,0 @@ -/* swc: libswc/cursor_plane.h - * - * Copyright (c) 2013, 2014 Michael Forney - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef SWC_CURSOR_PLANE_H -#define SWC_CURSOR_PLANE_H - -#include "view.h" - -struct cursor_plane { - struct view view; - const struct swc_rectangle *origin; - uint32_t crtc; - struct wl_listener swc_listener; -}; - -bool cursor_plane_initialize(struct cursor_plane *plane, uint32_t crtc, const struct swc_rectangle *origin); -void cursor_plane_finalize(struct cursor_plane *plane); - -#endif diff --git a/libswc/drm.c b/libswc/drm.c @@ -27,6 +27,7 @@ #include "internal.h" #include "launch.h" #include "output.h" +#include "plane.h" #include "screen.h" #include "util.h" #include "wayland_buffer.h" @@ -269,6 +270,10 @@ drm_initialize(void) ERROR("Could not open DRM device at %s\n", primary); goto error0; } + if (drmSetClientCap(swc.drm->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) { + ERROR("Could not enable DRM universal planes\n"); + goto error1; + } if (drmGetCap(swc.drm->fd, DRM_CAP_CURSOR_WIDTH, &val) < 0) val = 64; swc.drm->cursor_w = val; @@ -341,17 +346,32 @@ drm_finalize(void) bool drm_create_screens(struct wl_list *screens) { + drmModePlaneRes *plane_ids; drmModeRes *resources; drmModeConnector *connector; - int i; + struct plane *plane, *cursor_plane; struct output *output; - uint32_t taken_crtcs = 0; + uint32_t i, taken_crtcs = 0; + struct wl_list planes; - if (!(resources = drmModeGetResources(swc.drm->fd))) { - ERROR("Could not get DRM resources\n"); + plane_ids = drmModeGetPlaneResources(swc.drm->fd); + if (!plane_ids) { + ERROR("Could not get DRM plane resources\n"); return false; } + wl_list_init(&planes); + for (i = 0; i < plane_ids->count_planes; ++i) { + plane = plane_new(plane_ids->planes[i]); + if (plane) + wl_list_insert(&planes, &plane->link); + } + drmModeFreePlaneResources(plane_ids); + resources = drmModeGetResources(swc.drm->fd); + if (!resources) { + ERROR("Could not get DRM resources\n"); + return false; + } for (i = 0; i < resources->count_connectors; ++i, drmModeFreeConnector(connector)) { connector = drmModeGetConnector(swc.drm->fd, resources->connectors[i]); @@ -364,6 +384,18 @@ drm_create_screens(struct wl_list *screens) continue; } + cursor_plane = NULL; + wl_list_for_each (plane, &planes, link) { + if (plane->type == DRM_PLANE_TYPE_CURSOR && plane->possible_crtcs & 1 << crtc_index) { + wl_list_remove(&plane->link); + cursor_plane = plane; + break; + } + } + if (!cursor_plane) { + WARNING("Could not find cursor plane for CRTC %d\n", crtc_index); + } + if (!find_available_id(&id)) { WARNING("No more available output IDs\n"); drmModeFreeConnector(connector); @@ -373,7 +405,7 @@ drm_create_screens(struct wl_list *screens) if (!(output = output_new(connector))) continue; - output->screen = screen_new(resources->crtcs[crtc_index], output); + output->screen = screen_new(resources->crtcs[crtc_index], output, cursor_plane); output->screen->id = id; taken_crtcs |= 1 << crtc_index; @@ -382,7 +414,6 @@ drm_create_screens(struct wl_list *screens) wl_list_insert(screens, &output->screen->link); } } - drmModeFreeResources(resources); return true; @@ -430,6 +461,9 @@ drm_get_framebuffer(struct wld_buffer *buffer) union wld_object object; int ret; + if (!buffer) + return 0; + if (wld_export(buffer, WLD_USER_OBJECT_FRAMEBUFFER, &object)) return object.u32; diff --git a/libswc/local.mk b/libswc/local.mk @@ -24,7 +24,6 @@ SWC_SOURCES = \ launch/protocol.c \ libswc/bindings.c \ libswc/compositor.c \ - libswc/cursor_plane.c \ libswc/data.c \ libswc/data_device.c \ libswc/data_device_manager.c \ @@ -37,6 +36,7 @@ SWC_SOURCES = \ libswc/output.c \ libswc/panel.c \ libswc/panel_manager.c \ + libswc/plane.c \ libswc/pointer.c \ libswc/primary_plane.c \ libswc/region.c \ diff --git a/libswc/plane.c b/libswc/plane.c @@ -0,0 +1,174 @@ +/* swc: libswc/plane.c + * + * Copyright (c) 2019 Michael Forney + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "plane.h" +#include "event.h" +#include "drm.h" +#include "internal.h" +#include "screen.h" +#include "util.h" + +#include <errno.h> +#include <stdlib.h> +#include <wld/wld.h> +#include <wld/drm.h> +#include <xf86drmMode.h> + +enum plane_property { + PLANE_TYPE, + PLANE_IN_FENCE_FD, + PLANE_CRTC_ID, + PLANE_CRTC_X, + PLANE_CRTC_Y, + PLANE_CRTC_W, + PLANE_CRTC_H, + PLANE_SRC_X, + PLANE_SRC_Y, + PLANE_SRC_W, + PLANE_SRC_H, +}; + +static bool +update(struct view *view) +{ + struct plane *plane = wl_container_of(view, plane, view); + uint32_t x, y, w, h; + + if (!plane->screen) + return false; + x = view->geometry.x - plane->screen->base.geometry.x; + y = view->geometry.y - plane->screen->base.geometry.y; + w = view->geometry.width; + h = view->geometry.height; + if (swc.active && drmModeSetPlane(swc.drm->fd, plane->id, plane->screen->crtc, plane->fb, 0, x, y, w, h, 0, 0, w << 16, h << 16) < 0) { + ERROR("Could not set cursor: %s\n", strerror(errno)); + return false; + } + + return true; +} + +static int +attach(struct view *view, struct wld_buffer *buffer) +{ + struct plane *plane = wl_container_of(view, plane, view); + + plane->fb = drm_get_framebuffer(buffer); + view_set_size_from_buffer(view, buffer); + return 0; +} + +static bool +move(struct view *view, int32_t x, int32_t y) +{ + view_set_position(view, x, y); + return true; +} + +static const struct view_impl view_impl = { + .update = update, + .attach = attach, + .move = move, +}; + +static enum plane_property +find_prop(const char *name) +{ + static const char property_names[][16] = { + [PLANE_TYPE] = "type", + [PLANE_IN_FENCE_FD] = "IN_FENCE_FD", + [PLANE_CRTC_ID] = "CRTC_ID", + [PLANE_CRTC_X] = "CRTC_X", + [PLANE_CRTC_Y] = "CRTC_Y", + [PLANE_CRTC_W] = "CRTC_W", + [PLANE_CRTC_H] = "CRTC_H", + [PLANE_SRC_X] = "SRC_X", + [PLANE_SRC_Y] = "SRC_Y", + [PLANE_SRC_W] = "SRC_W", + [PLANE_SRC_H] = "SRC_H", + }; + size_t i; + + for (i = 0; i < ARRAY_LENGTH(property_names); ++i) { + if (strcmp(name, property_names[i]) == 0) + return i; + } + return -1; +} + +static void +handle_swc_event(struct wl_listener *listener, void *data) +{ + struct event *event = data; + struct plane *plane = wl_container_of(listener, plane, swc_listener); + + switch (event->type) { + case SWC_EVENT_ACTIVATED: + update(&plane->view); + break; + } +} + +struct plane * +plane_new(uint32_t id) +{ + struct plane *plane; + uint32_t i; + drmModeObjectProperties *props; + drmModePropertyRes *prop; + drmModePlane *drm_plane; + + plane = malloc(sizeof(*plane)); + if (!plane) + goto error0; + drm_plane = drmModeGetPlane(swc.drm->fd, id); + if (!drm_plane) + goto error1; + plane->id = id; + plane->fb = 0; + plane->screen = NULL; + plane->possible_crtcs = drm_plane->possible_crtcs; + drmModeFreePlane(drm_plane); + plane->type = -1; + props = drmModeObjectGetProperties(swc.drm->fd, id, DRM_MODE_OBJECT_PLANE); + for (i = 0; i < props->count_props; ++i, drmModeFreeProperty(prop)) { + prop = drmModeGetProperty(swc.drm->fd, props->props[i]); + if (prop && find_prop(prop->name) == PLANE_TYPE) + plane->type = props->prop_values[i]; + } + plane->swc_listener.notify = &handle_swc_event; + wl_signal_add(&swc.event_signal, &plane->swc_listener); + view_initialize(&plane->view, &view_impl); + return plane; + +error1: + free(plane); +error0: + return NULL; +} + +void +plane_destroy(struct plane *plane) +{ + free(plane); +} diff --git a/libswc/plane.h b/libswc/plane.h @@ -0,0 +1,45 @@ +/* swc: libswc/plane.h + * + * Copyright (c) 2019 Michael Forney + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef SWC_PLANE_H +#define SWC_PLANE_H + +#include "plane.h" +#include "view.h" + +#include <wayland-util.h> + +struct plane { + struct view view; + struct screen *screen; + uint32_t id, fb; + int type; + uint32_t possible_crtcs; + struct wl_listener swc_listener; + struct wl_list link; +}; + +struct plane *plane_new(uint32_t id); +void plane_destroy(struct plane *plane); + +#endif diff --git a/libswc/pointer.c b/libswc/pointer.c @@ -25,6 +25,7 @@ #include "compositor.h" #include "event.h" #include "internal.h" +#include "plane.h" #include "screen.h" #include "shm.h" #include "surface.h" @@ -106,8 +107,10 @@ attach(struct view *view, struct wld_buffer *buffer) if (view_set_size_from_buffer(view, buffer)) view_update_screens(view); - wl_list_for_each (screen, &swc.screens, link) - view_attach(&screen->planes.cursor.view, buffer ? pointer->cursor.buffer : NULL); + wl_list_for_each (screen, &swc.screens, link) { + view_attach(&screen->planes.cursor->view, buffer ? pointer->cursor.buffer : NULL); + view_update(&screen->planes.cursor->view); + } return 0; } @@ -120,8 +123,10 @@ move(struct view *view, int32_t x, int32_t y) if (view_set_position(view, x, y)) view_update_screens(view); - wl_list_for_each (screen, &swc.screens, link) - view_move(&screen->planes.cursor.view, view->geometry.x, view->geometry.y); + wl_list_for_each (screen, &swc.screens, link) { + view_move(&screen->planes.cursor->view, view->geometry.x, view->geometry.y); + view_update(&screen->planes.cursor->view); + } return true; } @@ -243,7 +248,7 @@ pointer_initialize(struct pointer *pointer) pointer_set_cursor(pointer, cursor_left_ptr); wl_list_for_each (screen, &swc.screens, link) - view_attach(&screen->planes.cursor.view, pointer->cursor.buffer); + view_attach(&screen->planes.cursor->view, pointer->cursor.buffer); input_focus_initialize(&pointer->focus, &pointer->focus_handler); pixman_region32_init(&pointer->region); diff --git a/libswc/screen.c b/libswc/screen.c @@ -27,6 +27,7 @@ #include "internal.h" #include "mode.h" #include "output.h" +#include "plane.h" #include "pointer.h" #include "util.h" @@ -98,7 +99,7 @@ bind_screen(struct wl_client *client, void *data, uint32_t version, uint32_t id) } struct screen * -screen_new(uint32_t crtc, struct output *output) +screen_new(uint32_t crtc, struct output *output, struct plane *cursor_plane) { struct screen *screen; int32_t x = 0; @@ -117,15 +118,15 @@ screen_new(uint32_t crtc, struct output *output) goto error1; } + screen->crtc = crtc; + if (!primary_plane_initialize(&screen->planes.primary, crtc, output->preferred_mode, &output->connector, 1)) { ERROR("Failed to initialize primary plane\n"); goto error2; } - if (!cursor_plane_initialize(&screen->planes.cursor, crtc, &screen->base.geometry)) { - ERROR("Failed to initialize cursor plane\n"); - goto error3; - } + cursor_plane->screen = screen; + screen->planes.cursor = cursor_plane; screen->handler = &null_handler; wl_signal_init(&screen->destroy_signal); @@ -142,8 +143,6 @@ screen_new(uint32_t crtc, struct output *output) return screen; -error3: - primary_plane_finalize(&screen->planes.primary); error2: wl_global_destroy(screen->global); error1: @@ -165,7 +164,7 @@ screen_destroy(struct screen *screen) wl_list_for_each_safe (output, next, &screen->outputs, link) output_destroy(output); primary_plane_finalize(&screen->planes.primary); - cursor_plane_finalize(&screen->planes.cursor); + plane_destroy(screen->planes.cursor); free(screen); } diff --git a/libswc/screen.h b/libswc/screen.h @@ -25,7 +25,6 @@ #define SWC_SCREEN_H #include "swc.h" -#include "cursor_plane.h" #include "primary_plane.h" #include <wayland-util.h> @@ -50,10 +49,11 @@ struct screen { struct wl_signal destroy_signal; uint8_t id; + uint32_t crtc; struct { struct primary_plane primary; - struct cursor_plane cursor; + struct plane *cursor; } planes; struct wl_global *global; @@ -67,7 +67,7 @@ struct screen { bool screens_initialize(void); void screens_finalize(void); -struct screen *screen_new(uint32_t crtc, struct output *output); +struct screen *screen_new(uint32_t crtc, struct output *output, struct plane *cursor_plane); void screen_destroy(struct screen *screen); static inline uint32_t