commit bd1a974

Michael Forney  ·  2019-08-29 06:38:54 +0000 UTC
parent 351b43d
Use universal planes for cursor
8 files changed,  +250, -153
+0, -121
  1@@ -1,121 +0,0 @@
  2-/* swc: cursor_plane.c
  3- *
  4- * Copyright (c) 2013, 2014 Michael Forney
  5- *
  6- * Permission is hereby granted, free of charge, to any person obtaining a copy
  7- * of this software and associated documentation files (the "Software"), to deal
  8- * in the Software without restriction, including without limitation the rights
  9- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10- * copies of the Software, and to permit persons to whom the Software is
 11- * furnished to do so, subject to the following conditions:
 12- *
 13- * The above copyright notice and this permission notice shall be included in
 14- * all copies or substantial portions of the Software.
 15- *
 16- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22- * SOFTWARE.
 23- */
 24-
 25-#include "cursor_plane.h"
 26-#include "drm.h"
 27-#include "event.h"
 28-#include "internal.h"
 29-#include "launch.h"
 30-#include "screen.h"
 31-#include "util.h"
 32-
 33-#include <errno.h>
 34-#include <wld/wld.h>
 35-#include <wld/drm.h>
 36-#include <xf86drmMode.h>
 37-
 38-static bool
 39-update(struct view *view)
 40-{
 41-	return true;
 42-}
 43-
 44-static int
 45-attach(struct view *view, struct wld_buffer *buffer)
 46-{
 47-	struct cursor_plane *plane = wl_container_of(view, plane, view);
 48-
 49-	if (buffer) {
 50-		union wld_object object;
 51-
 52-		if (!wld_export(buffer, WLD_DRM_OBJECT_HANDLE, &object)) {
 53-			ERROR("Could not get export buffer to DRM handle\n");
 54-			/* XXX: Not the best error code, but we don't know better until wld
 55-			 * returns an actual error code. */
 56-			return -EINVAL;
 57-		}
 58-
 59-		if (swc.active && drmModeSetCursor(swc.drm->fd, plane->crtc, object.u32, buffer->width, buffer->height) < 0) {
 60-			ERROR("Could not set cursor: %s\n", strerror(errno));
 61-			return -errno;
 62-		}
 63-	} else if (swc.active && drmModeSetCursor(swc.drm->fd, plane->crtc, 0, 0, 0) < 0) {
 64-		ERROR("Could not unset cursor: %s\n", strerror(errno));
 65-		return -errno;
 66-	}
 67-
 68-	view_set_size_from_buffer(view, buffer);
 69-	return 0;
 70-}
 71-
 72-static bool
 73-move(struct view *view, int32_t x, int32_t y)
 74-{
 75-	struct cursor_plane *plane = wl_container_of(view, plane, view);
 76-
 77-	if (swc.active && drmModeMoveCursor(swc.drm->fd, plane->crtc, x - plane->origin->x, y - plane->origin->y) != 0) {
 78-		ERROR("Could not move cursor: %s\n", strerror(errno));
 79-		return false;
 80-	}
 81-
 82-	view_set_position(view, x, y);
 83-
 84-	return true;
 85-}
 86-
 87-static const struct view_impl view_impl = {
 88-	.update = update,
 89-	.attach = attach,
 90-	.move = move,
 91-};
 92-
 93-static void
 94-handle_swc_event(struct wl_listener *listener, void *data)
 95-{
 96-	struct event *event = data;
 97-	struct cursor_plane *plane = wl_container_of(listener, plane, swc_listener);
 98-
 99-	switch (event->type) {
100-	case SWC_EVENT_ACTIVATED:
101-		move(&plane->view, plane->view.geometry.x, plane->view.geometry.y);
102-		attach(&plane->view, plane->view.buffer);
103-		break;
104-	}
105-}
106-
107-bool
108-cursor_plane_initialize(struct cursor_plane *plane, uint32_t crtc, const struct swc_rectangle *origin)
109-{
110-	plane->origin = origin;
111-	plane->crtc = crtc;
112-	plane->swc_listener.notify = &handle_swc_event;
113-	wl_signal_add(&swc.event_signal, &plane->swc_listener);
114-	view_initialize(&plane->view, &view_impl);
115-
116-	return true;
117-}
118-
119-void
120-cursor_plane_finalize(struct cursor_plane *plane)
121-{
122-}
+40, -6
  1@@ -27,6 +27,7 @@
  2 #include "internal.h"
  3 #include "launch.h"
  4 #include "output.h"
  5+#include "plane.h"
  6 #include "screen.h"
  7 #include "util.h"
  8 #include "wayland_buffer.h"
  9@@ -269,6 +270,10 @@ drm_initialize(void)
 10 		ERROR("Could not open DRM device at %s\n", primary);
 11 		goto error0;
 12 	}
 13+	if (drmSetClientCap(swc.drm->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) {
 14+		ERROR("Could not enable DRM universal planes\n");
 15+		goto error1;
 16+	}
 17 	if (drmGetCap(swc.drm->fd, DRM_CAP_CURSOR_WIDTH, &val) < 0)
 18 		val = 64;
 19 	swc.drm->cursor_w = val;
 20@@ -341,17 +346,32 @@ drm_finalize(void)
 21 bool
 22 drm_create_screens(struct wl_list *screens)
 23 {
 24+	drmModePlaneRes *plane_ids;
 25 	drmModeRes *resources;
 26 	drmModeConnector *connector;
 27-	int i;
 28+	struct plane *plane, *cursor_plane;
 29 	struct output *output;
 30-	uint32_t taken_crtcs = 0;
 31+	uint32_t i, taken_crtcs = 0;
 32+	struct wl_list planes;
 33 
 34-	if (!(resources = drmModeGetResources(swc.drm->fd))) {
 35-		ERROR("Could not get DRM resources\n");
 36+	plane_ids = drmModeGetPlaneResources(swc.drm->fd);
 37+	if (!plane_ids) {
 38+		ERROR("Could not get DRM plane resources\n");
 39 		return false;
 40 	}
 41+	wl_list_init(&planes);
 42+	for (i = 0; i < plane_ids->count_planes; ++i) {
 43+		plane = plane_new(plane_ids->planes[i]);
 44+		if (plane)
 45+			wl_list_insert(&planes, &plane->link);
 46+	}
 47+	drmModeFreePlaneResources(plane_ids);
 48 
 49+	resources = drmModeGetResources(swc.drm->fd);
 50+	if (!resources) {
 51+		ERROR("Could not get DRM resources\n");
 52+		return false;
 53+	}
 54 	for (i = 0; i < resources->count_connectors; ++i, drmModeFreeConnector(connector)) {
 55 		connector = drmModeGetConnector(swc.drm->fd, resources->connectors[i]);
 56 
 57@@ -364,6 +384,18 @@ drm_create_screens(struct wl_list *screens)
 58 				continue;
 59 			}
 60 
 61+			cursor_plane = NULL;
 62+			wl_list_for_each (plane, &planes, link) {
 63+				if (plane->type == DRM_PLANE_TYPE_CURSOR && plane->possible_crtcs & 1 << crtc_index) {
 64+					wl_list_remove(&plane->link);
 65+					cursor_plane = plane;
 66+					break;
 67+				}
 68+			}
 69+			if (!cursor_plane) {
 70+				WARNING("Could not find cursor plane for CRTC %d\n", crtc_index);
 71+			}
 72+
 73 			if (!find_available_id(&id)) {
 74 				WARNING("No more available output IDs\n");
 75 				drmModeFreeConnector(connector);
 76@@ -373,7 +405,7 @@ drm_create_screens(struct wl_list *screens)
 77 			if (!(output = output_new(connector)))
 78 				continue;
 79 
 80-			output->screen = screen_new(resources->crtcs[crtc_index], output);
 81+			output->screen = screen_new(resources->crtcs[crtc_index], output, cursor_plane);
 82 			output->screen->id = id;
 83 
 84 			taken_crtcs |= 1 << crtc_index;
 85@@ -382,7 +414,6 @@ drm_create_screens(struct wl_list *screens)
 86 			wl_list_insert(screens, &output->screen->link);
 87 		}
 88 	}
 89-
 90 	drmModeFreeResources(resources);
 91 
 92 	return true;
 93@@ -430,6 +461,9 @@ drm_get_framebuffer(struct wld_buffer *buffer)
 94 	union wld_object object;
 95 	int ret;
 96 
 97+	if (!buffer)
 98+		return 0;
 99+
100 	if (wld_export(buffer, WLD_USER_OBJECT_FRAMEBUFFER, &object))
101 		return object.u32;
102 
+1, -1
 1@@ -24,7 +24,6 @@ SWC_SOURCES =                       \
 2     launch/protocol.c               \
 3     libswc/bindings.c               \
 4     libswc/compositor.c             \
 5-    libswc/cursor_plane.c           \
 6     libswc/data.c                   \
 7     libswc/data_device.c            \
 8     libswc/data_device_manager.c    \
 9@@ -37,6 +36,7 @@ SWC_SOURCES =                       \
10     libswc/output.c                 \
11     libswc/panel.c                  \
12     libswc/panel_manager.c          \
13+    libswc/plane.c                  \
14     libswc/pointer.c                \
15     libswc/primary_plane.c          \
16     libswc/region.c                 \
+174, -0
  1@@ -0,0 +1,174 @@
  2+/* swc: libswc/plane.c
  3+ *
  4+ * Copyright (c) 2019 Michael Forney
  5+ *
  6+ * Permission is hereby granted, free of charge, to any person obtaining a copy
  7+ * of this software and associated documentation files (the "Software"), to deal
  8+ * in the Software without restriction, including without limitation the rights
  9+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10+ * copies of the Software, and to permit persons to whom the Software is
 11+ * furnished to do so, subject to the following conditions:
 12+ *
 13+ * The above copyright notice and this permission notice shall be included in
 14+ * all copies or substantial portions of the Software.
 15+ *
 16+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 22+ * SOFTWARE.
 23+ */
 24+
 25+#include "plane.h"
 26+#include "event.h"
 27+#include "drm.h"
 28+#include "internal.h"
 29+#include "screen.h"
 30+#include "util.h"
 31+
 32+#include <errno.h>
 33+#include <stdlib.h>
 34+#include <wld/wld.h>
 35+#include <wld/drm.h>
 36+#include <xf86drmMode.h>
 37+
 38+enum plane_property {
 39+	PLANE_TYPE,
 40+	PLANE_IN_FENCE_FD,
 41+	PLANE_CRTC_ID,
 42+	PLANE_CRTC_X,
 43+	PLANE_CRTC_Y,
 44+	PLANE_CRTC_W,
 45+	PLANE_CRTC_H,
 46+	PLANE_SRC_X,
 47+	PLANE_SRC_Y,
 48+	PLANE_SRC_W,
 49+	PLANE_SRC_H,
 50+};
 51+
 52+static bool
 53+update(struct view *view)
 54+{
 55+	struct plane *plane = wl_container_of(view, plane, view);
 56+	uint32_t x, y, w, h;
 57+
 58+	if (!plane->screen)
 59+		return false;
 60+	x = view->geometry.x - plane->screen->base.geometry.x;
 61+	y = view->geometry.y - plane->screen->base.geometry.y;
 62+	w = view->geometry.width;
 63+	h = view->geometry.height;
 64+	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) {
 65+		ERROR("Could not set cursor: %s\n", strerror(errno));
 66+		return false;
 67+	}
 68+
 69+	return true;
 70+}
 71+
 72+static int
 73+attach(struct view *view, struct wld_buffer *buffer)
 74+{
 75+	struct plane *plane = wl_container_of(view, plane, view);
 76+
 77+	plane->fb = drm_get_framebuffer(buffer);
 78+	view_set_size_from_buffer(view, buffer);
 79+	return 0;
 80+}
 81+
 82+static bool
 83+move(struct view *view, int32_t x, int32_t y)
 84+{
 85+	view_set_position(view, x, y);
 86+	return true;
 87+}
 88+
 89+static const struct view_impl view_impl = {
 90+	.update = update,
 91+	.attach = attach,
 92+	.move = move,
 93+};
 94+
 95+static enum plane_property
 96+find_prop(const char *name)
 97+{
 98+	static const char property_names[][16] = {
 99+		[PLANE_TYPE]        = "type",
100+		[PLANE_IN_FENCE_FD] = "IN_FENCE_FD",
101+		[PLANE_CRTC_ID]     = "CRTC_ID",
102+		[PLANE_CRTC_X]      = "CRTC_X",
103+		[PLANE_CRTC_Y]      = "CRTC_Y",
104+		[PLANE_CRTC_W]      = "CRTC_W",
105+		[PLANE_CRTC_H]      = "CRTC_H",
106+		[PLANE_SRC_X]       = "SRC_X",
107+		[PLANE_SRC_Y]       = "SRC_Y",
108+		[PLANE_SRC_W]       = "SRC_W",
109+		[PLANE_SRC_H]       = "SRC_H",
110+	};
111+	size_t i;
112+
113+	for (i = 0; i < ARRAY_LENGTH(property_names); ++i) {
114+		if (strcmp(name, property_names[i]) == 0)
115+			return i;
116+	}
117+	return -1;
118+}
119+
120+static void
121+handle_swc_event(struct wl_listener *listener, void *data)
122+{
123+	struct event *event = data;
124+	struct plane *plane = wl_container_of(listener, plane, swc_listener);
125+
126+	switch (event->type) {
127+	case SWC_EVENT_ACTIVATED:
128+		update(&plane->view);
129+		break;
130+	}
131+}
132+
133+struct plane *
134+plane_new(uint32_t id)
135+{
136+	struct plane *plane;
137+	uint32_t i;
138+	drmModeObjectProperties *props;
139+	drmModePropertyRes *prop;
140+	drmModePlane *drm_plane;
141+
142+	plane = malloc(sizeof(*plane));
143+	if (!plane)
144+		goto error0;
145+	drm_plane = drmModeGetPlane(swc.drm->fd, id);
146+	if (!drm_plane)
147+		goto error1;
148+	plane->id = id;
149+	plane->fb = 0;
150+	plane->screen = NULL;
151+	plane->possible_crtcs = drm_plane->possible_crtcs;
152+	drmModeFreePlane(drm_plane);
153+	plane->type = -1;
154+	props = drmModeObjectGetProperties(swc.drm->fd, id, DRM_MODE_OBJECT_PLANE);
155+	for (i = 0; i < props->count_props; ++i, drmModeFreeProperty(prop)) {
156+		prop = drmModeGetProperty(swc.drm->fd, props->props[i]);
157+		if (prop && find_prop(prop->name) == PLANE_TYPE)
158+			plane->type = props->prop_values[i];
159+	}
160+	plane->swc_listener.notify = &handle_swc_event;
161+	wl_signal_add(&swc.event_signal, &plane->swc_listener);
162+	view_initialize(&plane->view, &view_impl);
163+	return plane;
164+
165+error1:
166+	free(plane);
167+error0:
168+	return NULL;
169+}
170+
171+void
172+plane_destroy(struct plane *plane)
173+{
174+	free(plane);
175+}
R libswc/cursor_plane.h => libswc/plane.h
+15, -9
 1@@ -1,6 +1,6 @@
 2-/* swc: libswc/cursor_plane.h
 3+/* swc: libswc/plane.h
 4  *
 5- * Copyright (c) 2013, 2014 Michael Forney
 6+ * Copyright (c) 2019 Michael Forney
 7  *
 8  * Permission is hereby granted, free of charge, to any person obtaining a copy
 9  * of this software and associated documentation files (the "Software"), to deal
10@@ -21,19 +21,25 @@
11  * SOFTWARE.
12  */
13 
14-#ifndef SWC_CURSOR_PLANE_H
15-#define SWC_CURSOR_PLANE_H
16+#ifndef SWC_PLANE_H
17+#define SWC_PLANE_H
18 
19+#include "plane.h"
20 #include "view.h"
21 
22-struct cursor_plane {
23+#include <wayland-util.h>
24+
25+struct plane {
26 	struct view view;
27-	const struct swc_rectangle *origin;
28-	uint32_t crtc;
29+	struct screen *screen;
30+	uint32_t id, fb;
31+	int type;
32+	uint32_t possible_crtcs;
33 	struct wl_listener swc_listener;
34+	struct wl_list link;
35 };
36 
37-bool cursor_plane_initialize(struct cursor_plane *plane, uint32_t crtc, const struct swc_rectangle *origin);
38-void cursor_plane_finalize(struct cursor_plane *plane);
39+struct plane *plane_new(uint32_t id);
40+void plane_destroy(struct plane *plane);
41 
42 #endif
+10, -5
 1@@ -25,6 +25,7 @@
 2 #include "compositor.h"
 3 #include "event.h"
 4 #include "internal.h"
 5+#include "plane.h"
 6 #include "screen.h"
 7 #include "shm.h"
 8 #include "surface.h"
 9@@ -106,8 +107,10 @@ attach(struct view *view, struct wld_buffer *buffer)
10 	if (view_set_size_from_buffer(view, buffer))
11 		view_update_screens(view);
12 
13-	wl_list_for_each (screen, &swc.screens, link)
14-		view_attach(&screen->planes.cursor.view, buffer ? pointer->cursor.buffer : NULL);
15+	wl_list_for_each (screen, &swc.screens, link) {
16+		view_attach(&screen->planes.cursor->view, buffer ? pointer->cursor.buffer : NULL);
17+		view_update(&screen->planes.cursor->view);
18+	}
19 
20 	return 0;
21 }
22@@ -120,8 +123,10 @@ move(struct view *view, int32_t x, int32_t y)
23 	if (view_set_position(view, x, y))
24 		view_update_screens(view);
25 
26-	wl_list_for_each (screen, &swc.screens, link)
27-		view_move(&screen->planes.cursor.view, view->geometry.x, view->geometry.y);
28+	wl_list_for_each (screen, &swc.screens, link) {
29+		view_move(&screen->planes.cursor->view, view->geometry.x, view->geometry.y);
30+		view_update(&screen->planes.cursor->view);
31+	}
32 
33 	return true;
34 }
35@@ -243,7 +248,7 @@ pointer_initialize(struct pointer *pointer)
36 	pointer_set_cursor(pointer, cursor_left_ptr);
37 
38 	wl_list_for_each (screen, &swc.screens, link)
39-		view_attach(&screen->planes.cursor.view, pointer->cursor.buffer);
40+		view_attach(&screen->planes.cursor->view, pointer->cursor.buffer);
41 
42 	input_focus_initialize(&pointer->focus, &pointer->focus_handler);
43 	pixman_region32_init(&pointer->region);
+7, -8
 1@@ -27,6 +27,7 @@
 2 #include "internal.h"
 3 #include "mode.h"
 4 #include "output.h"
 5+#include "plane.h"
 6 #include "pointer.h"
 7 #include "util.h"
 8 
 9@@ -98,7 +99,7 @@ bind_screen(struct wl_client *client, void *data, uint32_t version, uint32_t id)
