1/* swc: libswc/plane.c
2 *
3 * Copyright (c) 2019 Michael Forney
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24#include "plane.h"
25#include "drm.h"
26#include "event.h"
27#include "internal.h"
28#include "screen.h"
29#include "util.h"
30
31#include <errno.h>
32#include <stdlib.h>
33#include <wld/drm.h>
34#include <wld/wld.h>
35#include <xf86drmMode.h>
36
37enum plane_property {
38 PLANE_TYPE,
39 PLANE_IN_FENCE_FD,
40 PLANE_CRTC_ID,
41 PLANE_CRTC_X,
42 PLANE_CRTC_Y,
43 PLANE_CRTC_W,
44 PLANE_CRTC_H,
45 PLANE_SRC_X,
46 PLANE_SRC_Y,
47 PLANE_SRC_W,
48 PLANE_SRC_H,
49};
50
51static bool
52update(struct view *view)
53{
54 struct plane *plane = wl_container_of(view, plane, view);
55 uint32_t x, y, w, h;
56
57 if (!plane->screen) {
58 return false;
59 }
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 &&
65 drmModeSetPlane(swc.drm->fd, plane->id, plane->screen->crtc, plane->fb,
66 0, x, y, w, h, 0, 0, w << 16, h << 16) < 0) {
67 ERROR("Could not set cursor: %s\n", strerror(errno));
68 return false;
69 }
70
71 return true;
72}
73
74static int
75attach(struct view *view, struct wld_buffer *buffer)
76{
77 struct plane *plane = wl_container_of(view, plane, view);
78
79 plane->fb = drm_get_framebuffer(buffer);
80 view_set_size_from_buffer(view, buffer);
81 return 0;
82}
83
84static bool
85move(struct view *view, int32_t x, int32_t y)
86{
87 view_set_position(view, x, y);
88 return true;
89}
90
91static const struct view_impl view_impl = {
92 .update = update,
93 .attach = attach,
94 .move = move,
95};
96
97static enum plane_property
98find_prop(const char *name)
99{
100 static const char property_names[][16] = {
101 [PLANE_TYPE] = "type", [PLANE_IN_FENCE_FD] = "IN_FENCE_FD",
102 [PLANE_CRTC_ID] = "CRTC_ID", [PLANE_CRTC_X] = "CRTC_X",
103 [PLANE_CRTC_Y] = "CRTC_Y", [PLANE_CRTC_W] = "CRTC_W",
104 [PLANE_CRTC_H] = "CRTC_H", [PLANE_SRC_X] = "SRC_X",
105 [PLANE_SRC_Y] = "SRC_Y", [PLANE_SRC_W] = "SRC_W",
106 [PLANE_SRC_H] = "SRC_H",
107 };
108 size_t i;
109
110 for (i = 0; i < ARRAY_LENGTH(property_names); ++i) {
111 if (strcmp(name, property_names[i]) == 0) {
112 return i;
113 }
114 }
115 return -1;
116}
117
118static void
119handle_swc_event(struct wl_listener *listener, void *data)
120{
121 struct event *event = data;
122 struct plane *plane = wl_container_of(listener, plane, swc_listener);
123
124 switch (event->type) {
125 case SWC_EVENT_ACTIVATED:
126 update(&plane->view);
127 break;
128 }
129}
130
131struct plane *
132plane_new(uint32_t id)
133{
134 struct plane *plane;
135 uint32_t i;
136 drmModeObjectProperties *props;
137 drmModePropertyRes *prop;
138 drmModePlane *drm_plane;
139
140 plane = malloc(sizeof(*plane));
141 if (!plane) {
142 goto error0;
143 }
144 drm_plane = drmModeGetPlane(swc.drm->fd, id);
145 if (!drm_plane) {
146 goto error1;
147 }
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 }
161 plane->swc_listener.notify = &handle_swc_event;
162 wl_signal_add(&swc.event_signal, &plane->swc_listener);
163 view_initialize(&plane->view, &view_impl);
164 return plane;
165
166error1:
167 free(plane);
168error0:
169 return NULL;
170}
171
172void
173plane_destroy(struct plane *plane)
174{
175 free(plane);
176}