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