10 }
11 
12 struct screen *
13-screen_new(uint32_t crtc, struct output *output)
14+screen_new(uint32_t crtc, struct output *output, struct plane *cursor_plane)
15 {
16 	struct screen *screen;
17 	int32_t x = 0;
18@@ -117,15 +118,15 @@ screen_new(uint32_t crtc, struct output *output)
19 		goto error1;
20 	}
21 
22+	screen->crtc = crtc;
23+
24 	if (!primary_plane_initialize(&screen->planes.primary, crtc, output->preferred_mode, &output->connector, 1)) {
25 		ERROR("Failed to initialize primary plane\n");
26 		goto error2;
27 	}
28 
29-	if (!cursor_plane_initialize(&screen->planes.cursor, crtc, &screen->base.geometry)) {
30-		ERROR("Failed to initialize cursor plane\n");
31-		goto error3;
32-	}
33+	cursor_plane->screen = screen;
34+	screen->planes.cursor = cursor_plane;
35 
36 	screen->handler = &null_handler;
37 	wl_signal_init(&screen->destroy_signal);
38@@ -142,8 +143,6 @@ screen_new(uint32_t crtc, struct output *output)
39 
40 	return screen;
41 
42-error3:
43-	primary_plane_finalize(&screen->planes.primary);
44 error2:
45 	wl_global_destroy(screen->global);
46 error1:
47@@ -165,7 +164,7 @@ screen_destroy(struct screen *screen)
48 	wl_list_for_each_safe (output, next, &screen->outputs, link)
49 		output_destroy(output);
50 	primary_plane_finalize(&screen->planes.primary);
51-	cursor_plane_finalize(&screen->planes.cursor);
52+	plane_destroy(screen->planes.cursor);
53 	free(screen);
54 }
55 
+3, -3
 1@@ -25,7 +25,6 @@
 2 #define SWC_SCREEN_H
 3 
 4 #include "swc.h"
 5-#include "cursor_plane.h"
 6 #include "primary_plane.h"
 7 
 8 #include <wayland-util.h>
 9@@ -50,10 +49,11 @@ struct screen {
10 
11 	struct wl_signal destroy_signal;
12 	uint8_t id;
13+	uint32_t crtc;
14 
15 	struct {
16 		struct primary_plane primary;
17-		struct cursor_plane cursor;
18+		struct plane *cursor;
19 	} planes;
20 
21 	struct wl_global *global;
22@@ -67,7 +67,7 @@ struct screen {
23 bool screens_initialize(void);
24 void screens_finalize(void);
25 
26-struct screen *screen_new(uint32_t crtc, struct output *output);
27+struct screen *screen_new(uint32_t crtc, struct output *output, struct plane *cursor_plane);
28 void screen_destroy(struct screen *screen);
29 
30 static inline uint32_t