1 /*
2 * Copyright © 2008-2011 Kristian Høgsberg
3 * Copyright © 2011 Intel Corporation
4 * Copyright © 2017, 2018 Collabora, Ltd.
5 * Copyright © 2017, 2018 General Electric Company
6 * Copyright (c) 2018 DisplayLink (UK) Ltd.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial
18 * portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30 #include "config.h"
31
32 #include <errno.h>
33 #include <stdint.h>
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <string.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <linux/input.h>
40 #include <linux/vt.h>
41 #include <assert.h>
42 #include <sys/mman.h>
43 #include <dlfcn.h>
44 #include <time.h>
45
46 #include <xf86drm.h>
47 #include <xf86drmMode.h>
48 #include <drm_fourcc.h>
49
50 #include <libudev.h>
51
52 #include <libweston/libweston.h>
53 #include <libweston/backend-drm.h>
54 #include <libweston/weston-log.h>
55 #include "drm-internal.h"
56 #include "shared/helpers.h"
57 #include "shared/timespec-util.h"
58 #include "renderer-gl/gl-renderer.h"
59 #include "weston-egl-ext.h"
60 #include "pixman-renderer.h"
61 #include "pixel-formats.h"
62 #include "libbacklight.h"
63 #include "libinput-seat.h"
64 #include "launcher-util.h"
65 #include "vaapi-recorder.h"
66 #include "presentation-time-server-protocol.h"
67 #include "linux-dmabuf.h"
68 #include "linux-dmabuf-unstable-v1-server-protocol.h"
69 #include "linux-explicit-synchronization.h"
70
71 static struct gl_renderer_interface *gl_renderer;
72
73 static const char default_seat[] = "seat0";
74
75 static void
wl_array_remove_uint32(struct wl_array * array,uint32_t elm)76 wl_array_remove_uint32(struct wl_array *array, uint32_t elm)
77 {
78 uint32_t *pos, *end;
79
80 end = (uint32_t *) ((char *) array->data + array->size);
81
82 wl_array_for_each(pos, array) {
83 if (*pos != elm)
84 continue;
85
86 array->size -= sizeof(*pos);
87 if (pos + 1 == end)
88 break;
89
90 memmove(pos, pos + 1, (char *) end - (char *) (pos + 1));
91 break;
92 }
93 }
94
95 static int
pageflip_timeout(void * data)96 pageflip_timeout(void *data) {
97 /*
98 * Our timer just went off, that means we're not receiving drm
99 * page flip events anymore for that output. Let's gracefully exit
100 * weston with a return value so devs can debug what's going on.
101 */
102 struct drm_output *output = data;
103 struct weston_compositor *compositor = output->base.compositor;
104
105 weston_log("Pageflip timeout reached on output %s, your "
106 "driver is probably buggy! Exiting.\n",
107 output->base.name);
108 weston_compositor_exit_with_code(compositor, EXIT_FAILURE);
109
110 return 0;
111 }
112
113 /* Creates the pageflip timer. Note that it isn't armed by default */
114 static int
drm_output_pageflip_timer_create(struct drm_output * output)115 drm_output_pageflip_timer_create(struct drm_output *output)
116 {
117 struct wl_event_loop *loop = NULL;
118 struct weston_compositor *ec = output->base.compositor;
119
120 loop = wl_display_get_event_loop(ec->wl_display);
121 assert(loop);
122 output->pageflip_timer = wl_event_loop_add_timer(loop,
123 pageflip_timeout,
124 output);
125
126 if (output->pageflip_timer == NULL) {
127 weston_log("creating drm pageflip timer failed: %s\n",
128 strerror(errno));
129 return -1;
130 }
131
132 return 0;
133 }
134
135 static void
136 drm_output_destroy(struct weston_output *output_base);
137
138 static void
139 drm_virtual_output_destroy(struct weston_output *output_base);
140
141 /**
142 * Returns true if the plane can be used on the given output for its current
143 * repaint cycle.
144 */
145 bool
drm_plane_is_available(struct drm_plane * plane,struct drm_output * output)146 drm_plane_is_available(struct drm_plane *plane, struct drm_output *output)
147 {
148 assert(plane->state_cur);
149
150 if (output->virtual)
151 return false;
152
153 /* The plane still has a request not yet completed by the kernel. */
154 if (!plane->state_cur->complete)
155 return false;
156
157 /* The plane is still active on another output. */
158 if (plane->state_cur->output && plane->state_cur->output != output)
159 return false;
160
161 /* Check whether the plane can be used with this CRTC; possible_crtcs
162 * is a bitmask of CRTC indices (pipe), rather than CRTC object ID. */
163 return !!(plane->possible_crtcs & (1 << output->pipe));
164 }
165
166 struct drm_output *
drm_output_find_by_crtc(struct drm_backend * b,uint32_t crtc_id)167 drm_output_find_by_crtc(struct drm_backend *b, uint32_t crtc_id)
168 {
169 struct drm_output *output;
170
171 wl_list_for_each(output, &b->compositor->output_list, base.link) {
172 if (output->crtc_id == crtc_id)
173 return output;
174 }
175
176 return NULL;
177 }
178
179 struct drm_head *
drm_head_find_by_connector(struct drm_backend * backend,uint32_t connector_id)180 drm_head_find_by_connector(struct drm_backend *backend, uint32_t connector_id)
181 {
182 struct weston_head *base;
183 struct drm_head *head;
184
185 wl_list_for_each(base,
186 &backend->compositor->head_list, compositor_link) {
187 head = to_drm_head(base);
188 if (head->connector_id == connector_id)
189 return head;
190 }
191
192 return NULL;
193 }
194
195 /**
196 * Get output state to disable output
197 *
198 * Returns a pointer to an output_state object which can be used to disable
199 * an output (e.g. DPMS off).
200 *
201 * @param pending_state The pending state object owning this update
202 * @param output The output to disable
203 * @returns A drm_output_state to disable the output
204 */
205 static struct drm_output_state *
drm_output_get_disable_state(struct drm_pending_state * pending_state,struct drm_output * output)206 drm_output_get_disable_state(struct drm_pending_state *pending_state,
207 struct drm_output *output)
208 {
209 struct drm_output_state *output_state;
210
211 output_state = drm_output_state_duplicate(output->state_cur,
212 pending_state,
213 DRM_OUTPUT_STATE_CLEAR_PLANES);
214 output_state->dpms = WESTON_DPMS_OFF;
215
216 return output_state;
217 }
218
219
220 /**
221 * Mark a drm_output_state (the output's last state) as complete. This handles
222 * any post-completion actions such as updating the repaint timer, disabling the
223 * output, and finally freeing the state.
224 */
225 void
drm_output_update_complete(struct drm_output * output,uint32_t flags,unsigned int sec,unsigned int usec)226 drm_output_update_complete(struct drm_output *output, uint32_t flags,
227 unsigned int sec, unsigned int usec)
228 {
229 struct drm_backend *b = to_drm_backend(output->base.compositor);
230 struct drm_plane_state *ps;
231 struct timespec ts;
232
233 /* Stop the pageflip timer instead of rearming it here */
234 if (output->pageflip_timer)
235 wl_event_source_timer_update(output->pageflip_timer, 0);
236
237 wl_list_for_each(ps, &output->state_cur->plane_list, link)
238 ps->complete = true;
239
240 drm_output_state_free(output->state_last);
241 output->state_last = NULL;
242
243 if (output->destroy_pending) {
244 output->destroy_pending = 0;
245 output->disable_pending = 0;
246 output->dpms_off_pending = 0;
247 drm_output_destroy(&output->base);
248 return;
249 } else if (output->disable_pending) {
250 output->disable_pending = 0;
251 output->dpms_off_pending = 0;
252 weston_output_disable(&output->base);
253 return;
254 } else if (output->dpms_off_pending) {
255 struct drm_pending_state *pending = drm_pending_state_alloc(b);
256 output->dpms_off_pending = 0;
257 drm_output_get_disable_state(pending, output);
258 drm_pending_state_apply_sync(pending);
259 } else if (output->state_cur->dpms == WESTON_DPMS_OFF &&
260 output->base.repaint_status != REPAINT_AWAITING_COMPLETION) {
261 /* DPMS can happen to us either in the middle of a repaint
262 * cycle (when we have painted fresh content, only to throw it
263 * away for DPMS off), or at any other random point. If the
264 * latter is true, then we cannot go through finish_frame,
265 * because the repaint machinery does not expect this. */
266 return;
267 }
268
269 ts.tv_sec = sec;
270 ts.tv_nsec = usec * 1000;
271 weston_output_finish_frame(&output->base, &ts, flags);
272
273 /* We can't call this from frame_notify, because the output's
274 * repaint needed flag is cleared just after that */
275 if (output->recorder)
276 weston_output_schedule_repaint(&output->base);
277 }
278
279
280 static struct drm_fb *
drm_output_render_gl(struct drm_output_state * state,pixman_region32_t * damage)281 drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
282 {
283 struct drm_output *output = state->output;
284 struct drm_backend *b = to_drm_backend(output->base.compositor);
285 struct gbm_bo *bo;
286 struct drm_fb *ret;
287
288 output->base.compositor->renderer->repaint_output(&output->base,
289 damage);
290
291 bo = gbm_surface_lock_front_buffer(output->gbm_surface);
292 if (!bo) {
293 weston_log("failed to lock front buffer: %s\n",
294 strerror(errno));
295 return NULL;
296 }
297
298 /* The renderer always produces an opaque image. */
299 ret = drm_fb_get_from_bo(bo, b, true, BUFFER_GBM_SURFACE);
300 if (!ret) {
301 weston_log("failed to get drm_fb for bo\n");
302 gbm_surface_release_buffer(output->gbm_surface, bo);
303 return NULL;
304 }
305 ret->gbm_surface = output->gbm_surface;
306
307 return ret;
308 }
309
310 static struct drm_fb *
drm_output_render_pixman(struct drm_output_state * state,pixman_region32_t * damage)311 drm_output_render_pixman(struct drm_output_state *state,
312 pixman_region32_t *damage)
313 {
314 struct drm_output *output = state->output;
315 struct weston_compositor *ec = output->base.compositor;
316
317 output->current_image ^= 1;
318
319 pixman_renderer_output_set_buffer(&output->base,
320 output->image[output->current_image]);
321 pixman_renderer_output_set_hw_extra_damage(&output->base,
322 &output->previous_damage);
323
324 ec->renderer->repaint_output(&output->base, damage);
325
326 pixman_region32_copy(&output->previous_damage, damage);
327
328 return drm_fb_ref(output->dumb[output->current_image]);
329 }
330
331 static void
drm_output_render(struct drm_output_state * state,pixman_region32_t * damage)332 drm_output_render(struct drm_output_state *state, pixman_region32_t *damage)
333 {
334 struct drm_output *output = state->output;
335 struct weston_compositor *c = output->base.compositor;
336 struct drm_plane_state *scanout_state;
337 struct drm_plane *scanout_plane = output->scanout_plane;
338 struct drm_backend *b = to_drm_backend(c);
339 struct drm_fb *fb;
340
341 /* If we already have a client buffer promoted to scanout, then we don't
342 * want to render. */
343 scanout_state = drm_output_state_get_plane(state,
344 output->scanout_plane);
345 if (scanout_state->fb)
346 return;
347
348 if (!pixman_region32_not_empty(damage) &&
349 scanout_plane->state_cur->fb &&
350 (scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE ||
351 scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) &&
352 scanout_plane->state_cur->fb->width ==
353 output->base.current_mode->width &&
354 scanout_plane->state_cur->fb->height ==
355 output->base.current_mode->height) {
356 fb = drm_fb_ref(scanout_plane->state_cur->fb);
357 } else if (b->use_pixman) {
358 fb = drm_output_render_pixman(state, damage);
359 } else {
360 fb = drm_output_render_gl(state, damage);
361 }
362
363 if (!fb) {
364 drm_plane_state_put_back(scanout_state);
365 return;
366 }
367
368 scanout_state->fb = fb;
369 scanout_state->output = output;
370
371 scanout_state->src_x = 0;
372 scanout_state->src_y = 0;
373 scanout_state->src_w = output->base.current_mode->width << 16;
374 scanout_state->src_h = output->base.current_mode->height << 16;
375
376 scanout_state->dest_x = 0;
377 scanout_state->dest_y = 0;
378 scanout_state->dest_w = scanout_state->src_w >> 16;
379 scanout_state->dest_h = scanout_state->src_h >> 16;
380
381 pixman_region32_copy(&scanout_state->damage, damage);
382 if (output->base.zoom.active) {
383 weston_matrix_transform_region(&scanout_state->damage,
384 &output->base.matrix,
385 &scanout_state->damage);
386 } else {
387 pixman_region32_translate(&scanout_state->damage,
388 -output->base.x, -output->base.y);
389 weston_transformed_region(output->base.width,
390 output->base.height,
391 output->base.transform,
392 output->base.current_scale,
393 &scanout_state->damage,
394 &scanout_state->damage);
395 }
396
397 pixman_region32_subtract(&c->primary_plane.damage,
398 &c->primary_plane.damage, damage);
399 }
400
401 static int
drm_output_repaint(struct weston_output * output_base,pixman_region32_t * damage,void * repaint_data)402 drm_output_repaint(struct weston_output *output_base,
403 pixman_region32_t *damage,
404 void *repaint_data)
405 {
406 struct drm_pending_state *pending_state = repaint_data;
407 struct drm_output *output = to_drm_output(output_base);
408 struct drm_output_state *state = NULL;
409 struct drm_plane_state *scanout_state;
410
411 assert(!output->virtual);
412
413 if (output->disable_pending || output->destroy_pending)
414 goto err;
415
416 assert(!output->state_last);
417
418 /* If planes have been disabled in the core, we might not have
419 * hit assign_planes at all, so might not have valid output state
420 * here. */
421 state = drm_pending_state_get_output(pending_state, output);
422 if (!state)
423 state = drm_output_state_duplicate(output->state_cur,
424 pending_state,
425 DRM_OUTPUT_STATE_CLEAR_PLANES);
426 state->dpms = WESTON_DPMS_ON;
427
428 drm_output_render(state, damage);
429 scanout_state = drm_output_state_get_plane(state,
430 output->scanout_plane);
431 if (!scanout_state || !scanout_state->fb)
432 goto err;
433
434 return 0;
435
436 err:
437 drm_output_state_free(state);
438 return -1;
439 }
440
441 /* Determine the type of vblank synchronization to use for the output.
442 *
443 * The pipe parameter indicates which CRTC is in use. Knowing this, we
444 * can determine which vblank sequence type to use for it. Traditional
445 * cards had only two CRTCs, with CRTC 0 using no special flags, and
446 * CRTC 1 using DRM_VBLANK_SECONDARY. The first bit of the pipe
447 * parameter indicates this.
448 *
449 * Bits 1-5 of the pipe parameter are 5 bit wide pipe number between
450 * 0-31. If this is non-zero it indicates we're dealing with a
451 * multi-gpu situation and we need to calculate the vblank sync
452 * using DRM_BLANK_HIGH_CRTC_MASK.
453 */
454 static unsigned int
drm_waitvblank_pipe(struct drm_output * output)455 drm_waitvblank_pipe(struct drm_output *output)
456 {
457 if (output->pipe > 1)
458 return (output->pipe << DRM_VBLANK_HIGH_CRTC_SHIFT) &
459 DRM_VBLANK_HIGH_CRTC_MASK;
460 else if (output->pipe > 0)
461 return DRM_VBLANK_SECONDARY;
462 else
463 return 0;
464 }
465
466 static int
drm_output_start_repaint_loop(struct weston_output * output_base)467 drm_output_start_repaint_loop(struct weston_output *output_base)
468 {
469 struct drm_output *output = to_drm_output(output_base);
470 struct drm_pending_state *pending_state;
471 struct drm_plane *scanout_plane = output->scanout_plane;
472 struct drm_backend *backend =
473 to_drm_backend(output_base->compositor);
474 struct timespec ts, tnow;
475 struct timespec vbl2now;
476 int64_t refresh_nsec;
477 int ret;
478 drmVBlank vbl = {
479 .request.type = DRM_VBLANK_RELATIVE,
480 .request.sequence = 0,
481 .request.signal = 0,
482 };
483
484 if (output->disable_pending || output->destroy_pending)
485 return 0;
486
487 if (!output->scanout_plane->state_cur->fb) {
488 /* We can't page flip if there's no mode set */
489 goto finish_frame;
490 }
491
492 /* Need to smash all state in from scratch; current timings might not
493 * be what we want, page flip might not work, etc.
494 */
495 if (backend->state_invalid)
496 goto finish_frame;
497
498 assert(scanout_plane->state_cur->output == output);
499
500 /* Try to get current msc and timestamp via instant query */
501 vbl.request.type |= drm_waitvblank_pipe(output);
502 ret = drmWaitVBlank(backend->drm.fd, &vbl);
503
504 /* Error ret or zero timestamp means failure to get valid timestamp */
505 if ((ret == 0) && (vbl.reply.tval_sec > 0 || vbl.reply.tval_usec > 0)) {
506 ts.tv_sec = vbl.reply.tval_sec;
507 ts.tv_nsec = vbl.reply.tval_usec * 1000;
508
509 /* Valid timestamp for most recent vblank - not stale?
510 * Stale ts could happen on Linux 3.17+, so make sure it
511 * is not older than 1 refresh duration since now.
512 */
513 weston_compositor_read_presentation_clock(backend->compositor,
514 &tnow);
515 timespec_sub(&vbl2now, &tnow, &ts);
516 refresh_nsec =
517 millihz_to_nsec(output->base.current_mode->refresh);
518 if (timespec_to_nsec(&vbl2now) < refresh_nsec) {
519 drm_output_update_msc(output, vbl.reply.sequence);
520 weston_output_finish_frame(output_base, &ts,
521 WP_PRESENTATION_FEEDBACK_INVALID);
522 return 0;
523 }
524 }
525
526 /* Immediate query didn't provide valid timestamp.
527 * Use pageflip fallback.
528 */
529
530 assert(!output->page_flip_pending);
531 assert(!output->state_last);
532
533 pending_state = drm_pending_state_alloc(backend);
534 drm_output_state_duplicate(output->state_cur, pending_state,
535 DRM_OUTPUT_STATE_PRESERVE_PLANES);
536
537 ret = drm_pending_state_apply(pending_state);
538 if (ret != 0) {
539 weston_log("applying repaint-start state failed: %s\n",
540 strerror(errno));
541 if (ret == -EACCES)
542 return -1;
543 goto finish_frame;
544 }
545
546 return 0;
547
548 finish_frame:
549 /* if we cannot page-flip, immediately finish frame */
550 weston_output_finish_frame(output_base, NULL,
551 WP_PRESENTATION_FEEDBACK_INVALID);
552 return 0;
553 }
554
555 /**
556 * Begin a new repaint cycle
557 *
558 * Called by the core compositor at the beginning of a repaint cycle. Creates
559 * a new pending_state structure to own any output state created by individual
560 * output repaint functions until the repaint is flushed or cancelled.
561 */
562 static void *
drm_repaint_begin(struct weston_compositor * compositor)563 drm_repaint_begin(struct weston_compositor *compositor)
564 {
565 struct drm_backend *b = to_drm_backend(compositor);
566 struct drm_pending_state *ret;
567
568 ret = drm_pending_state_alloc(b);
569 b->repaint_data = ret;
570
571 if (weston_log_scope_is_enabled(b->debug)) {
572 char *dbg = weston_compositor_print_scene_graph(compositor);
573 drm_debug(b, "[repaint] Beginning repaint; pending_state %p\n",
574 ret);
575 drm_debug(b, "%s", dbg);
576 free(dbg);
577 }
578
579 return ret;
580 }
581
582 /**
583 * Flush a repaint set
584 *
585 * Called by the core compositor when a repaint cycle has been completed
586 * and should be flushed. Frees the pending state, transitioning ownership
587 * of the output state from the pending state, to the update itself. When
588 * the update completes (see drm_output_update_complete), the output
589 * state will be freed.
590 */
591 static int
drm_repaint_flush(struct weston_compositor * compositor,void * repaint_data)592 drm_repaint_flush(struct weston_compositor *compositor, void *repaint_data)
593 {
594 struct drm_backend *b = to_drm_backend(compositor);
595 struct drm_pending_state *pending_state = repaint_data;
596 int ret;
597
598 ret = drm_pending_state_apply(pending_state);
599 if (ret != 0)
600 weston_log("repaint-flush failed: %s\n", strerror(errno));
601
602 drm_debug(b, "[repaint] flushed pending_state %p\n", pending_state);
603 b->repaint_data = NULL;
604
605 return (ret == -EACCES) ? -1 : 0;
606 }
607
608 /**
609 * Cancel a repaint set
610 *
611 * Called by the core compositor when a repaint has finished, so the data
612 * held across the repaint cycle should be discarded.
613 */
614 static void
drm_repaint_cancel(struct weston_compositor * compositor,void * repaint_data)615 drm_repaint_cancel(struct weston_compositor *compositor, void *repaint_data)
616 {
617 struct drm_backend *b = to_drm_backend(compositor);
618 struct drm_pending_state *pending_state = repaint_data;
619
620 drm_pending_state_free(pending_state);
621 drm_debug(b, "[repaint] cancel pending_state %p\n", pending_state);
622 b->repaint_data = NULL;
623 }
624
625 static int
626 drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
627 static void
628 drm_output_fini_egl(struct drm_output *output);
629 static int
630 drm_output_init_pixman(struct drm_output *output, struct drm_backend *b);
631 static void
632 drm_output_fini_pixman(struct drm_output *output);
633
634 static int
drm_output_switch_mode(struct weston_output * output_base,struct weston_mode * mode)635 drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
636 {
637 struct drm_output *output = to_drm_output(output_base);
638 struct drm_backend *b = to_drm_backend(output_base->compositor);
639 struct drm_mode *drm_mode = drm_output_choose_mode(output, mode);
640
641 if (!drm_mode) {
642 weston_log("%s: invalid resolution %dx%d\n",
643 output_base->name, mode->width, mode->height);
644 return -1;
645 }
646
647 if (&drm_mode->base == output->base.current_mode)
648 return 0;
649
650 output->base.current_mode->flags = 0;
651
652 output->base.current_mode = &drm_mode->base;
653 output->base.current_mode->flags =
654 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
655
656 /* XXX: This drops our current buffer too early, before we've started
657 * displaying it. Ideally this should be much more atomic and
658 * integrated with a full repaint cycle, rather than doing a
659 * sledgehammer modeswitch first, and only later showing new
660 * content.
661 */
662 b->state_invalid = true;
663
664 if (b->use_pixman) {
665 drm_output_fini_pixman(output);
666 if (drm_output_init_pixman(output, b) < 0) {
667 weston_log("failed to init output pixman state with "
668 "new mode\n");
669 return -1;
670 }
671 } else {
672 drm_output_fini_egl(output);
673 if (drm_output_init_egl(output, b) < 0) {
674 weston_log("failed to init output egl state with "
675 "new mode");
676 return -1;
677 }
678 }
679
680 return 0;
681 }
682
683 static struct gbm_device *
create_gbm_device(int fd)684 create_gbm_device(int fd)
685 {
686 struct gbm_device *gbm;
687
688 gl_renderer = weston_load_module("gl-renderer.so",
689 "gl_renderer_interface");
690 if (!gl_renderer)
691 return NULL;
692
693 /* GBM will load a dri driver, but even though they need symbols from
694 * libglapi, in some version of Mesa they are not linked to it. Since
695 * only the gl-renderer module links to it, the call above won't make
696 * these symbols globally available, and loading the DRI driver fails.
697 * Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
698 dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
699
700 gbm = gbm_create_device(fd);
701
702 return gbm;
703 }
704
705 /* When initializing EGL, if the preferred buffer format isn't available
706 * we may be able to substitute an ARGB format for an XRGB one.
707 *
708 * This returns 0 if substitution isn't possible, but 0 might be a
709 * legitimate format for other EGL platforms, so the caller is
710 * responsible for checking for 0 before calling gl_renderer->create().
711 *
712 * This works around https://bugs.freedesktop.org/show_bug.cgi?id=89689
713 * but it's entirely possible we'll see this again on other implementations.
714 */
715 static int
fallback_format_for(uint32_t format)716 fallback_format_for(uint32_t format)
717 {
718 switch (format) {
719 case GBM_FORMAT_XRGB8888:
720 return GBM_FORMAT_ARGB8888;
721 case GBM_FORMAT_XRGB2101010:
722 return GBM_FORMAT_ARGB2101010;
723 default:
724 return 0;
725 }
726 }
727
728 static int
drm_backend_create_gl_renderer(struct drm_backend * b)729 drm_backend_create_gl_renderer(struct drm_backend *b)
730 {
731 EGLint format[3] = {
732 b->gbm_format,
733 fallback_format_for(b->gbm_format),
734 0,
735 };
736 int n_formats = 2;
737
738 if (format[1])
739 n_formats = 3;
740 if (gl_renderer->display_create(b->compositor,
741 EGL_PLATFORM_GBM_KHR,
742 (void *)b->gbm,
743 NULL,
744 gl_renderer->opaque_attribs,
745 format,
746 n_formats) < 0) {
747 return -1;
748 }
749
750 return 0;
751 }
752
753 static int
init_egl(struct drm_backend * b)754 init_egl(struct drm_backend *b)
755 {
756 b->gbm = create_gbm_device(b->drm.fd);
757
758 if (!b->gbm)
759 return -1;
760
761 if (drm_backend_create_gl_renderer(b) < 0) {
762 gbm_device_destroy(b->gbm);
763 return -1;
764 }
765
766 return 0;
767 }
768
769 static int
init_pixman(struct drm_backend * b)770 init_pixman(struct drm_backend *b)
771 {
772 return pixman_renderer_init(b->compositor);
773 }
774
775
776 /**
777 * Create a drm_plane for a hardware plane
778 *
779 * Creates one drm_plane structure for a hardware plane, and initialises its
780 * properties and formats.
781 *
782 * In the absence of universal plane support, where KMS does not explicitly
783 * expose the primary and cursor planes to userspace, this may also create
784 * an 'internal' plane for internal management.
785 *
786 * This function does not add the plane to the list of usable planes in Weston
787 * itself; the caller is responsible for this.
788 *
789 * Call drm_plane_destroy to clean up the plane.
790 *
791 * @sa drm_output_find_special_plane
792 * @param b DRM compositor backend
793 * @param kplane DRM plane to create, or NULL if creating internal plane
794 * @param output Output to create internal plane for, or NULL
795 * @param type Type to use when creating internal plane, or invalid
796 * @param format Format to use for internal planes, or 0
797 */
798 static struct drm_plane *
drm_plane_create(struct drm_backend * b,const drmModePlane * kplane,struct drm_output * output,enum wdrm_plane_type type,uint32_t format)799 drm_plane_create(struct drm_backend *b, const drmModePlane *kplane,
800 struct drm_output *output, enum wdrm_plane_type type,
801 uint32_t format)
802 {
803 struct drm_plane *plane;
804 drmModeObjectProperties *props;
805 uint32_t num_formats = (kplane) ? kplane->count_formats : 1;
806
807 plane = zalloc(sizeof(*plane) +
808 (sizeof(plane->formats[0]) * num_formats));
809 if (!plane) {
810 weston_log("%s: out of memory\n", __func__);
811 return NULL;
812 }
813
814 plane->backend = b;
815 plane->count_formats = num_formats;
816 plane->state_cur = drm_plane_state_alloc(NULL, plane);
817 plane->state_cur->complete = true;
818
819 if (kplane) {
820 plane->possible_crtcs = kplane->possible_crtcs;
821 plane->plane_id = kplane->plane_id;
822
823 props = drmModeObjectGetProperties(b->drm.fd, kplane->plane_id,
824 DRM_MODE_OBJECT_PLANE);
825 if (!props) {
826 weston_log("couldn't get plane properties\n");
827 goto err;
828 }
829 drm_property_info_populate(b, plane_props, plane->props,
830 WDRM_PLANE__COUNT, props);
831 plane->type =
832 drm_property_get_value(&plane->props[WDRM_PLANE_TYPE],
833 props,
834 WDRM_PLANE_TYPE__COUNT);
835
836 if (drm_plane_populate_formats(plane, kplane, props) < 0) {
837 drmModeFreeObjectProperties(props);
838 goto err;
839 }
840
841 drmModeFreeObjectProperties(props);
842 }
843 else {
844 plane->possible_crtcs = (1 << output->pipe);
845 plane->plane_id = 0;
846 plane->count_formats = 1;
847 plane->formats[0].format = format;
848 plane->type = type;
849 }
850
851 if (plane->type == WDRM_PLANE_TYPE__COUNT)
852 goto err_props;
853
854 /* With universal planes, everything is a DRM plane; without
855 * universal planes, the only DRM planes are overlay planes.
856 * Everything else is a fake plane. */
857 if (b->universal_planes) {
858 assert(kplane);
859 } else {
860 if (kplane)
861 assert(plane->type == WDRM_PLANE_TYPE_OVERLAY);
862 else
863 assert(plane->type != WDRM_PLANE_TYPE_OVERLAY &&
864 output);
865 }
866
867 weston_plane_init(&plane->base, b->compositor, 0, 0);
868 wl_list_insert(&b->plane_list, &plane->link);
869
870 return plane;
871
872 err_props:
873 drm_property_info_free(plane->props, WDRM_PLANE__COUNT);
874 err:
875 drm_plane_state_free(plane->state_cur, true);
876 free(plane);
877 return NULL;
878 }
879
880 /**
881 * Find, or create, a special-purpose plane
882 *
883 * Primary and cursor planes are a special case, in that before universal
884 * planes, they are driven by non-plane API calls. Without universal plane
885 * support, the only way to configure a primary plane is via drmModeSetCrtc,
886 * and the only way to configure a cursor plane is drmModeSetCursor2.
887 *
888 * Although they may actually be regular planes in the hardware, without
889 * universal plane support, these planes are not actually exposed to
890 * userspace in the regular plane list.
891 *
892 * However, for ease of internal tracking, we want to manage all planes
893 * through the same drm_plane structures. Therefore, when we are running
894 * without universal plane support, we create fake drm_plane structures
895 * to track these planes.
896 *
897 * @param b DRM backend
898 * @param output Output to use for plane
899 * @param type Type of plane
900 */
901 static struct drm_plane *
drm_output_find_special_plane(struct drm_backend * b,struct drm_output * output,enum wdrm_plane_type type)902 drm_output_find_special_plane(struct drm_backend *b, struct drm_output *output,
903 enum wdrm_plane_type type)
904 {
905 struct drm_plane *plane;
906
907 if (!b->universal_planes) {
908 uint32_t format;
909
910 switch (type) {
911 case WDRM_PLANE_TYPE_CURSOR:
912 format = DRM_FORMAT_ARGB8888;
913 break;
914 case WDRM_PLANE_TYPE_PRIMARY:
915 /* We don't know what formats the primary plane supports
916 * before universal planes, so we just assume that the
917 * GBM format works; however, this isn't set until after
918 * the output is created. */
919 format = 0;
920 break;
921 default:
922 assert(!"invalid type in drm_output_find_special_plane");
923 break;
924 }
925
926 return drm_plane_create(b, NULL, output, type, format);
927 }
928
929 wl_list_for_each(plane, &b->plane_list, link) {
930 struct drm_output *tmp;
931 bool found_elsewhere = false;
932
933 if (plane->type != type)
934 continue;
935 if (!drm_plane_is_available(plane, output))
936 continue;
937
938 /* On some platforms, primary/cursor planes can roam
939 * between different CRTCs, so make sure we don't claim the
940 * same plane for two outputs. */
941 wl_list_for_each(tmp, &b->compositor->output_list,
942 base.link) {
943 if (tmp->cursor_plane == plane ||
944 tmp->scanout_plane == plane) {
945 found_elsewhere = true;
946 break;
947 }
948 }
949
950 if (found_elsewhere)
951 continue;
952
953 plane->possible_crtcs = (1 << output->pipe);
954 return plane;
955 }
956
957 return NULL;
958 }
959
960 /**
961 * Destroy one DRM plane
962 *
963 * Destroy a DRM plane, removing it from screen and releasing its retained
964 * buffers in the process. The counterpart to drm_plane_create.
965 *
966 * @param plane Plane to deallocate (will be freed)
967 */
968 static void
drm_plane_destroy(struct drm_plane * plane)969 drm_plane_destroy(struct drm_plane *plane)
970 {
971 if (plane->type == WDRM_PLANE_TYPE_OVERLAY)
972 drmModeSetPlane(plane->backend->drm.fd, plane->plane_id,
973 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
974 drm_plane_state_free(plane->state_cur, true);
975 drm_property_info_free(plane->props, WDRM_PLANE__COUNT);
976 weston_plane_release(&plane->base);
977 wl_list_remove(&plane->link);
978 free(plane);
979 }
980
981 /**
982 * Create a drm_plane for virtual output
983 *
984 * Call drm_virtual_plane_destroy to clean up the plane.
985 *
986 * @param b DRM compositor backend
987 * @param output Output to create internal plane for
988 */
989 static struct drm_plane *
drm_virtual_plane_create(struct drm_backend * b,struct drm_output * output)990 drm_virtual_plane_create(struct drm_backend *b, struct drm_output *output)
991 {
992 struct drm_plane *plane;
993
994 /* num of formats is one */
995 plane = zalloc(sizeof(*plane) + sizeof(plane->formats[0]));
996 if (!plane) {
997 weston_log("%s: out of memory\n", __func__);
998 return NULL;
999 }
1000
1001 plane->type = WDRM_PLANE_TYPE_PRIMARY;
1002 plane->backend = b;
1003 plane->state_cur = drm_plane_state_alloc(NULL, plane);
1004 plane->state_cur->complete = true;
1005 plane->formats[0].format = output->gbm_format;
1006 plane->count_formats = 1;
1007 if ((output->gbm_bo_flags & GBM_BO_USE_LINEAR) && b->fb_modifiers) {
1008 uint64_t *modifiers = zalloc(sizeof *modifiers);
1009 if (modifiers) {
1010 *modifiers = DRM_FORMAT_MOD_LINEAR;
1011 plane->formats[0].modifiers = modifiers;
1012 plane->formats[0].count_modifiers = 1;
1013 }
1014 }
1015
1016 weston_plane_init(&plane->base, b->compositor, 0, 0);
1017 wl_list_insert(&b->plane_list, &plane->link);
1018
1019 return plane;
1020 }
1021
1022 /**
1023 * Destroy one DRM plane
1024 *
1025 * @param plane Plane to deallocate (will be freed)
1026 */
1027 static void
drm_virtual_plane_destroy(struct drm_plane * plane)1028 drm_virtual_plane_destroy(struct drm_plane *plane)
1029 {
1030 drm_plane_state_free(plane->state_cur, true);
1031 weston_plane_release(&plane->base);
1032 wl_list_remove(&plane->link);
1033 if (plane->formats[0].modifiers)
1034 free(plane->formats[0].modifiers);
1035 free(plane);
1036 }
1037
1038 /**
1039 * Initialise sprites (overlay planes)
1040 *
1041 * Walk the list of provided DRM planes, and add overlay planes.
1042 *
1043 * Call destroy_sprites to free these planes.
1044 *
1045 * @param b DRM compositor backend
1046 */
1047 static void
create_sprites(struct drm_backend * b)1048 create_sprites(struct drm_backend *b)
1049 {
1050 drmModePlaneRes *kplane_res;
1051 drmModePlane *kplane;
1052 struct drm_plane *drm_plane;
1053 uint32_t i;
1054 kplane_res = drmModeGetPlaneResources(b->drm.fd);
1055 if (!kplane_res) {
1056 weston_log("failed to get plane resources: %s\n",
1057 strerror(errno));
1058 return;
1059 }
1060
1061 for (i = 0; i < kplane_res->count_planes; i++) {
1062 kplane = drmModeGetPlane(b->drm.fd, kplane_res->planes[i]);
1063 if (!kplane)
1064 continue;
1065
1066 drm_plane = drm_plane_create(b, kplane, NULL,
1067 WDRM_PLANE_TYPE__COUNT, 0);
1068 drmModeFreePlane(kplane);
1069 if (!drm_plane)
1070 continue;
1071
1072 if (drm_plane->type == WDRM_PLANE_TYPE_OVERLAY)
1073 weston_compositor_stack_plane(b->compositor,
1074 &drm_plane->base,
1075 &b->compositor->primary_plane);
1076 }
1077
1078 drmModeFreePlaneResources(kplane_res);
1079 }
1080
1081 /**
1082 * Clean up sprites (overlay planes)
1083 *
1084 * The counterpart to create_sprites.
1085 *
1086 * @param b DRM compositor backend
1087 */
1088 static void
destroy_sprites(struct drm_backend * b)1089 destroy_sprites(struct drm_backend *b)
1090 {
1091 struct drm_plane *plane, *next;
1092
1093 wl_list_for_each_safe(plane, next, &b->plane_list, link)
1094 drm_plane_destroy(plane);
1095 }
1096
1097 /* returns a value between 0-255 range, where higher is brighter */
1098 static uint32_t
drm_get_backlight(struct drm_head * head)1099 drm_get_backlight(struct drm_head *head)
1100 {
1101 long brightness, max_brightness, norm;
1102
1103 brightness = backlight_get_brightness(head->backlight);
1104 max_brightness = backlight_get_max_brightness(head->backlight);
1105
1106 /* convert it on a scale of 0 to 255 */
1107 norm = (brightness * 255)/(max_brightness);
1108
1109 return (uint32_t) norm;
1110 }
1111
1112 /* values accepted are between 0-255 range */
1113 static void
drm_set_backlight(struct weston_output * output_base,uint32_t value)1114 drm_set_backlight(struct weston_output *output_base, uint32_t value)
1115 {
1116 struct drm_output *output = to_drm_output(output_base);
1117 struct drm_head *head;
1118 long max_brightness, new_brightness;
1119
1120 if (value > 255)
1121 return;
1122
1123 wl_list_for_each(head, &output->base.head_list, base.output_link) {
1124 if (!head->backlight)
1125 return;
1126
1127 max_brightness = backlight_get_max_brightness(head->backlight);
1128
1129 /* get denormalized value */
1130 new_brightness = (value * max_brightness) / 255;
1131
1132 backlight_set_brightness(head->backlight, new_brightness);
1133 }
1134 }
1135
1136 static void
drm_output_init_backlight(struct drm_output * output)1137 drm_output_init_backlight(struct drm_output *output)
1138 {
1139 struct weston_head *base;
1140 struct drm_head *head;
1141
1142 output->base.set_backlight = NULL;
1143
1144 wl_list_for_each(base, &output->base.head_list, output_link) {
1145 head = to_drm_head(base);
1146
1147 if (head->backlight) {
1148 weston_log("Initialized backlight for head '%s', device %s\n",
1149 head->base.name, head->backlight->path);
1150
1151 if (!output->base.set_backlight) {
1152 output->base.set_backlight = drm_set_backlight;
1153 output->base.backlight_current =
1154 drm_get_backlight(head);
1155 }
1156 }
1157 }
1158 }
1159
1160 /**
1161 * Power output on or off
1162 *
1163 * The DPMS/power level of an output is used to switch it on or off. This
1164 * is DRM's hook for doing so, which can called either as part of repaint,
1165 * or independently of the repaint loop.
1166 *
1167 * If we are called as part of repaint, we simply set the relevant bit in
1168 * state and return.
1169 *
1170 * This function is never called on a virtual output.
1171 */
1172 static void
drm_set_dpms(struct weston_output * output_base,enum dpms_enum level)1173 drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1174 {
1175 struct drm_output *output = to_drm_output(output_base);
1176 struct drm_backend *b = to_drm_backend(output_base->compositor);
1177 struct drm_pending_state *pending_state = b->repaint_data;
1178 struct drm_output_state *state;
1179 int ret;
1180
1181 assert(!output->virtual);
1182
1183 if (output->state_cur->dpms == level)
1184 return;
1185
1186 /* If we're being called during the repaint loop, then this is
1187 * simple: discard any previously-generated state, and create a new
1188 * state where we disable everything. When we come to flush, this
1189 * will be applied.
1190 *
1191 * However, we need to be careful: we can be called whilst another
1192 * output is in its repaint cycle (pending_state exists), but our
1193 * output still has an incomplete state application outstanding.
1194 * In that case, we need to wait until that completes. */
1195 if (pending_state && !output->state_last) {
1196 /* The repaint loop already sets DPMS on; we don't need to
1197 * explicitly set it on here, as it will already happen
1198 * whilst applying the repaint state. */
1199 if (level == WESTON_DPMS_ON)
1200 return;
1201
1202 state = drm_pending_state_get_output(pending_state, output);
1203 if (state)
1204 drm_output_state_free(state);
1205 state = drm_output_get_disable_state(pending_state, output);
1206 return;
1207 }
1208
1209 /* As we throw everything away when disabling, just send us back through
1210 * a repaint cycle. */
1211 if (level == WESTON_DPMS_ON) {
1212 if (output->dpms_off_pending)
1213 output->dpms_off_pending = 0;
1214 weston_output_schedule_repaint(output_base);
1215 return;
1216 }
1217
1218 /* If we've already got a request in the pipeline, then we need to
1219 * park our DPMS request until that request has quiesced. */
1220 if (output->state_last) {
1221 output->dpms_off_pending = 1;
1222 return;
1223 }
1224
1225 pending_state = drm_pending_state_alloc(b);
1226 drm_output_get_disable_state(pending_state, output);
1227 ret = drm_pending_state_apply_sync(pending_state);
1228 if (ret != 0)
1229 weston_log("drm_set_dpms: couldn't disable output?\n");
1230 }
1231
1232 static const char * const connector_type_names[] = {
1233 [DRM_MODE_CONNECTOR_Unknown] = "Unknown",
1234 [DRM_MODE_CONNECTOR_VGA] = "VGA",
1235 [DRM_MODE_CONNECTOR_DVII] = "DVI-I",
1236 [DRM_MODE_CONNECTOR_DVID] = "DVI-D",
1237 [DRM_MODE_CONNECTOR_DVIA] = "DVI-A",
1238 [DRM_MODE_CONNECTOR_Composite] = "Composite",
1239 [DRM_MODE_CONNECTOR_SVIDEO] = "SVIDEO",
1240 [DRM_MODE_CONNECTOR_LVDS] = "LVDS",
1241 [DRM_MODE_CONNECTOR_Component] = "Component",
1242 [DRM_MODE_CONNECTOR_9PinDIN] = "DIN",
1243 [DRM_MODE_CONNECTOR_DisplayPort] = "DP",
1244 [DRM_MODE_CONNECTOR_HDMIA] = "HDMI-A",
1245 [DRM_MODE_CONNECTOR_HDMIB] = "HDMI-B",
1246 [DRM_MODE_CONNECTOR_TV] = "TV",
1247 [DRM_MODE_CONNECTOR_eDP] = "eDP",
1248 #ifdef DRM_MODE_CONNECTOR_DSI
1249 [DRM_MODE_CONNECTOR_VIRTUAL] = "Virtual",
1250 [DRM_MODE_CONNECTOR_DSI] = "DSI",
1251 #endif
1252 #ifdef DRM_MODE_CONNECTOR_DPI
1253 [DRM_MODE_CONNECTOR_DPI] = "DPI",
1254 #endif
1255 };
1256
1257 /** Create a name given a DRM connector
1258 *
1259 * \param con The DRM connector whose type and id form the name.
1260 * \return A newly allocate string, or NULL on error. Must be free()'d
1261 * after use.
1262 *
1263 * The name does not identify the DRM display device.
1264 */
1265 static char *
make_connector_name(const drmModeConnector * con)1266 make_connector_name(const drmModeConnector *con)
1267 {
1268 char *name;
1269 const char *type_name = NULL;
1270 int ret;
1271
1272 if (con->connector_type < ARRAY_LENGTH(connector_type_names))
1273 type_name = connector_type_names[con->connector_type];
1274
1275 if (!type_name)
1276 type_name = "UNNAMED";
1277
1278 ret = asprintf(&name, "%s-%d", type_name, con->connector_type_id);
1279 if (ret < 0)
1280 return NULL;
1281
1282 return name;
1283 }
1284
drm_output_fini_cursor_egl(struct drm_output * output)1285 static void drm_output_fini_cursor_egl(struct drm_output *output)
1286 {
1287 unsigned int i;
1288
1289 for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
1290 drm_fb_unref(output->gbm_cursor_fb[i]);
1291 output->gbm_cursor_fb[i] = NULL;
1292 }
1293 }
1294
1295 static int
drm_output_init_cursor_egl(struct drm_output * output,struct drm_backend * b)1296 drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
1297 {
1298 unsigned int i;
1299
1300 /* No point creating cursors if we don't have a plane for them. */
1301 if (!output->cursor_plane)
1302 return 0;
1303
1304 for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
1305 struct gbm_bo *bo;
1306
1307 bo = gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
1308 GBM_FORMAT_ARGB8888,
1309 GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
1310 if (!bo)
1311 goto err;
1312
1313 output->gbm_cursor_fb[i] =
1314 drm_fb_get_from_bo(bo, b, false, BUFFER_CURSOR);
1315 if (!output->gbm_cursor_fb[i]) {
1316 gbm_bo_destroy(bo);
1317 goto err;
1318 }
1319 output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
1320 }
1321
1322 return 0;
1323
1324 err:
1325 weston_log("cursor buffers unavailable, using gl cursors\n");
1326 b->cursors_are_broken = 1;
1327 drm_output_fini_cursor_egl(output);
1328 return -1;
1329 }
1330
1331 /* Init output state that depends on gl or gbm */
1332 static int
drm_output_init_egl(struct drm_output * output,struct drm_backend * b)1333 drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
1334 {
1335 EGLint format[2] = {
1336 output->gbm_format,
1337 fallback_format_for(output->gbm_format),
1338 };
1339 int n_formats = 1;
1340 struct weston_mode *mode = output->base.current_mode;
1341 struct drm_plane *plane = output->scanout_plane;
1342 unsigned int i;
1343
1344 assert(output->gbm_surface == NULL);
1345
1346 for (i = 0; i < plane->count_formats; i++) {
1347 if (plane->formats[i].format == output->gbm_format)
1348 break;
1349 }
1350
1351 if (i == plane->count_formats) {
1352 weston_log("format 0x%x not supported by output %s\n",
1353 output->gbm_format, output->base.name);
1354 return -1;
1355 }
1356
1357 #ifdef HAVE_GBM_MODIFIERS
1358 if (plane->formats[i].count_modifiers > 0) {
1359 output->gbm_surface =
1360 gbm_surface_create_with_modifiers(b->gbm,
1361 mode->width,
1362 mode->height,
1363 output->gbm_format,
1364 plane->formats[i].modifiers,
1365 plane->formats[i].count_modifiers);
1366 }
1367
1368 /* If allocating with modifiers fails, try again without. This can
1369 * happen when the KMS display device supports modifiers but the
1370 * GBM driver does not, e.g. the old i915 Mesa driver. */
1371 if (!output->gbm_surface)
1372 #endif
1373 {
1374 output->gbm_surface =
1375 gbm_surface_create(b->gbm, mode->width, mode->height,
1376 output->gbm_format,
1377 output->gbm_bo_flags);
1378 }
1379
1380 if (!output->gbm_surface) {
1381 weston_log("failed to create gbm surface\n");
1382 return -1;
1383 }
1384
1385 if (format[1])
1386 n_formats = 2;
1387 if (gl_renderer->output_window_create(&output->base,
1388 (EGLNativeWindowType)output->gbm_surface,
1389 output->gbm_surface,
1390 gl_renderer->opaque_attribs,
1391 format,
1392 n_formats) < 0) {
1393 weston_log("failed to create gl renderer output state\n");
1394 gbm_surface_destroy(output->gbm_surface);
1395 output->gbm_surface = NULL;
1396 return -1;
1397 }
1398
1399 drm_output_init_cursor_egl(output, b);
1400
1401 return 0;
1402 }
1403
1404 static void
drm_output_fini_egl(struct drm_output * output)1405 drm_output_fini_egl(struct drm_output *output)
1406 {
1407 struct drm_backend *b = to_drm_backend(output->base.compositor);
1408
1409 /* Destroying the GBM surface will destroy all our GBM buffers,
1410 * regardless of refcount. Ensure we destroy them here. */
1411 if (!b->shutting_down &&
1412 output->scanout_plane->state_cur->fb &&
1413 output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
1414 drm_plane_state_free(output->scanout_plane->state_cur, true);
1415 output->scanout_plane->state_cur =
1416 drm_plane_state_alloc(NULL, output->scanout_plane);
1417 output->scanout_plane->state_cur->complete = true;
1418 }
1419
1420 gl_renderer->output_destroy(&output->base);
1421 gbm_surface_destroy(output->gbm_surface);
1422 output->gbm_surface = NULL;
1423 drm_output_fini_cursor_egl(output);
1424 }
1425
1426 static int
drm_output_init_pixman(struct drm_output * output,struct drm_backend * b)1427 drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
1428 {
1429 int w = output->base.current_mode->width;
1430 int h = output->base.current_mode->height;
1431 uint32_t format = output->gbm_format;
1432 uint32_t pixman_format;
1433 unsigned int i;
1434 uint32_t flags = 0;
1435
1436 switch (format) {
1437 case DRM_FORMAT_XRGB8888:
1438 pixman_format = PIXMAN_x8r8g8b8;
1439 break;
1440 case DRM_FORMAT_RGB565:
1441 pixman_format = PIXMAN_r5g6b5;
1442 break;
1443 default:
1444 weston_log("Unsupported pixman format 0x%x\n", format);
1445 return -1;
1446 }
1447
1448 /* FIXME error checking */
1449 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1450 output->dumb[i] = drm_fb_create_dumb(b, w, h, format);
1451 if (!output->dumb[i])
1452 goto err;
1453
1454 output->image[i] =
1455 pixman_image_create_bits(pixman_format, w, h,
1456 output->dumb[i]->map,
1457 output->dumb[i]->strides[0]);
1458 if (!output->image[i])
1459 goto err;
1460 }
1461
1462 if (b->use_pixman_shadow)
1463 flags |= PIXMAN_RENDERER_OUTPUT_USE_SHADOW;
1464
1465 if (pixman_renderer_output_create(&output->base, flags) < 0)
1466 goto err;
1467
1468 weston_log("DRM: output %s %s shadow framebuffer.\n", output->base.name,
1469 b->use_pixman_shadow ? "uses" : "does not use");
1470
1471 pixman_region32_init_rect(&output->previous_damage,
1472 output->base.x, output->base.y, output->base.width, output->base.height);
1473
1474 return 0;
1475
1476 err:
1477 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1478 if (output->dumb[i])
1479 drm_fb_unref(output->dumb[i]);
1480 if (output->image[i])
1481 pixman_image_unref(output->image[i]);
1482
1483 output->dumb[i] = NULL;
1484 output->image[i] = NULL;
1485 }
1486
1487 return -1;
1488 }
1489
1490 static void
drm_output_fini_pixman(struct drm_output * output)1491 drm_output_fini_pixman(struct drm_output *output)
1492 {
1493 struct drm_backend *b = to_drm_backend(output->base.compositor);
1494 unsigned int i;
1495
1496 /* Destroying the Pixman surface will destroy all our buffers,
1497 * regardless of refcount. Ensure we destroy them here. */
1498 if (!b->shutting_down &&
1499 output->scanout_plane->state_cur->fb &&
1500 output->scanout_plane->state_cur->fb->type == BUFFER_PIXMAN_DUMB) {
1501 drm_plane_state_free(output->scanout_plane->state_cur, true);
1502 output->scanout_plane->state_cur =
1503 drm_plane_state_alloc(NULL, output->scanout_plane);
1504 output->scanout_plane->state_cur->complete = true;
1505 }
1506
1507 pixman_renderer_output_destroy(&output->base);
1508 pixman_region32_fini(&output->previous_damage);
1509
1510 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1511 pixman_image_unref(output->image[i]);
1512 drm_fb_unref(output->dumb[i]);
1513 output->dumb[i] = NULL;
1514 output->image[i] = NULL;
1515 }
1516 }
1517
1518 static void
setup_output_seat_constraint(struct drm_backend * b,struct weston_output * output,const char * s)1519 setup_output_seat_constraint(struct drm_backend *b,
1520 struct weston_output *output,
1521 const char *s)
1522 {
1523 if (strcmp(s, "") != 0) {
1524 struct weston_pointer *pointer;
1525 struct udev_seat *seat;
1526
1527 seat = udev_seat_get_named(&b->input, s);
1528 if (!seat)
1529 return;
1530
1531 seat->base.output = output;
1532
1533 pointer = weston_seat_get_pointer(&seat->base);
1534 if (pointer)
1535 weston_pointer_clamp(pointer,
1536 &pointer->x,
1537 &pointer->y);
1538 }
1539 }
1540
1541 static int
drm_output_attach_head(struct weston_output * output_base,struct weston_head * head_base)1542 drm_output_attach_head(struct weston_output *output_base,
1543 struct weston_head *head_base)
1544 {
1545 struct drm_backend *b = to_drm_backend(output_base->compositor);
1546
1547 if (wl_list_length(&output_base->head_list) >= MAX_CLONED_CONNECTORS)
1548 return -1;
1549
1550 if (!output_base->enabled)
1551 return 0;
1552
1553 /* XXX: ensure the configuration will work.
1554 * This is actually impossible without major infrastructure
1555 * work. */
1556
1557 /* Need to go through modeset to add connectors. */
1558 /* XXX: Ideally we'd do this per-output, not globally. */
1559 /* XXX: Doing it globally, what guarantees another output's update
1560 * will not clear the flag before this output is updated?
1561 */
1562 b->state_invalid = true;
1563
1564 weston_output_schedule_repaint(output_base);
1565
1566 return 0;
1567 }
1568
1569 static void
drm_output_detach_head(struct weston_output * output_base,struct weston_head * head_base)1570 drm_output_detach_head(struct weston_output *output_base,
1571 struct weston_head *head_base)
1572 {
1573 struct drm_backend *b = to_drm_backend(output_base->compositor);
1574
1575 if (!output_base->enabled)
1576 return;
1577
1578 /* Need to go through modeset to drop connectors that should no longer
1579 * be driven. */
1580 /* XXX: Ideally we'd do this per-output, not globally. */
1581 b->state_invalid = true;
1582
1583 weston_output_schedule_repaint(output_base);
1584 }
1585
1586 static int
parse_gbm_format(const char * s,uint32_t default_value,uint32_t * gbm_format)1587 parse_gbm_format(const char *s, uint32_t default_value, uint32_t *gbm_format)
1588 {
1589 const struct pixel_format_info *pinfo;
1590
1591 if (s == NULL) {
1592 *gbm_format = default_value;
1593
1594 return 0;
1595 }
1596
1597 pinfo = pixel_format_get_info_by_drm_name(s);
1598 if (!pinfo) {
1599 weston_log("fatal: unrecognized pixel format: %s\n", s);
1600
1601 return -1;
1602 }
1603
1604 /* GBM formats and DRM formats are identical. */
1605 *gbm_format = pinfo->format;
1606
1607 return 0;
1608 }
1609
1610 static int
drm_head_read_current_setup(struct drm_head * head,struct drm_backend * backend)1611 drm_head_read_current_setup(struct drm_head *head, struct drm_backend *backend)
1612 {
1613 int drm_fd = backend->drm.fd;
1614 drmModeEncoder *encoder;
1615 drmModeCrtc *crtc;
1616
1617 /* Get the current mode on the crtc that's currently driving
1618 * this connector. */
1619 encoder = drmModeGetEncoder(drm_fd, head->connector->encoder_id);
1620 if (encoder != NULL) {
1621 head->inherited_crtc_id = encoder->crtc_id;
1622
1623 crtc = drmModeGetCrtc(drm_fd, encoder->crtc_id);
1624 drmModeFreeEncoder(encoder);
1625
1626 if (crtc == NULL)
1627 return -1;
1628 if (crtc->mode_valid)
1629 head->inherited_mode = crtc->mode;
1630 drmModeFreeCrtc(crtc);
1631 }
1632
1633 return 0;
1634 }
1635
1636 static void
drm_output_set_gbm_format(struct weston_output * base,const char * gbm_format)1637 drm_output_set_gbm_format(struct weston_output *base,
1638 const char *gbm_format)
1639 {
1640 struct drm_output *output = to_drm_output(base);
1641 struct drm_backend *b = to_drm_backend(base->compositor);
1642
1643 if (parse_gbm_format(gbm_format, b->gbm_format, &output->gbm_format) == -1)
1644 output->gbm_format = b->gbm_format;
1645
1646 /* Without universal planes, we can't discover which formats are
1647 * supported by the primary plane; we just hope that the GBM format
1648 * works. */
1649 if (!b->universal_planes)
1650 output->scanout_plane->formats[0].format = output->gbm_format;
1651 }
1652
1653 static void
drm_output_set_seat(struct weston_output * base,const char * seat)1654 drm_output_set_seat(struct weston_output *base,
1655 const char *seat)
1656 {
1657 struct drm_output *output = to_drm_output(base);
1658 struct drm_backend *b = to_drm_backend(base->compositor);
1659
1660 setup_output_seat_constraint(b, &output->base,
1661 seat ? seat : "");
1662 }
1663
1664 static int
drm_output_init_gamma_size(struct drm_output * output)1665 drm_output_init_gamma_size(struct drm_output *output)
1666 {
1667 struct drm_backend *backend = to_drm_backend(output->base.compositor);
1668 drmModeCrtc *crtc;
1669
1670 assert(output->base.compositor);
1671 assert(output->crtc_id != 0);
1672 crtc = drmModeGetCrtc(backend->drm.fd, output->crtc_id);
1673 if (!crtc)
1674 return -1;
1675
1676 output->base.gamma_size = crtc->gamma_size;
1677
1678 drmModeFreeCrtc(crtc);
1679
1680 return 0;
1681 }
1682
1683 static uint32_t
drm_head_get_possible_crtcs_mask(struct drm_head * head)1684 drm_head_get_possible_crtcs_mask(struct drm_head *head)
1685 {
1686 uint32_t possible_crtcs = 0;
1687 drmModeEncoder *encoder;
1688 int i;
1689
1690 for (i = 0; i < head->connector->count_encoders; i++) {
1691 encoder = drmModeGetEncoder(head->backend->drm.fd,
1692 head->connector->encoders[i]);
1693 if (!encoder)
1694 continue;
1695
1696 possible_crtcs |= encoder->possible_crtcs;
1697 drmModeFreeEncoder(encoder);
1698 }
1699
1700 return possible_crtcs;
1701 }
1702
1703 static int
drm_crtc_get_index(drmModeRes * resources,uint32_t crtc_id)1704 drm_crtc_get_index(drmModeRes *resources, uint32_t crtc_id)
1705 {
1706 int i;
1707
1708 for (i = 0; i < resources->count_crtcs; i++) {
1709 if (resources->crtcs[i] == crtc_id)
1710 return i;
1711 }
1712
1713 assert(0 && "unknown crtc id");
1714 return -1;
1715 }
1716
1717 /** Pick a CRTC that might be able to drive all attached connectors
1718 *
1719 * @param output The output whose attached heads to include.
1720 * @param resources The DRM KMS resources.
1721 * @return CRTC index, or -1 on failure or not found.
1722 */
1723 static int
drm_output_pick_crtc(struct drm_output * output,drmModeRes * resources)1724 drm_output_pick_crtc(struct drm_output *output, drmModeRes *resources)
1725 {
1726 struct drm_backend *backend;
1727 struct weston_head *base;
1728 struct drm_head *head;
1729 uint32_t possible_crtcs = 0xffffffff;
1730 int existing_crtc[32];
1731 unsigned j, n = 0;
1732 uint32_t crtc_id;
1733 int best_crtc_index = -1;
1734 int fallback_crtc_index = -1;
1735 int i;
1736 bool match;
1737
1738 backend = to_drm_backend(output->base.compositor);
1739
1740 /* This algorithm ignores drmModeEncoder::possible_clones restriction,
1741 * because it is more often set wrong than not in the kernel. */
1742
1743 /* Accumulate a mask of possible crtcs and find existing routings. */
1744 wl_list_for_each(base, &output->base.head_list, output_link) {
1745 head = to_drm_head(base);
1746
1747 possible_crtcs &= drm_head_get_possible_crtcs_mask(head);
1748
1749 crtc_id = head->inherited_crtc_id;
1750 if (crtc_id > 0 && n < ARRAY_LENGTH(existing_crtc))
1751 existing_crtc[n++] = drm_crtc_get_index(resources,
1752 crtc_id);
1753 }
1754
1755 /* Find a crtc that could drive each connector individually at least,
1756 * and prefer existing routings. */
1757 for (i = 0; i < resources->count_crtcs; i++) {
1758 crtc_id = resources->crtcs[i];
1759
1760 /* Could the crtc not drive each connector? */
1761 if (!(possible_crtcs & (1 << i)))
1762 continue;
1763
1764 /* Is the crtc already in use? */
1765 if (drm_output_find_by_crtc(backend, crtc_id))
1766 continue;
1767
1768 /* Try to preserve the existing CRTC -> connector routing;
1769 * it makes initialisation faster, and also since we have a
1770 * very dumb picking algorithm, may preserve a better
1771 * choice. */
1772 for (j = 0; j < n; j++) {
1773 if (existing_crtc[j] == i)
1774 return i;
1775 }
1776
1777 /* Check if any other head had existing routing to this CRTC.
1778 * If they did, this is not the best CRTC as it might be needed
1779 * for another output we haven't enabled yet. */
1780 match = false;
1781 wl_list_for_each(base, &backend->compositor->head_list,
1782 compositor_link) {
1783 head = to_drm_head(base);
1784
1785 if (head->base.output == &output->base)
1786 continue;
1787
1788 if (weston_head_is_enabled(&head->base))
1789 continue;
1790
1791 if (head->inherited_crtc_id == crtc_id) {
1792 match = true;
1793 break;
1794 }
1795 }
1796 if (!match)
1797 best_crtc_index = i;
1798
1799 fallback_crtc_index = i;
1800 }
1801
1802 if (best_crtc_index != -1)
1803 return best_crtc_index;
1804
1805 if (fallback_crtc_index != -1)
1806 return fallback_crtc_index;
1807
1808 /* Likely possible_crtcs was empty due to asking for clones,
1809 * but since the DRM documentation says the kernel lies, let's
1810 * pick one crtc anyway. Trial and error is the only way to
1811 * be sure if something doesn't work. */
1812
1813 /* First pick any existing assignment. */
1814 for (j = 0; j < n; j++) {
1815 crtc_id = resources->crtcs[existing_crtc[j]];
1816 if (!drm_output_find_by_crtc(backend, crtc_id))
1817 return existing_crtc[j];
1818 }
1819
1820 /* Otherwise pick any available crtc. */
1821 for (i = 0; i < resources->count_crtcs; i++) {
1822 crtc_id = resources->crtcs[i];
1823
1824 if (!drm_output_find_by_crtc(backend, crtc_id))
1825 return i;
1826 }
1827
1828 return -1;
1829 }
1830
1831 /** Allocate a CRTC for the output
1832 *
1833 * @param output The output with no allocated CRTC.
1834 * @param resources DRM KMS resources.
1835 * @return 0 on success, -1 on failure.
1836 *
1837 * Finds a free CRTC that might drive the attached connectors, reserves the CRTC
1838 * for the output, and loads the CRTC properties.
1839 *
1840 * Populates the cursor and scanout planes.
1841 *
1842 * On failure, the output remains without a CRTC.
1843 */
1844 static int
drm_output_init_crtc(struct drm_output * output,drmModeRes * resources)1845 drm_output_init_crtc(struct drm_output *output, drmModeRes *resources)
1846 {
1847 struct drm_backend *b = to_drm_backend(output->base.compositor);
1848 drmModeObjectPropertiesPtr props;
1849 int i;
1850
1851 assert(output->crtc_id == 0);
1852
1853 i = drm_output_pick_crtc(output, resources);
1854 if (i < 0) {
1855 weston_log("Output '%s': No available CRTCs.\n",
1856 output->base.name);
1857 return -1;
1858 }
1859
1860 output->crtc_id = resources->crtcs[i];
1861 output->pipe = i;
1862
1863 props = drmModeObjectGetProperties(b->drm.fd, output->crtc_id,
1864 DRM_MODE_OBJECT_CRTC);
1865 if (!props) {
1866 weston_log("failed to get CRTC properties\n");
1867 goto err_crtc;
1868 }
1869 drm_property_info_populate(b, crtc_props, output->props_crtc,
1870 WDRM_CRTC__COUNT, props);
1871 drmModeFreeObjectProperties(props);
1872
1873 output->scanout_plane =
1874 drm_output_find_special_plane(b, output,
1875 WDRM_PLANE_TYPE_PRIMARY);
1876 if (!output->scanout_plane) {
1877 weston_log("Failed to find primary plane for output %s\n",
1878 output->base.name);
1879 goto err_crtc;
1880 }
1881
1882 /* Failing to find a cursor plane is not fatal, as we'll fall back
1883 * to software cursor. */
1884 output->cursor_plane =
1885 drm_output_find_special_plane(b, output,
1886 WDRM_PLANE_TYPE_CURSOR);
1887
1888 wl_array_remove_uint32(&b->unused_crtcs, output->crtc_id);
1889
1890 return 0;
1891
1892 err_crtc:
1893 output->crtc_id = 0;
1894 output->pipe = 0;
1895
1896 return -1;
1897 }
1898
1899 /** Free the CRTC from the output
1900 *
1901 * @param output The output whose CRTC to deallocate.
1902 *
1903 * The CRTC reserved for the given output becomes free to use again.
1904 */
1905 static void
drm_output_fini_crtc(struct drm_output * output)1906 drm_output_fini_crtc(struct drm_output *output)
1907 {
1908 struct drm_backend *b = to_drm_backend(output->base.compositor);
1909 uint32_t *unused;
1910
1911 if (!b->universal_planes && !b->shutting_down) {
1912 /* With universal planes, the 'special' planes are allocated at
1913 * startup, freed at shutdown, and live on the plane list in
1914 * between. We want the planes to continue to exist and be freed
1915 * up for other outputs.
1916 *
1917 * Without universal planes, our special planes are
1918 * pseudo-planes allocated at output creation, freed at output
1919 * destruction, and not usable by other outputs.
1920 *
1921 * On the other hand, if the compositor is already shutting down,
1922 * the plane has already been destroyed.
1923 */
1924 if (output->cursor_plane)
1925 drm_plane_destroy(output->cursor_plane);
1926 if (output->scanout_plane)
1927 drm_plane_destroy(output->scanout_plane);
1928 }
1929
1930 drm_property_info_free(output->props_crtc, WDRM_CRTC__COUNT);
1931
1932 assert(output->crtc_id != 0);
1933
1934 unused = wl_array_add(&b->unused_crtcs, sizeof(*unused));
1935 *unused = output->crtc_id;
1936
1937 /* Force resetting unused CRTCs */
1938 b->state_invalid = true;
1939
1940 output->crtc_id = 0;
1941 output->cursor_plane = NULL;
1942 output->scanout_plane = NULL;
1943 }
1944
1945 static int
drm_output_enable(struct weston_output * base)1946 drm_output_enable(struct weston_output *base)
1947 {
1948 struct drm_output *output = to_drm_output(base);
1949 struct drm_backend *b = to_drm_backend(base->compositor);
1950 drmModeRes *resources;
1951 int ret;
1952
1953 assert(!output->virtual);
1954
1955 resources = drmModeGetResources(b->drm.fd);
1956 if (!resources) {
1957 weston_log("drmModeGetResources failed\n");
1958 return -1;
1959 }
1960 ret = drm_output_init_crtc(output, resources);
1961 drmModeFreeResources(resources);
1962 if (ret < 0)
1963 return -1;
1964
1965 if (drm_output_init_gamma_size(output) < 0)
1966 goto err;
1967
1968 if (b->pageflip_timeout)
1969 drm_output_pageflip_timer_create(output);
1970
1971 if (b->use_pixman) {
1972 if (drm_output_init_pixman(output, b) < 0) {
1973 weston_log("Failed to init output pixman state\n");
1974 goto err;
1975 }
1976 } else if (drm_output_init_egl(output, b) < 0) {
1977 weston_log("Failed to init output gl state\n");
1978 goto err;
1979 }
1980
1981 drm_output_init_backlight(output);
1982
1983 output->base.start_repaint_loop = drm_output_start_repaint_loop;
1984 output->base.repaint = drm_output_repaint;
1985 output->base.assign_planes = drm_assign_planes;
1986 output->base.set_dpms = drm_set_dpms;
1987 output->base.switch_mode = drm_output_switch_mode;
1988 output->base.set_gamma = drm_output_set_gamma;
1989
1990 if (output->cursor_plane)
1991 weston_compositor_stack_plane(b->compositor,
1992 &output->cursor_plane->base,
1993 NULL);
1994 else
1995 b->cursors_are_broken = 1;
1996
1997 weston_compositor_stack_plane(b->compositor,
1998 &output->scanout_plane->base,
1999 &b->compositor->primary_plane);
2000
2001 weston_log("Output %s (crtc %d) video modes:\n",
2002 output->base.name, output->crtc_id);
2003 drm_output_print_modes(output);
2004
2005 return 0;
2006
2007 err:
2008 drm_output_fini_crtc(output);
2009
2010 return -1;
2011 }
2012
2013 static void
drm_output_deinit(struct weston_output * base)2014 drm_output_deinit(struct weston_output *base)
2015 {
2016 struct drm_output *output = to_drm_output(base);
2017 struct drm_backend *b = to_drm_backend(base->compositor);
2018
2019 if (b->use_pixman)
2020 drm_output_fini_pixman(output);
2021 else
2022 drm_output_fini_egl(output);
2023
2024 /* Since our planes are no longer in use anywhere, remove their base
2025 * weston_plane's link from the plane stacking list, unless we're
2026 * shutting down, in which case the plane has already been
2027 * destroyed. */
2028 if (!b->shutting_down) {
2029 wl_list_remove(&output->scanout_plane->base.link);
2030 wl_list_init(&output->scanout_plane->base.link);
2031
2032 if (output->cursor_plane) {
2033 wl_list_remove(&output->cursor_plane->base.link);
2034 wl_list_init(&output->cursor_plane->base.link);
2035 /* Turn off hardware cursor */
2036 drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
2037 }
2038 }
2039
2040 drm_output_fini_crtc(output);
2041 }
2042
2043 static void
2044 drm_head_destroy(struct drm_head *head);
2045
2046 static void
drm_output_destroy(struct weston_output * base)2047 drm_output_destroy(struct weston_output *base)
2048 {
2049 struct drm_output *output = to_drm_output(base);
2050 struct drm_backend *b = to_drm_backend(base->compositor);
2051
2052 assert(!output->virtual);
2053
2054 if (output->page_flip_pending || output->atomic_complete_pending) {
2055 output->destroy_pending = 1;
2056 weston_log("destroy output while page flip pending\n");
2057 return;
2058 }
2059
2060 if (output->base.enabled)
2061 drm_output_deinit(&output->base);
2062
2063 drm_mode_list_destroy(b, &output->base.mode_list);
2064
2065 if (output->pageflip_timer)
2066 wl_event_source_remove(output->pageflip_timer);
2067
2068 weston_output_release(&output->base);
2069
2070 assert(!output->state_last);
2071 drm_output_state_free(output->state_cur);
2072
2073 free(output);
2074 }
2075
2076 static int
drm_output_disable(struct weston_output * base)2077 drm_output_disable(struct weston_output *base)
2078 {
2079 struct drm_output *output = to_drm_output(base);
2080
2081 assert(!output->virtual);
2082
2083 if (output->page_flip_pending || output->atomic_complete_pending) {
2084 output->disable_pending = 1;
2085 return -1;
2086 }
2087
2088 weston_log("Disabling output %s\n", output->base.name);
2089
2090 if (output->base.enabled)
2091 drm_output_deinit(&output->base);
2092
2093 output->disable_pending = 0;
2094
2095 return 0;
2096 }
2097
2098 /**
2099 * Update the list of unused connectors and CRTCs
2100 *
2101 * This keeps the unused_crtc arrays up to date.
2102 *
2103 * @param b Weston backend structure
2104 * @param resources DRM resources for this device
2105 */
2106 static void
drm_backend_update_unused_outputs(struct drm_backend * b,drmModeRes * resources)2107 drm_backend_update_unused_outputs(struct drm_backend *b, drmModeRes *resources)
2108 {
2109 int i;
2110
2111 wl_array_release(&b->unused_crtcs);
2112 wl_array_init(&b->unused_crtcs);
2113
2114 for (i = 0; i < resources->count_crtcs; i++) {
2115 struct drm_output *output;
2116 uint32_t *crtc_id;
2117
2118 output = drm_output_find_by_crtc(b, resources->crtcs[i]);
2119 if (output && output->base.enabled)
2120 continue;
2121
2122 crtc_id = wl_array_add(&b->unused_crtcs, sizeof(*crtc_id));
2123 *crtc_id = resources->crtcs[i];
2124 }
2125 }
2126
2127 /** Replace connector data and monitor information
2128 *
2129 * @param head The head to update.
2130 * @param connector The connector data to be owned by the head, must match
2131 * the head's connector ID.
2132 * @return 0 on success, -1 on failure.
2133 *
2134 * Takes ownership of @c connector on success, not on failure.
2135 *
2136 * May schedule a heads changed call.
2137 */
2138 static int
drm_head_assign_connector_info(struct drm_head * head,drmModeConnector * connector)2139 drm_head_assign_connector_info(struct drm_head *head,
2140 drmModeConnector *connector)
2141 {
2142 drmModeObjectProperties *props;
2143
2144 assert(connector);
2145 assert(head->connector_id == connector->connector_id);
2146
2147 props = drmModeObjectGetProperties(head->backend->drm.fd,
2148 head->connector_id,
2149 DRM_MODE_OBJECT_CONNECTOR);
2150 if (!props) {
2151 weston_log("Error: failed to get connector '%s' properties\n",
2152 head->base.name);
2153 return -1;
2154 }
2155
2156 if (head->connector)
2157 drmModeFreeConnector(head->connector);
2158 head->connector = connector;
2159
2160 drm_property_info_populate(head->backend, connector_props,
2161 head->props_conn,
2162 WDRM_CONNECTOR__COUNT, props);
2163 update_head_from_connector(head, props);
2164 drmModeFreeObjectProperties(props);
2165
2166 return 0;
2167 }
2168
2169 static void
drm_head_log_info(struct drm_head * head,const char * msg)2170 drm_head_log_info(struct drm_head *head, const char *msg)
2171 {
2172 if (head->base.connected) {
2173 weston_log("DRM: head '%s' %s, connector %d is connected, "
2174 "EDID make '%s', model '%s', serial '%s'\n",
2175 head->base.name, msg, head->connector_id,
2176 head->base.make, head->base.model,
2177 head->base.serial_number ?: "");
2178 } else {
2179 weston_log("DRM: head '%s' %s, connector %d is disconnected.\n",
2180 head->base.name, msg, head->connector_id);
2181 }
2182 }
2183
2184 /** Update connector and monitor information
2185 *
2186 * @param head The head to update.
2187 *
2188 * Re-reads the DRM property lists for the connector and updates monitor
2189 * information and connection status. This may schedule a heads changed call
2190 * to the user.
2191 */
2192 static void
drm_head_update_info(struct drm_head * head)2193 drm_head_update_info(struct drm_head *head)
2194 {
2195 drmModeConnector *connector;
2196
2197 connector = drmModeGetConnector(head->backend->drm.fd,
2198 head->connector_id);
2199 if (!connector) {
2200 weston_log("DRM: getting connector info for '%s' failed.\n",
2201 head->base.name);
2202 return;
2203 }
2204
2205 if (drm_head_assign_connector_info(head, connector) < 0)
2206 drmModeFreeConnector(connector);
2207
2208 if (head->base.device_changed)
2209 drm_head_log_info(head, "updated");
2210 }
2211
2212 /**
2213 * Create a Weston head for a connector
2214 *
2215 * Given a DRM connector, create a matching drm_head structure and add it
2216 * to Weston's head list.
2217 *
2218 * @param backend Weston backend structure
2219 * @param connector_id DRM connector ID for the head
2220 * @param drm_device udev device pointer
2221 * @returns The new head, or NULL on failure.
2222 */
2223 static struct drm_head *
drm_head_create(struct drm_backend * backend,uint32_t connector_id,struct udev_device * drm_device)2224 drm_head_create(struct drm_backend *backend, uint32_t connector_id,
2225 struct udev_device *drm_device)
2226 {
2227 struct drm_head *head;
2228 drmModeConnector *connector;
2229 char *name;
2230
2231 head = zalloc(sizeof *head);
2232 if (!head)
2233 return NULL;
2234
2235 connector = drmModeGetConnector(backend->drm.fd, connector_id);
2236 if (!connector)
2237 goto err_alloc;
2238
2239 name = make_connector_name(connector);
2240 if (!name)
2241 goto err_alloc;
2242
2243 weston_head_init(&head->base, name);
2244 free(name);
2245
2246 head->connector_id = connector_id;
2247 head->backend = backend;
2248
2249 head->backlight = backlight_init(drm_device, connector->connector_type);
2250
2251 if (drm_head_assign_connector_info(head, connector) < 0)
2252 goto err_init;
2253
2254 if (head->connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
2255 head->connector->connector_type == DRM_MODE_CONNECTOR_eDP)
2256 weston_head_set_internal(&head->base);
2257
2258 if (drm_head_read_current_setup(head, backend) < 0) {
2259 weston_log("Failed to retrieve current mode from connector %d.\n",
2260 head->connector_id);
2261 /* Not fatal. */
2262 }
2263
2264 weston_compositor_add_head(backend->compositor, &head->base);
2265 drm_head_log_info(head, "found");
2266
2267 return head;
2268
2269 err_init:
2270 weston_head_release(&head->base);
2271
2272 err_alloc:
2273 if (connector)
2274 drmModeFreeConnector(connector);
2275
2276 free(head);
2277
2278 return NULL;
2279 }
2280
2281 static void
drm_head_destroy(struct drm_head * head)2282 drm_head_destroy(struct drm_head *head)
2283 {
2284 weston_head_release(&head->base);
2285
2286 drm_property_info_free(head->props_conn, WDRM_CONNECTOR__COUNT);
2287 drmModeFreeConnector(head->connector);
2288
2289 if (head->backlight)
2290 backlight_destroy(head->backlight);
2291
2292 free(head);
2293 }
2294
2295 /**
2296 * Create a Weston output structure
2297 *
2298 * Create an "empty" drm_output. This is the implementation of
2299 * weston_backend::create_output.
2300 *
2301 * Creating an output is usually followed by drm_output_attach_head()
2302 * and drm_output_enable() to make use of it.
2303 *
2304 * @param compositor The compositor instance.
2305 * @param name Name for the new output.
2306 * @returns The output, or NULL on failure.
2307 */
2308 static struct weston_output *
drm_output_create(struct weston_compositor * compositor,const char * name)2309 drm_output_create(struct weston_compositor *compositor, const char *name)
2310 {
2311 struct drm_backend *b = to_drm_backend(compositor);
2312 struct drm_output *output;
2313
2314 output = zalloc(sizeof *output);
2315 if (output == NULL)
2316 return NULL;
2317
2318 output->backend = b;
2319 output->gbm_bo_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
2320
2321 weston_output_init(&output->base, compositor, name);
2322
2323 output->base.enable = drm_output_enable;
2324 output->base.destroy = drm_output_destroy;
2325 output->base.disable = drm_output_disable;
2326 output->base.attach_head = drm_output_attach_head;
2327 output->base.detach_head = drm_output_detach_head;
2328
2329 output->destroy_pending = 0;
2330 output->disable_pending = 0;
2331
2332 output->state_cur = drm_output_state_alloc(output, NULL);
2333
2334 weston_compositor_add_pending_output(&output->base, b->compositor);
2335
2336 return &output->base;
2337 }
2338
2339 static int
drm_backend_create_heads(struct drm_backend * b,struct udev_device * drm_device)2340 drm_backend_create_heads(struct drm_backend *b, struct udev_device *drm_device)
2341 {
2342 struct drm_head *head;
2343 drmModeRes *resources;
2344 int i;
2345
2346 resources = drmModeGetResources(b->drm.fd);
2347 if (!resources) {
2348 weston_log("drmModeGetResources failed\n");
2349 return -1;
2350 }
2351
2352 b->min_width = resources->min_width;
2353 b->max_width = resources->max_width;
2354 b->min_height = resources->min_height;
2355 b->max_height = resources->max_height;
2356
2357 for (i = 0; i < resources->count_connectors; i++) {
2358 uint32_t connector_id = resources->connectors[i];
2359
2360 head = drm_head_create(b, connector_id, drm_device);
2361 if (!head) {
2362 weston_log("DRM: failed to create head for connector %d.\n",
2363 connector_id);
2364 }
2365 }
2366
2367 drm_backend_update_unused_outputs(b, resources);
2368
2369 drmModeFreeResources(resources);
2370
2371 return 0;
2372 }
2373
2374 static void
drm_backend_update_heads(struct drm_backend * b,struct udev_device * drm_device)2375 drm_backend_update_heads(struct drm_backend *b, struct udev_device *drm_device)
2376 {
2377 drmModeRes *resources;
2378 struct weston_head *base, *next;
2379 struct drm_head *head;
2380 int i;
2381
2382 resources = drmModeGetResources(b->drm.fd);
2383 if (!resources) {
2384 weston_log("drmModeGetResources failed\n");
2385 return;
2386 }
2387
2388 /* collect new connectors that have appeared, e.g. MST */
2389 for (i = 0; i < resources->count_connectors; i++) {
2390 uint32_t connector_id = resources->connectors[i];
2391
2392 head = drm_head_find_by_connector(b, connector_id);
2393 if (head) {
2394 drm_head_update_info(head);
2395 } else {
2396 head = drm_head_create(b, connector_id, drm_device);
2397 if (!head)
2398 weston_log("DRM: failed to create head for hot-added connector %d.\n",
2399 connector_id);
2400 }
2401 }
2402
2403 /* Remove connectors that have disappeared. */
2404 wl_list_for_each_safe(base, next,
2405 &b->compositor->head_list, compositor_link) {
2406 bool removed = true;
2407
2408 head = to_drm_head(base);
2409
2410 for (i = 0; i < resources->count_connectors; i++) {
2411 if (resources->connectors[i] == head->connector_id) {
2412 removed = false;
2413 break;
2414 }
2415 }
2416
2417 if (!removed)
2418 continue;
2419
2420 weston_log("DRM: head '%s' (connector %d) disappeared.\n",
2421 head->base.name, head->connector_id);
2422 drm_head_destroy(head);
2423 }
2424
2425 drm_backend_update_unused_outputs(b, resources);
2426
2427 drmModeFreeResources(resources);
2428 }
2429
2430 static int
udev_event_is_hotplug(struct drm_backend * b,struct udev_device * device)2431 udev_event_is_hotplug(struct drm_backend *b, struct udev_device *device)
2432 {
2433 const char *sysnum;
2434 const char *val;
2435
2436 sysnum = udev_device_get_sysnum(device);
2437 if (!sysnum || atoi(sysnum) != b->drm.id)
2438 return 0;
2439
2440 val = udev_device_get_property_value(device, "HOTPLUG");
2441 if (!val)
2442 return 0;
2443
2444 return strcmp(val, "1") == 0;
2445 }
2446
2447 static int
udev_drm_event(int fd,uint32_t mask,void * data)2448 udev_drm_event(int fd, uint32_t mask, void *data)
2449 {
2450 struct drm_backend *b = data;
2451 struct udev_device *event;
2452
2453 event = udev_monitor_receive_device(b->udev_monitor);
2454
2455 if (udev_event_is_hotplug(b, event))
2456 drm_backend_update_heads(b, event);
2457
2458 udev_device_unref(event);
2459
2460 return 1;
2461 }
2462
2463 static void
drm_destroy(struct weston_compositor * ec)2464 drm_destroy(struct weston_compositor *ec)
2465 {
2466 struct drm_backend *b = to_drm_backend(ec);
2467 struct weston_head *base, *next;
2468
2469 udev_input_destroy(&b->input);
2470
2471 wl_event_source_remove(b->udev_drm_source);
2472 wl_event_source_remove(b->drm_source);
2473
2474 b->shutting_down = true;
2475
2476 destroy_sprites(b);
2477
2478 weston_compositor_log_scope_destroy(b->debug);
2479 b->debug = NULL;
2480 weston_compositor_shutdown(ec);
2481
2482 wl_list_for_each_safe(base, next, &ec->head_list, compositor_link)
2483 drm_head_destroy(to_drm_head(base));
2484
2485 if (b->gbm)
2486 gbm_device_destroy(b->gbm);
2487
2488 udev_monitor_unref(b->udev_monitor);
2489 udev_unref(b->udev);
2490
2491 weston_launcher_destroy(ec->launcher);
2492
2493 wl_array_release(&b->unused_crtcs);
2494
2495 close(b->drm.fd);
2496 free(b->drm.filename);
2497 free(b);
2498 }
2499
2500 static void
session_notify(struct wl_listener * listener,void * data)2501 session_notify(struct wl_listener *listener, void *data)
2502 {
2503 struct weston_compositor *compositor = data;
2504 struct drm_backend *b = to_drm_backend(compositor);
2505 struct drm_plane *plane;
2506 struct drm_output *output;
2507
2508 if (compositor->session_active) {
2509 weston_log("activating session\n");
2510 weston_compositor_wake(compositor);
2511 weston_compositor_damage_all(compositor);
2512 b->state_invalid = true;
2513 udev_input_enable(&b->input);
2514 } else {
2515 weston_log("deactivating session\n");
2516 udev_input_disable(&b->input);
2517
2518 weston_compositor_offscreen(compositor);
2519
2520 /* If we have a repaint scheduled (either from a
2521 * pending pageflip or the idle handler), make sure we
2522 * cancel that so we don't try to pageflip when we're
2523 * vt switched away. The OFFSCREEN state will prevent
2524 * further attempts at repainting. When we switch
2525 * back, we schedule a repaint, which will process
2526 * pending frame callbacks. */
2527
2528 wl_list_for_each(output, &compositor->output_list, base.link) {
2529 output->base.repaint_needed = false;
2530 if (output->cursor_plane)
2531 drmModeSetCursor(b->drm.fd, output->crtc_id,
2532 0, 0, 0);
2533 }
2534
2535 output = container_of(compositor->output_list.next,
2536 struct drm_output, base.link);
2537
2538 wl_list_for_each(plane, &b->plane_list, link) {
2539 if (plane->type != WDRM_PLANE_TYPE_OVERLAY)
2540 continue;
2541
2542 drmModeSetPlane(b->drm.fd,
2543 plane->plane_id,
2544 output->crtc_id, 0, 0,
2545 0, 0, 0, 0, 0, 0, 0, 0);
2546 }
2547 }
2548 }
2549
2550
2551 /**
2552 * Handle KMS GPU being added/removed
2553 *
2554 * If the device being added/removed is the KMS device, we activate/deactivate
2555 * the compositor session.
2556 *
2557 * @param compositor The compositor instance.
2558 * @param device The device being added/removed.
2559 * @param added Whether the device is being added (or removed)
2560 */
2561 static void
drm_device_changed(struct weston_compositor * compositor,dev_t device,bool added)2562 drm_device_changed(struct weston_compositor *compositor,
2563 dev_t device, bool added)
2564 {
2565 struct drm_backend *b = to_drm_backend(compositor);
2566
2567 if (b->drm.fd < 0 || b->drm.devnum != device ||
2568 compositor->session_active == added)
2569 return;
2570
2571 compositor->session_active = added;
2572 wl_signal_emit(&compositor->session_signal, compositor);
2573 }
2574
2575 /**
2576 * Determines whether or not a device is capable of modesetting. If successful,
2577 * sets b->drm.fd and b->drm.filename to the opened device.
2578 */
2579 static bool
drm_device_is_kms(struct drm_backend * b,struct udev_device * device)2580 drm_device_is_kms(struct drm_backend *b, struct udev_device *device)
2581 {
2582 const char *filename = udev_device_get_devnode(device);
2583 const char *sysnum = udev_device_get_sysnum(device);
2584 dev_t devnum = udev_device_get_devnum(device);
2585 drmModeRes *res;
2586 int id = -1, fd;
2587
2588 if (!filename)
2589 return false;
2590
2591 fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR);
2592 if (fd < 0)
2593 return false;
2594
2595 res = drmModeGetResources(fd);
2596 if (!res)
2597 goto out_fd;
2598
2599 if (res->count_crtcs <= 0 || res->count_connectors <= 0 ||
2600 res->count_encoders <= 0)
2601 goto out_res;
2602
2603 if (sysnum)
2604 id = atoi(sysnum);
2605 if (!sysnum || id < 0) {
2606 weston_log("couldn't get sysnum for device %s\n", filename);
2607 goto out_res;
2608 }
2609
2610 /* We can be called successfully on multiple devices; if we have,
2611 * clean up old entries. */
2612 if (b->drm.fd >= 0)
2613 weston_launcher_close(b->compositor->launcher, b->drm.fd);
2614 free(b->drm.filename);
2615
2616 b->drm.fd = fd;
2617 b->drm.id = id;
2618 b->drm.filename = strdup(filename);
2619 b->drm.devnum = devnum;
2620
2621 drmModeFreeResources(res);
2622
2623 return true;
2624
2625 out_res:
2626 drmModeFreeResources(res);
2627 out_fd:
2628 weston_launcher_close(b->compositor->launcher, fd);
2629 return false;
2630 }
2631
2632 /*
2633 * Find primary GPU
2634 * Some systems may have multiple DRM devices attached to a single seat. This
2635 * function loops over all devices and tries to find a PCI device with the
2636 * boot_vga sysfs attribute set to 1.
2637 * If no such device is found, the first DRM device reported by udev is used.
2638 * Devices are also vetted to make sure they are are capable of modesetting,
2639 * rather than pure render nodes (GPU with no display), or pure
2640 * memory-allocation devices (VGEM).
2641 */
2642 static struct udev_device*
find_primary_gpu(struct drm_backend * b,const char * seat)2643 find_primary_gpu(struct drm_backend *b, const char *seat)
2644 {
2645 struct udev_enumerate *e;
2646 struct udev_list_entry *entry;
2647 const char *path, *device_seat, *id;
2648 struct udev_device *device, *drm_device, *pci;
2649
2650 e = udev_enumerate_new(b->udev);
2651 udev_enumerate_add_match_subsystem(e, "drm");
2652 udev_enumerate_add_match_sysname(e, "card[0-9]*");
2653
2654 udev_enumerate_scan_devices(e);
2655 drm_device = NULL;
2656 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
2657 bool is_boot_vga = false;
2658
2659 path = udev_list_entry_get_name(entry);
2660 device = udev_device_new_from_syspath(b->udev, path);
2661 if (!device)
2662 continue;
2663 device_seat = udev_device_get_property_value(device, "ID_SEAT");
2664 if (!device_seat)
2665 device_seat = default_seat;
2666 if (strcmp(device_seat, seat)) {
2667 udev_device_unref(device);
2668 continue;
2669 }
2670
2671 pci = udev_device_get_parent_with_subsystem_devtype(device,
2672 "pci", NULL);
2673 if (pci) {
2674 id = udev_device_get_sysattr_value(pci, "boot_vga");
2675 if (id && !strcmp(id, "1"))
2676 is_boot_vga = true;
2677 }
2678
2679 /* If we already have a modesetting-capable device, and this
2680 * device isn't our boot-VGA device, we aren't going to use
2681 * it. */
2682 if (!is_boot_vga && drm_device) {
2683 udev_device_unref(device);
2684 continue;
2685 }
2686
2687 /* Make sure this device is actually capable of modesetting;
2688 * if this call succeeds, b->drm.{fd,filename} will be set,
2689 * and any old values freed. */
2690 if (!drm_device_is_kms(b, device)) {
2691 udev_device_unref(device);
2692 continue;
2693 }
2694
2695 /* There can only be one boot_vga device, and we try to use it
2696 * at all costs. */
2697 if (is_boot_vga) {
2698 if (drm_device)
2699 udev_device_unref(drm_device);
2700 drm_device = device;
2701 break;
2702 }
2703
2704 /* Per the (!is_boot_vga && drm_device) test above, we only
2705 * trump existing saved devices with boot-VGA devices, so if
2706 * we end up here, this must be the first device we've seen. */
2707 assert(!drm_device);
2708 drm_device = device;
2709 }
2710
2711 /* If we're returning a device to use, we must have an open FD for
2712 * it. */
2713 assert(!!drm_device == (b->drm.fd >= 0));
2714
2715 udev_enumerate_unref(e);
2716 return drm_device;
2717 }
2718
2719 static struct udev_device *
open_specific_drm_device(struct drm_backend * b,const char * name)2720 open_specific_drm_device(struct drm_backend *b, const char *name)
2721 {
2722 struct udev_device *device;
2723
2724 device = udev_device_new_from_subsystem_sysname(b->udev, "drm", name);
2725 if (!device) {
2726 weston_log("ERROR: could not open DRM device '%s'\n", name);
2727 return NULL;
2728 }
2729
2730 if (!drm_device_is_kms(b, device)) {
2731 udev_device_unref(device);
2732 weston_log("ERROR: DRM device '%s' is not a KMS device.\n", name);
2733 return NULL;
2734 }
2735
2736 /* If we're returning a device to use, we must have an open FD for
2737 * it. */
2738 assert(b->drm.fd >= 0);
2739
2740 return device;
2741 }
2742
2743 static void
planes_binding(struct weston_keyboard * keyboard,const struct timespec * time,uint32_t key,void * data)2744 planes_binding(struct weston_keyboard *keyboard, const struct timespec *time,
2745 uint32_t key, void *data)
2746 {
2747 struct drm_backend *b = data;
2748
2749 switch (key) {
2750 case KEY_C:
2751 b->cursors_are_broken ^= 1;
2752 break;
2753 case KEY_V:
2754 /* We don't support overlay-plane usage with legacy KMS. */
2755 if (b->atomic_modeset)
2756 b->sprites_are_broken ^= 1;
2757 break;
2758 case KEY_O:
2759 b->sprites_hidden ^= 1;
2760 break;
2761 default:
2762 break;
2763 }
2764 }
2765
2766 #ifdef BUILD_VAAPI_RECORDER
2767 static void
recorder_destroy(struct drm_output * output)2768 recorder_destroy(struct drm_output *output)
2769 {
2770 vaapi_recorder_destroy(output->recorder);
2771 output->recorder = NULL;
2772
2773 output->base.disable_planes--;
2774
2775 wl_list_remove(&output->recorder_frame_listener.link);
2776 weston_log("[libva recorder] done\n");
2777 }
2778
2779 static void
recorder_frame_notify(struct wl_listener * listener,void * data)2780 recorder_frame_notify(struct wl_listener *listener, void *data)
2781 {
2782 struct drm_output *output;
2783 struct drm_backend *b;
2784 int fd, ret;
2785
2786 output = container_of(listener, struct drm_output,
2787 recorder_frame_listener);
2788 b = to_drm_backend(output->base.compositor);
2789
2790 if (!output->recorder)
2791 return;
2792
2793 ret = drmPrimeHandleToFD(b->drm.fd,
2794 output->scanout_plane->state_cur->fb->handles[0],
2795 DRM_CLOEXEC, &fd);
2796 if (ret) {
2797 weston_log("[libva recorder] "
2798 "failed to create prime fd for front buffer\n");
2799 return;
2800 }
2801
2802 ret = vaapi_recorder_frame(output->recorder, fd,
2803 output->scanout_plane->state_cur->fb->strides[0]);
2804 if (ret < 0) {
2805 weston_log("[libva recorder] aborted: %s\n", strerror(errno));
2806 recorder_destroy(output);
2807 }
2808 }
2809
2810 static void *
create_recorder(struct drm_backend * b,int width,int height,const char * filename)2811 create_recorder(struct drm_backend *b, int width, int height,
2812 const char *filename)
2813 {
2814 int fd;
2815 drm_magic_t magic;
2816
2817 fd = open(b->drm.filename, O_RDWR | O_CLOEXEC);
2818 if (fd < 0)
2819 return NULL;
2820
2821 drmGetMagic(fd, &magic);
2822 drmAuthMagic(b->drm.fd, magic);
2823
2824 return vaapi_recorder_create(fd, width, height, filename);
2825 }
2826
2827 static void
recorder_binding(struct weston_keyboard * keyboard,const struct timespec * time,uint32_t key,void * data)2828 recorder_binding(struct weston_keyboard *keyboard, const struct timespec *time,
2829 uint32_t key, void *data)
2830 {
2831 struct drm_backend *b = data;
2832 struct drm_output *output;
2833 int width, height;
2834
2835 output = container_of(b->compositor->output_list.next,
2836 struct drm_output, base.link);
2837
2838 if (!output->recorder) {
2839 if (output->gbm_format != GBM_FORMAT_XRGB8888) {
2840 weston_log("failed to start vaapi recorder: "
2841 "output format not supported\n");
2842 return;
2843 }
2844
2845 width = output->base.current_mode->width;
2846 height = output->base.current_mode->height;
2847
2848 output->recorder =
2849 create_recorder(b, width, height, "capture.h264");
2850 if (!output->recorder) {
2851 weston_log("failed to create vaapi recorder\n");
2852 return;
2853 }
2854
2855 output->base.disable_planes++;
2856
2857 output->recorder_frame_listener.notify = recorder_frame_notify;
2858 wl_signal_add(&output->base.frame_signal,
2859 &output->recorder_frame_listener);
2860
2861 weston_output_schedule_repaint(&output->base);
2862
2863 weston_log("[libva recorder] initialized\n");
2864 } else {
2865 recorder_destroy(output);
2866 }
2867 }
2868 #else
2869 static void
recorder_binding(struct weston_keyboard * keyboard,const struct timespec * time,uint32_t key,void * data)2870 recorder_binding(struct weston_keyboard *keyboard, const struct timespec *time,
2871 uint32_t key, void *data)
2872 {
2873 weston_log("Compiled without libva support\n");
2874 }
2875 #endif
2876
2877 static void
switch_to_gl_renderer(struct drm_backend * b)2878 switch_to_gl_renderer(struct drm_backend *b)
2879 {
2880 struct drm_output *output;
2881 bool dmabuf_support_inited;
2882 bool linux_explicit_sync_inited;
2883
2884 if (!b->use_pixman)
2885 return;
2886
2887 dmabuf_support_inited = !!b->compositor->renderer->import_dmabuf;
2888 linux_explicit_sync_inited =
2889 b->compositor->capabilities & WESTON_CAP_EXPLICIT_SYNC;
2890
2891 weston_log("Switching to GL renderer\n");
2892
2893 b->gbm = create_gbm_device(b->drm.fd);
2894 if (!b->gbm) {
2895 weston_log("Failed to create gbm device. "
2896 "Aborting renderer switch\n");
2897 return;
2898 }
2899
2900 wl_list_for_each(output, &b->compositor->output_list, base.link)
2901 pixman_renderer_output_destroy(&output->base);
2902
2903 b->compositor->renderer->destroy(b->compositor);
2904
2905 if (drm_backend_create_gl_renderer(b) < 0) {
2906 gbm_device_destroy(b->gbm);
2907 weston_log("Failed to create GL renderer. Quitting.\n");
2908 /* FIXME: we need a function to shutdown cleanly */
2909 assert(0);
2910 }
2911
2912 wl_list_for_each(output, &b->compositor->output_list, base.link)
2913 drm_output_init_egl(output, b);
2914
2915 b->use_pixman = 0;
2916
2917 if (!dmabuf_support_inited && b->compositor->renderer->import_dmabuf) {
2918 if (linux_dmabuf_setup(b->compositor) < 0)
2919 weston_log("Error: initializing dmabuf "
2920 "support failed.\n");
2921 }
2922
2923 if (!linux_explicit_sync_inited &&
2924 (b->compositor->capabilities & WESTON_CAP_EXPLICIT_SYNC)) {
2925 if (linux_explicit_synchronization_setup(b->compositor) < 0)
2926 weston_log("Error: initializing explicit "
2927 " synchronization support failed.\n");
2928 }
2929 }
2930
2931 static void
renderer_switch_binding(struct weston_keyboard * keyboard,const struct timespec * time,uint32_t key,void * data)2932 renderer_switch_binding(struct weston_keyboard *keyboard,
2933 const struct timespec *time, uint32_t key, void *data)
2934 {
2935 struct drm_backend *b =
2936 to_drm_backend(keyboard->seat->compositor);
2937
2938 switch_to_gl_renderer(b);
2939 }
2940
2941 static int
drm_virtual_output_start_repaint_loop(struct weston_output * output_base)2942 drm_virtual_output_start_repaint_loop(struct weston_output *output_base)
2943 {
2944 weston_output_finish_frame(output_base, NULL,
2945 WP_PRESENTATION_FEEDBACK_INVALID);
2946
2947 return 0;
2948 }
2949
2950 static int
drm_virtual_output_submit_frame(struct drm_output * output,struct drm_fb * fb)2951 drm_virtual_output_submit_frame(struct drm_output *output,
2952 struct drm_fb *fb)
2953 {
2954 struct drm_backend *b = to_drm_backend(output->base.compositor);
2955 int fd, ret;
2956
2957 assert(fb->num_planes == 1);
2958 ret = drmPrimeHandleToFD(b->drm.fd, fb->handles[0], DRM_CLOEXEC, &fd);
2959 if (ret) {
2960 weston_log("drmPrimeHandleFD failed, errno=%d\n", errno);
2961 return -1;
2962 }
2963
2964 drm_fb_ref(fb);
2965 ret = output->virtual_submit_frame(&output->base, fd, fb->strides[0],
2966 fb);
2967 if (ret < 0) {
2968 drm_fb_unref(fb);
2969 close(fd);
2970 }
2971 return ret;
2972 }
2973
2974 static int
drm_virtual_output_repaint(struct weston_output * output_base,pixman_region32_t * damage,void * repaint_data)2975 drm_virtual_output_repaint(struct weston_output *output_base,
2976 pixman_region32_t *damage,
2977 void *repaint_data)
2978 {
2979 struct drm_pending_state *pending_state = repaint_data;
2980 struct drm_output_state *state = NULL;
2981 struct drm_output *output = to_drm_output(output_base);
2982 struct drm_plane *scanout_plane = output->scanout_plane;
2983 struct drm_plane_state *scanout_state;
2984
2985 assert(output->virtual);
2986
2987 if (output->disable_pending || output->destroy_pending)
2988 goto err;
2989
2990 /* Drop frame if there isn't free buffers */
2991 if (!gbm_surface_has_free_buffers(output->gbm_surface)) {
2992 weston_log("%s: Drop frame!!\n", __func__);
2993 return -1;
2994 }
2995
2996 assert(!output->state_last);
2997
2998 /* If planes have been disabled in the core, we might not have
2999 * hit assign_planes at all, so might not have valid output state
3000 * here. */
3001 state = drm_pending_state_get_output(pending_state, output);
3002 if (!state)
3003 state = drm_output_state_duplicate(output->state_cur,
3004 pending_state,
3005 DRM_OUTPUT_STATE_CLEAR_PLANES);
3006
3007 drm_output_render(state, damage);
3008 scanout_state = drm_output_state_get_plane(state, scanout_plane);
3009 if (!scanout_state || !scanout_state->fb)
3010 goto err;
3011
3012 if (drm_virtual_output_submit_frame(output, scanout_state->fb) < 0)
3013 goto err;
3014
3015 return 0;
3016
3017 err:
3018 drm_output_state_free(state);
3019 return -1;
3020 }
3021
3022 static void
drm_virtual_output_deinit(struct weston_output * base)3023 drm_virtual_output_deinit(struct weston_output *base)
3024 {
3025 struct drm_output *output = to_drm_output(base);
3026
3027 drm_output_fini_egl(output);
3028
3029 drm_virtual_plane_destroy(output->scanout_plane);
3030 }
3031
3032 static void
drm_virtual_output_destroy(struct weston_output * base)3033 drm_virtual_output_destroy(struct weston_output *base)
3034 {
3035 struct drm_output *output = to_drm_output(base);
3036
3037 assert(output->virtual);
3038
3039 if (output->base.enabled)
3040 drm_virtual_output_deinit(&output->base);
3041
3042 weston_output_release(&output->base);
3043
3044 drm_output_state_free(output->state_cur);
3045
3046 free(output);
3047 }
3048
3049 static int
drm_virtual_output_enable(struct weston_output * output_base)3050 drm_virtual_output_enable(struct weston_output *output_base)
3051 {
3052 struct drm_output *output = to_drm_output(output_base);
3053 struct drm_backend *b = to_drm_backend(output_base->compositor);
3054
3055 assert(output->virtual);
3056
3057 if (b->use_pixman) {
3058 weston_log("Not support pixman renderer on Virtual output\n");
3059 goto err;
3060 }
3061
3062 if (!output->virtual_submit_frame) {
3063 weston_log("The virtual_submit_frame hook is not set\n");
3064 goto err;
3065 }
3066
3067 output->scanout_plane = drm_virtual_plane_create(b, output);
3068 if (!output->scanout_plane) {
3069 weston_log("Failed to find primary plane for output %s\n",
3070 output->base.name);
3071 return -1;
3072 }
3073
3074 if (drm_output_init_egl(output, b) < 0) {
3075 weston_log("Failed to init output gl state\n");
3076 goto err;
3077 }
3078
3079 output->base.start_repaint_loop = drm_virtual_output_start_repaint_loop;
3080 output->base.repaint = drm_virtual_output_repaint;
3081 output->base.assign_planes = drm_assign_planes;
3082 output->base.set_dpms = NULL;
3083 output->base.switch_mode = NULL;
3084 output->base.gamma_size = 0;
3085 output->base.set_gamma = NULL;
3086
3087 weston_compositor_stack_plane(b->compositor,
3088 &output->scanout_plane->base,
3089 &b->compositor->primary_plane);
3090
3091 return 0;
3092 err:
3093 return -1;
3094 }
3095
3096 static int
drm_virtual_output_disable(struct weston_output * base)3097 drm_virtual_output_disable(struct weston_output *base)
3098 {
3099 struct drm_output *output = to_drm_output(base);
3100
3101 assert(output->virtual);
3102
3103 if (output->base.enabled)
3104 drm_virtual_output_deinit(&output->base);
3105
3106 return 0;
3107 }
3108
3109 static struct weston_output *
drm_virtual_output_create(struct weston_compositor * c,char * name)3110 drm_virtual_output_create(struct weston_compositor *c, char *name)
3111 {
3112 struct drm_output *output;
3113
3114 output = zalloc(sizeof *output);
3115 if (!output)
3116 return NULL;
3117
3118 output->virtual = true;
3119 output->gbm_bo_flags = GBM_BO_USE_LINEAR | GBM_BO_USE_RENDERING;
3120
3121 weston_output_init(&output->base, c, name);
3122
3123 output->base.enable = drm_virtual_output_enable;
3124 output->base.destroy = drm_virtual_output_destroy;
3125 output->base.disable = drm_virtual_output_disable;
3126 output->base.attach_head = NULL;
3127
3128 output->state_cur = drm_output_state_alloc(output, NULL);
3129
3130 weston_compositor_add_pending_output(&output->base, c);
3131
3132 return &output->base;
3133 }
3134
3135 static uint32_t
drm_virtual_output_set_gbm_format(struct weston_output * base,const char * gbm_format)3136 drm_virtual_output_set_gbm_format(struct weston_output *base,
3137 const char *gbm_format)
3138 {
3139 struct drm_output *output = to_drm_output(base);
3140 struct drm_backend *b = to_drm_backend(base->compositor);
3141
3142 if (parse_gbm_format(gbm_format, b->gbm_format, &output->gbm_format) == -1)
3143 output->gbm_format = b->gbm_format;
3144
3145 return output->gbm_format;
3146 }
3147
3148 static void
drm_virtual_output_set_submit_frame_cb(struct weston_output * output_base,submit_frame_cb cb)3149 drm_virtual_output_set_submit_frame_cb(struct weston_output *output_base,
3150 submit_frame_cb cb)
3151 {
3152 struct drm_output *output = to_drm_output(output_base);
3153
3154 output->virtual_submit_frame = cb;
3155 }
3156
3157 static int
drm_virtual_output_get_fence_fd(struct weston_output * output_base)3158 drm_virtual_output_get_fence_fd(struct weston_output *output_base)
3159 {
3160 return gl_renderer->create_fence_fd(output_base);
3161 }
3162
3163 static void
drm_virtual_output_buffer_released(struct drm_fb * fb)3164 drm_virtual_output_buffer_released(struct drm_fb *fb)
3165 {
3166 drm_fb_unref(fb);
3167 }
3168
3169 static void
drm_virtual_output_finish_frame(struct weston_output * output_base,struct timespec * stamp,uint32_t presented_flags)3170 drm_virtual_output_finish_frame(struct weston_output *output_base,
3171 struct timespec *stamp,
3172 uint32_t presented_flags)
3173 {
3174 struct drm_output *output = to_drm_output(output_base);
3175 struct drm_plane_state *ps;
3176
3177 wl_list_for_each(ps, &output->state_cur->plane_list, link)
3178 ps->complete = true;
3179
3180 drm_output_state_free(output->state_last);
3181 output->state_last = NULL;
3182
3183 weston_output_finish_frame(&output->base, stamp, presented_flags);
3184
3185 /* We can't call this from frame_notify, because the output's
3186 * repaint needed flag is cleared just after that */
3187 if (output->recorder)
3188 weston_output_schedule_repaint(&output->base);
3189 }
3190
3191 static const struct weston_drm_output_api api = {
3192 drm_output_set_mode,
3193 drm_output_set_gbm_format,
3194 drm_output_set_seat,
3195 };
3196
3197 static const struct weston_drm_virtual_output_api virt_api = {
3198 drm_virtual_output_create,
3199 drm_virtual_output_set_gbm_format,
3200 drm_virtual_output_set_submit_frame_cb,
3201 drm_virtual_output_get_fence_fd,
3202 drm_virtual_output_buffer_released,
3203 drm_virtual_output_finish_frame
3204 };
3205
3206 static struct drm_backend *
drm_backend_create(struct weston_compositor * compositor,struct weston_drm_backend_config * config)3207 drm_backend_create(struct weston_compositor *compositor,
3208 struct weston_drm_backend_config *config)
3209 {
3210 struct drm_backend *b;
3211 struct udev_device *drm_device;
3212 struct wl_event_loop *loop;
3213 const char *seat_id = default_seat;
3214 const char *session_seat;
3215 int ret;
3216
3217 session_seat = getenv("XDG_SEAT");
3218 if (session_seat)
3219 seat_id = session_seat;
3220
3221 if (config->seat_id)
3222 seat_id = config->seat_id;
3223
3224 weston_log("initializing drm backend\n");
3225
3226 b = zalloc(sizeof *b);
3227 if (b == NULL)
3228 return NULL;
3229
3230 b->state_invalid = true;
3231 b->drm.fd = -1;
3232 wl_array_init(&b->unused_crtcs);
3233
3234 b->compositor = compositor;
3235 b->use_pixman = config->use_pixman;
3236 b->pageflip_timeout = config->pageflip_timeout;
3237 b->use_pixman_shadow = config->use_pixman_shadow;
3238
3239 b->debug = weston_compositor_add_log_scope(compositor->weston_log_ctx,
3240 "drm-backend",
3241 "Debug messages from DRM/KMS backend\n",
3242 NULL, NULL);
3243
3244 compositor->backend = &b->base;
3245
3246 if (parse_gbm_format(config->gbm_format, DRM_FORMAT_XRGB8888, &b->gbm_format) < 0)
3247 goto err_compositor;
3248
3249 /* Check if we run drm-backend using weston-launch */
3250 compositor->launcher = weston_launcher_connect(compositor, config->tty,
3251 seat_id, true);
3252 if (compositor->launcher == NULL) {
3253 weston_log("fatal: drm backend should be run using "
3254 "weston-launch binary, or your system should "
3255 "provide the logind D-Bus API.\n");
3256 goto err_compositor;
3257 }
3258
3259 b->udev = udev_new();
3260 if (b->udev == NULL) {
3261 weston_log("failed to initialize udev context\n");
3262 goto err_launcher;
3263 }
3264
3265 b->session_listener.notify = session_notify;
3266 wl_signal_add(&compositor->session_signal, &b->session_listener);
3267
3268 if (config->specific_device)
3269 drm_device = open_specific_drm_device(b, config->specific_device);
3270 else
3271 drm_device = find_primary_gpu(b, seat_id);
3272 if (drm_device == NULL) {
3273 weston_log("no drm device found\n");
3274 goto err_udev;
3275 }
3276
3277 if (init_kms_caps(b) < 0) {
3278 weston_log("failed to initialize kms\n");
3279 goto err_udev_dev;
3280 }
3281
3282 if (b->use_pixman) {
3283 if (init_pixman(b) < 0) {
3284 weston_log("failed to initialize pixman renderer\n");
3285 goto err_udev_dev;
3286 }
3287 } else {
3288 if (init_egl(b) < 0) {
3289 weston_log("failed to initialize egl\n");
3290 goto err_udev_dev;
3291 }
3292 }
3293
3294 b->base.destroy = drm_destroy;
3295 b->base.repaint_begin = drm_repaint_begin;
3296 b->base.repaint_flush = drm_repaint_flush;
3297 b->base.repaint_cancel = drm_repaint_cancel;
3298 b->base.create_output = drm_output_create;
3299 b->base.device_changed = drm_device_changed;
3300
3301 weston_setup_vt_switch_bindings(compositor);
3302
3303 wl_list_init(&b->plane_list);
3304 create_sprites(b);
3305
3306 if (udev_input_init(&b->input,
3307 compositor, b->udev, seat_id,
3308 config->configure_device) < 0) {
3309 weston_log("failed to create input devices\n");
3310 goto err_sprite;
3311 }
3312
3313 if (drm_backend_create_heads(b, drm_device) < 0) {
3314 weston_log("Failed to create heads for %s\n", b->drm.filename);
3315 goto err_udev_input;
3316 }
3317
3318 /* A this point we have some idea of whether or not we have a working
3319 * cursor plane. */
3320 if (!b->cursors_are_broken)
3321 compositor->capabilities |= WESTON_CAP_CURSOR_PLANE;
3322
3323 loop = wl_display_get_event_loop(compositor->wl_display);
3324 b->drm_source =
3325 wl_event_loop_add_fd(loop, b->drm.fd,
3326 WL_EVENT_READABLE, on_drm_input, b);
3327
3328 b->udev_monitor = udev_monitor_new_from_netlink(b->udev, "udev");
3329 if (b->udev_monitor == NULL) {
3330 weston_log("failed to initialize udev monitor\n");
3331 goto err_drm_source;
3332 }
3333 udev_monitor_filter_add_match_subsystem_devtype(b->udev_monitor,
3334 "drm", NULL);
3335 b->udev_drm_source =
3336 wl_event_loop_add_fd(loop,
3337 udev_monitor_get_fd(b->udev_monitor),
3338 WL_EVENT_READABLE, udev_drm_event, b);
3339
3340 if (udev_monitor_enable_receiving(b->udev_monitor) < 0) {
3341 weston_log("failed to enable udev-monitor receiving\n");
3342 goto err_udev_monitor;
3343 }
3344
3345 udev_device_unref(drm_device);
3346
3347 weston_compositor_add_debug_binding(compositor, KEY_O,
3348 planes_binding, b);
3349 weston_compositor_add_debug_binding(compositor, KEY_C,
3350 planes_binding, b);
3351 weston_compositor_add_debug_binding(compositor, KEY_V,
3352 planes_binding, b);
3353 weston_compositor_add_debug_binding(compositor, KEY_Q,
3354 recorder_binding, b);
3355 weston_compositor_add_debug_binding(compositor, KEY_W,
3356 renderer_switch_binding, b);
3357
3358 if (compositor->renderer->import_dmabuf) {
3359 if (linux_dmabuf_setup(compositor) < 0)
3360 weston_log("Error: initializing dmabuf "
3361 "support failed.\n");
3362 }
3363
3364 if (compositor->capabilities & WESTON_CAP_EXPLICIT_SYNC) {
3365 if (linux_explicit_synchronization_setup(compositor) < 0)
3366 weston_log("Error: initializing explicit "
3367 " synchronization support failed.\n");
3368 }
3369
3370 ret = weston_plugin_api_register(compositor, WESTON_DRM_OUTPUT_API_NAME,
3371 &api, sizeof(api));
3372
3373 if (ret < 0) {
3374 weston_log("Failed to register output API.\n");
3375 goto err_udev_monitor;
3376 }
3377
3378 ret = weston_plugin_api_register(compositor,
3379 WESTON_DRM_VIRTUAL_OUTPUT_API_NAME,
3380 &virt_api, sizeof(virt_api));
3381 if (ret < 0) {
3382 weston_log("Failed to register virtual output API.\n");
3383 goto err_udev_monitor;
3384 }
3385
3386 return b;
3387
3388 err_udev_monitor:
3389 wl_event_source_remove(b->udev_drm_source);
3390 udev_monitor_unref(b->udev_monitor);
3391 err_drm_source:
3392 wl_event_source_remove(b->drm_source);
3393 err_udev_input:
3394 udev_input_destroy(&b->input);
3395 err_sprite:
3396 if (b->gbm)
3397 gbm_device_destroy(b->gbm);
3398 destroy_sprites(b);
3399 err_udev_dev:
3400 udev_device_unref(drm_device);
3401 err_launcher:
3402 weston_launcher_destroy(compositor->launcher);
3403 err_udev:
3404 udev_unref(b->udev);
3405 err_compositor:
3406 weston_compositor_shutdown(compositor);
3407 free(b);
3408 return NULL;
3409 }
3410
3411 static void
config_init_to_defaults(struct weston_drm_backend_config * config)3412 config_init_to_defaults(struct weston_drm_backend_config *config)
3413 {
3414 config->use_pixman_shadow = true;
3415 }
3416
3417 WL_EXPORT int
weston_backend_init(struct weston_compositor * compositor,struct weston_backend_config * config_base)3418 weston_backend_init(struct weston_compositor *compositor,
3419 struct weston_backend_config *config_base)
3420 {
3421 struct drm_backend *b;
3422 struct weston_drm_backend_config config = {{ 0, }};
3423
3424 if (config_base == NULL ||
3425 config_base->struct_version != WESTON_DRM_BACKEND_CONFIG_VERSION ||
3426 config_base->struct_size > sizeof(struct weston_drm_backend_config)) {
3427 weston_log("drm backend config structure is invalid\n");
3428 return -1;
3429 }
3430
3431 config_init_to_defaults(&config);
3432 memcpy(&config, config_base, config_base->struct_size);
3433
3434 b = drm_backend_create(compositor, &config);
3435 if (b == NULL)
3436 return -1;
3437
3438 return 0;
3439 }
3440