main neuswc / libswc / plane.c
  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}