blob: 85eb783ab38f8aa7f7fbc9993d4cef95e615eb3e [file] [log] [blame]
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001/*
Kristian Høgsberg96aa7da2011-09-15 15:43:14 -04002 * Copyright © 2008-2011 Kristian Høgsberg
3 * Copyright © 2011 Intel Corporation
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04004 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07005 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040012 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070013 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040025 */
26
Daniel Stonec228e232013-05-22 18:03:19 +030027#include "config.h"
Kristian Høgsberg0b9334a2011-04-12 11:34:32 -040028
Jesse Barnes58ef3792012-02-23 09:45:49 -050029#include <errno.h>
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040030#include <stdlib.h>
Richard Hughes2b2092a2013-04-24 14:58:02 +010031#include <ctype.h>
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040032#include <string.h>
33#include <fcntl.h>
34#include <unistd.h>
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -040035#include <linux/input.h>
Kristian Høgsberg3f495872013-09-18 23:00:17 -070036#include <linux/vt.h>
Ander Conselvan de Oliveirafd1f4c62012-06-26 17:09:14 +030037#include <assert.h>
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +020038#include <sys/mman.h>
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +030039#include <dlfcn.h>
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +030040#include <time.h>
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040041
Benjamin Franzkec649a922011-03-02 11:56:04 +010042#include <xf86drm.h>
43#include <xf86drmMode.h>
Jesse Barnes58ef3792012-02-23 09:45:49 -050044#include <drm_fourcc.h>
Benjamin Franzkec649a922011-03-02 11:56:04 +010045
Benjamin Franzke060cf802011-04-30 09:32:11 +020046#include <gbm.h>
Pekka Paalanen33156972012-08-03 13:30:30 -040047#include <libudev.h>
Benjamin Franzke060cf802011-04-30 09:32:11 +020048
Jon Cruz35b2eaa2015-06-15 15:37:08 -070049#include "shared/helpers.h"
Kristian Høgsberg36d5fac2014-01-27 23:02:35 -080050#include "libbacklight.h"
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040051#include "compositor.h"
John Kåre Alsaker30d2b1f2012-11-13 19:10:28 +010052#include "gl-renderer.h"
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +020053#include "pixman-renderer.h"
Peter Hutterer823ad332014-11-26 07:06:31 +100054#include "libinput-seat.h"
Benjamin Franzkebfeda132012-01-30 14:04:04 +010055#include "launcher-util.h"
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +030056#include "vaapi-recorder.h"
Pekka Paalanen363aa7b2014-12-17 16:20:40 +020057#include "presentation_timing-server-protocol.h"
Kristian Høgsbergfc783d42010-06-11 12:56:24 -040058
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +030059#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
60#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
61#endif
62
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -030063#ifndef DRM_CAP_CURSOR_WIDTH
64#define DRM_CAP_CURSOR_WIDTH 0x8
65#endif
66
67#ifndef DRM_CAP_CURSOR_HEIGHT
68#define DRM_CAP_CURSOR_HEIGHT 0x9
69#endif
70
71#ifndef GBM_BO_USE_CURSOR
72#define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64
73#endif
74
Kristian Høgsberg061c4252012-06-28 11:28:15 -040075static int option_current_mode = 0;
Scott Moreau8ab5d452012-07-30 19:51:08 -060076
77enum output_config {
78 OUTPUT_CONFIG_INVALID = 0,
79 OUTPUT_CONFIG_OFF,
80 OUTPUT_CONFIG_PREFERRED,
81 OUTPUT_CONFIG_CURRENT,
Scott Moreau8f37e0b2012-07-31 15:30:41 -060082 OUTPUT_CONFIG_MODE,
83 OUTPUT_CONFIG_MODELINE
Scott Moreau8ab5d452012-07-30 19:51:08 -060084};
85
Giulio Camuffo954f1832014-10-11 18:27:30 +030086struct drm_backend {
87 struct weston_backend base;
88 struct weston_compositor *compositor;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -040089
90 struct udev *udev;
91 struct wl_event_source *drm_source;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -040092
Benjamin Franzke9c26ff32011-03-15 15:08:41 +010093 struct udev_monitor *udev_monitor;
94 struct wl_event_source *udev_drm_source;
95
Benjamin Franzke2af7f102011-03-02 11:14:59 +010096 struct {
David Herrmannd7488c22012-03-11 20:05:21 +010097 int id;
Benjamin Franzke2af7f102011-03-02 11:14:59 +010098 int fd;
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +030099 char *filename;
Benjamin Franzke2af7f102011-03-02 11:14:59 +0100100 } drm;
Benjamin Franzke060cf802011-04-30 09:32:11 +0200101 struct gbm_device *gbm;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500102 uint32_t *crtcs;
103 int num_crtcs;
Marty Jack13d9db22011-02-09 19:01:42 -0500104 uint32_t crtc_allocator;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +0100105 uint32_t connector_allocator;
Kristian Høgsberg61741a22013-09-17 16:02:57 -0700106 struct wl_listener session_listener;
Kristian Høgsbergc3ea26c2013-09-25 15:46:42 -0700107 uint32_t format;
Pekka Paalanenbce2d3f2011-12-02 13:07:27 +0200108
Rob Clark4339add2012-08-09 14:18:28 -0500109 /* we need these parameters in order to not fail drmModeAddFB2()
110 * due to out of bounds dimensions, and then mistakenly set
111 * sprites_are_broken:
112 */
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200113 uint32_t min_width, max_width;
114 uint32_t min_height, max_height;
115 int no_addfb2;
Rob Clark4339add2012-08-09 14:18:28 -0500116
Jesse Barnes58ef3792012-02-23 09:45:49 -0500117 struct wl_list sprite_list;
Kristian Høgsberg65bec242012-03-05 19:57:35 -0500118 int sprites_are_broken;
Ander Conselvan de Oliveirada1c9082012-10-31 17:55:46 +0200119 int sprites_hidden;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500120
Rob Clarkab5b1e32012-08-09 13:24:45 -0500121 int cursors_are_broken;
122
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200123 int use_pixman;
124
Pekka Paalanenbce2d3f2011-12-02 13:07:27 +0200125 uint32_t prev_state;
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +0300126
Rob Bradfordd355b802013-05-31 18:09:55 +0100127 struct udev_input input;
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -0300128
129 uint32_t cursor_width;
130 uint32_t cursor_height;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -0400131};
132
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400133struct drm_mode {
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500134 struct weston_mode base;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400135 drmModeModeInfo mode_info;
136};
137
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300138struct drm_output;
139
140struct drm_fb {
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300141 struct drm_output *output;
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200142 uint32_t fb_id, stride, handle, size;
143 int fd;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300144 int is_client_buffer;
Pekka Paalanende685b82012-12-04 15:58:12 +0200145 struct weston_buffer_reference buffer_ref;
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200146
147 /* Used by gbm fbs */
148 struct gbm_bo *bo;
149
150 /* Used by dumb fbs */
151 void *map;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300152};
153
Richard Hughes2b2092a2013-04-24 14:58:02 +0100154struct drm_edid {
155 char eisa_id[13];
156 char monitor_name[13];
157 char pnp_id[5];
158 char serial_number[13];
159};
160
Kristian Høgsbergce5325d2010-06-14 11:54:00 -0400161struct drm_output {
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500162 struct weston_output base;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -0400163
Kristian Høgsbergce5325d2010-06-14 11:54:00 -0400164 uint32_t crtc_id;
Rob Clark5ca1a472012-08-08 20:27:37 -0500165 int pipe;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -0400166 uint32_t connector_id;
Matt Roper361d2ad2011-08-29 13:52:23 -0700167 drmModeCrtcPtr original_crtc;
Richard Hughes2b2092a2013-04-24 14:58:02 +0100168 struct drm_edid edid;
Ander Conselvan de Oliveiraa0a433a2013-06-04 16:24:04 +0300169 drmModePropertyPtr dpms_prop;
Neil Roberts77c1a5b2014-03-07 18:05:50 +0000170 uint32_t format;
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200171
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300172 int vblank_pending;
173 int page_flip_pending;
Xiong Zhangabd5d472013-10-11 14:43:07 +0800174 int destroy_pending;
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300175
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400176 struct gbm_surface *surface;
Kristian Høgsberg8e1f77f2012-05-03 11:39:35 -0400177 struct gbm_bo *cursor_bo[2];
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400178 struct weston_plane cursor_plane;
179 struct weston_plane fb_plane;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500180 struct weston_view *cursor_view;
Kristian Høgsberg5626d342012-08-03 11:50:05 -0400181 int current_cursor;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300182 struct drm_fb *current, *next;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +0200183 struct backlight *backlight;
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200184
185 struct drm_fb *dumb[2];
186 pixman_image_t *image[2];
187 int current_image;
188 pixman_region32_t previous_damage;
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +0300189
190 struct vaapi_recorder *recorder;
191 struct wl_listener recorder_frame_listener;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -0400192};
193
Jesse Barnes58ef3792012-02-23 09:45:49 -0500194/*
195 * An output has a primary display plane plus zero or more sprites for
196 * blending display contents.
197 */
198struct drm_sprite {
199 struct wl_list link;
200
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400201 struct weston_plane plane;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500202
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200203 struct drm_fb *current, *next;
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300204 struct drm_output *output;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300205 struct drm_backend *backend;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500206
Jesse Barnes58ef3792012-02-23 09:45:49 -0500207 uint32_t possible_crtcs;
208 uint32_t plane_id;
209 uint32_t count_formats;
210
211 int32_t src_x, src_y;
212 uint32_t src_w, src_h;
213 uint32_t dest_x, dest_y;
214 uint32_t dest_w, dest_h;
215
216 uint32_t formats[];
217};
218
Kristian Høgsbergd8e98332013-10-16 16:15:11 -0700219struct drm_parameters {
220 int connector;
221 int tty;
222 int use_pixman;
223 const char *seat_id;
224};
225
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +0300226static struct gl_renderer_interface *gl_renderer;
227
Kristian Høgsberg98cfea62013-02-18 16:15:53 -0500228static const char default_seat[] = "seat0";
Pekka Paalanen33156972012-08-03 13:30:30 -0400229
Kristian Høgsberg5626d342012-08-03 11:50:05 -0400230static void
231drm_output_set_cursor(struct drm_output *output);
Kristian Høgsberg5626d342012-08-03 11:50:05 -0400232
Jesse Barnes58ef3792012-02-23 09:45:49 -0500233static int
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200234drm_sprite_crtc_supported(struct drm_output *output, uint32_t supported)
Jesse Barnes58ef3792012-02-23 09:45:49 -0500235{
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200236 struct weston_compositor *ec = output->base.compositor;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300237 struct drm_backend *b =(struct drm_backend *)ec->backend;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500238 int crtc;
239
Giulio Camuffo954f1832014-10-11 18:27:30 +0300240 for (crtc = 0; crtc < b->num_crtcs; crtc++) {
241 if (b->crtcs[crtc] != output->crtc_id)
Jesse Barnes58ef3792012-02-23 09:45:49 -0500242 continue;
243
244 if (supported & (1 << crtc))
245 return -1;
246 }
247
248 return 0;
249}
250
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300251static void
252drm_fb_destroy_callback(struct gbm_bo *bo, void *data)
253{
254 struct drm_fb *fb = data;
255 struct gbm_device *gbm = gbm_bo_get_device(bo);
256
257 if (fb->fb_id)
258 drmModeRmFB(gbm_device_get_fd(gbm), fb->fb_id);
259
Pekka Paalanende685b82012-12-04 15:58:12 +0200260 weston_buffer_reference(&fb->buffer_ref, NULL);
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300261
262 free(data);
263}
264
265static struct drm_fb *
Giulio Camuffo954f1832014-10-11 18:27:30 +0300266drm_fb_create_dumb(struct drm_backend *b, unsigned width, unsigned height)
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200267{
268 struct drm_fb *fb;
269 int ret;
270
271 struct drm_mode_create_dumb create_arg;
272 struct drm_mode_destroy_dumb destroy_arg;
273 struct drm_mode_map_dumb map_arg;
274
Peter Huttererf3d62272013-08-08 11:57:05 +1000275 fb = zalloc(sizeof *fb);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200276 if (!fb)
277 return NULL;
278
Kristian Høgsbergac6104e2013-08-21 22:14:14 -0700279 memset(&create_arg, 0, sizeof create_arg);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200280 create_arg.bpp = 32;
281 create_arg.width = width;
282 create_arg.height = height;
283
Giulio Camuffo954f1832014-10-11 18:27:30 +0300284 ret = drmIoctl(b->drm.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200285 if (ret)
286 goto err_fb;
287
288 fb->handle = create_arg.handle;
289 fb->stride = create_arg.pitch;
290 fb->size = create_arg.size;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300291 fb->fd = b->drm.fd;
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200292
Giulio Camuffo954f1832014-10-11 18:27:30 +0300293 ret = drmModeAddFB(b->drm.fd, width, height, 24, 32,
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200294 fb->stride, fb->handle, &fb->fb_id);
295 if (ret)
296 goto err_bo;
297
Kristian Høgsbergac6104e2013-08-21 22:14:14 -0700298 memset(&map_arg, 0, sizeof map_arg);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200299 map_arg.handle = fb->handle;
Chris Michaeleb2074a2013-05-01 21:26:02 -0400300 ret = drmIoctl(fb->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_arg);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200301 if (ret)
302 goto err_add_fb;
303
304 fb->map = mmap(0, fb->size, PROT_WRITE,
Giulio Camuffo954f1832014-10-11 18:27:30 +0300305 MAP_SHARED, b->drm.fd, map_arg.offset);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200306 if (fb->map == MAP_FAILED)
307 goto err_add_fb;
308
309 return fb;
310
311err_add_fb:
Giulio Camuffo954f1832014-10-11 18:27:30 +0300312 drmModeRmFB(b->drm.fd, fb->fb_id);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200313err_bo:
314 memset(&destroy_arg, 0, sizeof(destroy_arg));
315 destroy_arg.handle = create_arg.handle;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300316 drmIoctl(b->drm.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200317err_fb:
318 free(fb);
319 return NULL;
320}
321
322static void
323drm_fb_destroy_dumb(struct drm_fb *fb)
324{
325 struct drm_mode_destroy_dumb destroy_arg;
326
327 if (!fb->map)
328 return;
329
330 if (fb->fb_id)
331 drmModeRmFB(fb->fd, fb->fb_id);
332
333 weston_buffer_reference(&fb->buffer_ref, NULL);
334
335 munmap(fb->map, fb->size);
336
337 memset(&destroy_arg, 0, sizeof(destroy_arg));
338 destroy_arg.handle = fb->handle;
339 drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
340
341 free(fb);
342}
343
344static struct drm_fb *
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500345drm_fb_get_from_bo(struct gbm_bo *bo,
Giulio Camuffo954f1832014-10-11 18:27:30 +0300346 struct drm_backend *backend, uint32_t format)
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300347{
348 struct drm_fb *fb = gbm_bo_get_user_data(bo);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200349 uint32_t width, height;
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200350 uint32_t handles[4], pitches[4], offsets[4];
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300351 int ret;
352
353 if (fb)
354 return fb;
355
Bryce Harringtonde16d892014-11-20 22:21:57 -0800356 fb = zalloc(sizeof *fb);
357 if (fb == NULL)
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200358 return NULL;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300359
360 fb->bo = bo;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300361
362 width = gbm_bo_get_width(bo);
363 height = gbm_bo_get_height(bo);
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200364 fb->stride = gbm_bo_get_stride(bo);
365 fb->handle = gbm_bo_get_handle(bo).u32;
366 fb->size = fb->stride * height;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300367 fb->fd = backend->drm.fd;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300368
Giulio Camuffo954f1832014-10-11 18:27:30 +0300369 if (backend->min_width > width || width > backend->max_width ||
370 backend->min_height > height ||
371 height > backend->max_height) {
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200372 weston_log("bo geometry out of bounds\n");
373 goto err_free;
374 }
375
376 ret = -1;
377
Giulio Camuffo954f1832014-10-11 18:27:30 +0300378 if (format && !backend->no_addfb2) {
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200379 handles[0] = fb->handle;
380 pitches[0] = fb->stride;
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200381 offsets[0] = 0;
382
Giulio Camuffo954f1832014-10-11 18:27:30 +0300383 ret = drmModeAddFB2(backend->drm.fd, width, height,
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200384 format, handles, pitches, offsets,
385 &fb->fb_id, 0);
386 if (ret) {
387 weston_log("addfb2 failed: %m\n");
Giulio Camuffo954f1832014-10-11 18:27:30 +0300388 backend->no_addfb2 = 1;
389 backend->sprites_are_broken = 1;
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200390 }
391 }
392
393 if (ret)
Giulio Camuffo954f1832014-10-11 18:27:30 +0300394 ret = drmModeAddFB(backend->drm.fd, width, height, 24, 32,
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200395 fb->stride, fb->handle, &fb->fb_id);
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200396
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300397 if (ret) {
Martin Minarik6d118362012-06-07 18:01:59 +0200398 weston_log("failed to create kms fb: %m\n");
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200399 goto err_free;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300400 }
401
402 gbm_bo_set_user_data(bo, fb, drm_fb_destroy_callback);
403
404 return fb;
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200405
406err_free:
407 free(fb);
408 return NULL;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300409}
410
411static void
Jason Ekstrand6bd62942013-06-20 20:38:23 -0500412drm_fb_set_buffer(struct drm_fb *fb, struct weston_buffer *buffer)
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200413{
Pekka Paalanende685b82012-12-04 15:58:12 +0200414 assert(fb->buffer_ref.buffer == NULL);
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200415
416 fb->is_client_buffer = 1;
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200417
Pekka Paalanende685b82012-12-04 15:58:12 +0200418 weston_buffer_reference(&fb->buffer_ref, buffer);
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200419}
420
Ander Conselvan de Oliveira526d4612013-01-25 15:13:03 +0200421static void
422drm_output_release_fb(struct drm_output *output, struct drm_fb *fb)
423{
424 if (!fb)
425 return;
426
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200427 if (fb->map &&
428 (fb != output->dumb[0] && fb != output->dumb[1])) {
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +0200429 drm_fb_destroy_dumb(fb);
430 } else if (fb->bo) {
Ander Conselvan de Oliveira526d4612013-01-25 15:13:03 +0200431 if (fb->is_client_buffer)
432 gbm_bo_destroy(fb->bo);
433 else
434 gbm_surface_release_buffer(output->surface,
Jason Ekstrand3ec57f52013-11-14 20:52:35 -0600435 fb->bo);
Ander Conselvan de Oliveira526d4612013-01-25 15:13:03 +0200436 }
437}
438
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500439static uint32_t
Ander Conselvan de Oliveirae9209412012-11-30 17:34:22 +0200440drm_output_check_scanout_format(struct drm_output *output,
441 struct weston_surface *es, struct gbm_bo *bo)
442{
Ander Conselvan de Oliveirae9209412012-11-30 17:34:22 +0200443 uint32_t format;
444 pixman_region32_t r;
445
446 format = gbm_bo_get_format(bo);
447
Kristian Høgsberg3f97b342013-10-16 16:08:57 -0700448 if (format == GBM_FORMAT_ARGB8888) {
449 /* We can scanout an ARGB buffer if the surface's
450 * opaque region covers the whole output, but we have
451 * to use XRGB as the KMS format code. */
Kristian Høgsberg1be87e32014-01-17 14:22:41 -0800452 pixman_region32_init_rect(&r, 0, 0,
453 output->base.width,
454 output->base.height);
455 pixman_region32_subtract(&r, &r, &es->opaque);
Ander Conselvan de Oliveirae9209412012-11-30 17:34:22 +0200456
457 if (!pixman_region32_not_empty(&r))
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500458 format = GBM_FORMAT_XRGB8888;
Ander Conselvan de Oliveirae9209412012-11-30 17:34:22 +0200459
460 pixman_region32_fini(&r);
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500461 }
Kristian Høgsberg3f97b342013-10-16 16:08:57 -0700462
Neil Roberts77c1a5b2014-03-07 18:05:50 +0000463 if (output->format == format)
Kristian Høgsberg3f97b342013-10-16 16:08:57 -0700464 return format;
465
466 return 0;
Ander Conselvan de Oliveirae9209412012-11-30 17:34:22 +0200467}
468
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400469static struct weston_plane *
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200470drm_output_prepare_scanout_view(struct drm_output *output,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500471 struct weston_view *ev)
Kristian Høgsberg5f5e42e2012-01-25 23:59:42 -0500472{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300473 struct drm_backend *b =
474 (struct drm_backend *)output->base.compositor->backend;
Jason Ekstranda7af7042013-10-12 22:38:11 -0500475 struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200476 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300477 struct gbm_bo *bo;
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500478 uint32_t format;
Kristian Høgsberg5f5e42e2012-01-25 23:59:42 -0500479
Jason Ekstranda7af7042013-10-12 22:38:11 -0500480 if (ev->geometry.x != output->base.x ||
481 ev->geometry.y != output->base.y ||
Giulio Camuffo954f1832014-10-11 18:27:30 +0300482 buffer == NULL || b->gbm == NULL ||
Hardeningff39efa2013-09-18 23:56:35 +0200483 buffer->width != output->base.current_mode->width ||
484 buffer->height != output->base.current_mode->height ||
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200485 output->base.transform != viewport->buffer.transform ||
Jason Ekstranda7af7042013-10-12 22:38:11 -0500486 ev->transform.enabled)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400487 return NULL;
Kristian Høgsberg5f5e42e2012-01-25 23:59:42 -0500488
Pekka Paalanen5580f222015-02-17 16:33:18 +0200489 if (ev->geometry.scissor_enabled)
490 return NULL;
491
Giulio Camuffo954f1832014-10-11 18:27:30 +0300492 bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
Kristian Høgsberg63996462013-09-03 22:27:08 -0700493 buffer->resource, GBM_BO_USE_SCANOUT);
Kristian Høgsberg5f5e42e2012-01-25 23:59:42 -0500494
Rob Bradford9b101872012-09-14 23:25:41 +0100495 /* Unable to use the buffer for scanout */
496 if (!bo)
497 return NULL;
498
Jason Ekstranda7af7042013-10-12 22:38:11 -0500499 format = drm_output_check_scanout_format(output, ev->surface, bo);
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500500 if (format == 0) {
Ander Conselvan de Oliveiraa64b15d2012-05-02 16:42:22 +0300501 gbm_bo_destroy(bo);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400502 return NULL;
Ander Conselvan de Oliveiraa64b15d2012-05-02 16:42:22 +0300503 }
504
Giulio Camuffo954f1832014-10-11 18:27:30 +0300505 output->next = drm_fb_get_from_bo(bo, b, format);
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300506 if (!output->next) {
507 gbm_bo_destroy(bo);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400508 return NULL;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300509 }
Kristian Høgsberg5f5e42e2012-01-25 23:59:42 -0500510
Pekka Paalanende685b82012-12-04 15:58:12 +0200511 drm_fb_set_buffer(output->next, buffer);
Kristian Høgsberg5f5e42e2012-01-25 23:59:42 -0500512
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400513 return &output->fb_plane;
Kristian Høgsberg5f5e42e2012-01-25 23:59:42 -0500514}
515
Kristian Høgsberg06cf6b02012-01-25 23:47:45 -0500516static void
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200517drm_output_render_gl(struct drm_output *output, pixman_region32_t *damage)
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400518{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300519 struct drm_backend *b =
520 (struct drm_backend *)output->base.compositor->backend;
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300521 struct gbm_bo *bo;
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400522
Giulio Camuffo954f1832014-10-11 18:27:30 +0300523 output->base.compositor->renderer->repaint_output(&output->base,
524 damage);
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400525
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300526 bo = gbm_surface_lock_front_buffer(output->surface);
527 if (!bo) {
Martin Minarik6d118362012-06-07 18:01:59 +0200528 weston_log("failed to lock front buffer: %m\n");
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400529 return;
530 }
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300531
Giulio Camuffo954f1832014-10-11 18:27:30 +0300532 output->next = drm_fb_get_from_bo(bo, b, output->format);
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300533 if (!output->next) {
Martin Minarik6d118362012-06-07 18:01:59 +0200534 weston_log("failed to get drm_fb for bo\n");
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300535 gbm_surface_release_buffer(output->surface, bo);
536 return;
537 }
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400538}
539
540static void
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200541drm_output_render_pixman(struct drm_output *output, pixman_region32_t *damage)
542{
543 struct weston_compositor *ec = output->base.compositor;
544 pixman_region32_t total_damage, previous_damage;
545
546 pixman_region32_init(&total_damage);
547 pixman_region32_init(&previous_damage);
548
549 pixman_region32_copy(&previous_damage, damage);
550
551 pixman_region32_union(&total_damage, damage, &output->previous_damage);
552 pixman_region32_copy(&output->previous_damage, &previous_damage);
553
554 output->current_image ^= 1;
555
556 output->next = output->dumb[output->current_image];
557 pixman_renderer_output_set_buffer(&output->base,
558 output->image[output->current_image]);
559
560 ec->renderer->repaint_output(&output->base, &total_damage);
561
562 pixman_region32_fini(&total_damage);
563 pixman_region32_fini(&previous_damage);
564}
565
566static void
567drm_output_render(struct drm_output *output, pixman_region32_t *damage)
568{
Giulio Camuffo954f1832014-10-11 18:27:30 +0300569 struct weston_compositor *c = output->base.compositor;
570 struct drm_backend *b = (struct drm_backend *)c->backend;
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200571
Giulio Camuffo954f1832014-10-11 18:27:30 +0300572 if (b->use_pixman)
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200573 drm_output_render_pixman(output, damage);
574 else
575 drm_output_render_gl(output, damage);
576
Giulio Camuffo954f1832014-10-11 18:27:30 +0300577 pixman_region32_subtract(&c->primary_plane.damage,
578 &c->primary_plane.damage, damage);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200579}
580
581static void
Richard Hughese7299962013-05-01 21:52:12 +0100582drm_output_set_gamma(struct weston_output *output_base,
583 uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
584{
585 int rc;
586 struct drm_output *output = (struct drm_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300587 struct drm_backend *backend =
588 (struct drm_backend *) output->base.compositor->backend;
Richard Hughese7299962013-05-01 21:52:12 +0100589
590 /* check */
591 if (output_base->gamma_size != size)
592 return;
593 if (!output->original_crtc)
594 return;
595
Giulio Camuffo954f1832014-10-11 18:27:30 +0300596 rc = drmModeCrtcSetGamma(backend->drm.fd,
Richard Hughese7299962013-05-01 21:52:12 +0100597 output->crtc_id,
598 size, r, g, b);
599 if (rc)
600 weston_log("set gamma failed: %m\n");
601}
602
Bryce Harringtonada4f072015-06-30 13:25:46 -0700603/* Determine the type of vblank synchronization to use for the output.
604 *
605 * The pipe parameter indicates which CRTC is in use. Knowing this, we
606 * can determine which vblank sequence type to use for it. Traditional
607 * cards had only two CRTCs, with CRTC 0 using no special flags, and
608 * CRTC 1 using DRM_VBLANK_SECONDARY. The first bit of the pipe
609 * parameter indicates this.
610 *
611 * Bits 1-5 of the pipe parameter are 5 bit wide pipe number between
612 * 0-31. If this is non-zero it indicates we're dealing with a
613 * multi-gpu situation and we need to calculate the vblank sync
614 * using DRM_BLANK_HIGH_CRTC_MASK.
615 */
Pekka Paalanenc8a1ff02015-07-02 15:06:08 +0300616static unsigned int
617drm_waitvblank_pipe(struct drm_output *output)
Mario Kleiner2ab4f4e2015-06-21 21:25:13 +0200618{
619 if (output->pipe > 1)
620 return (output->pipe << DRM_VBLANK_HIGH_CRTC_SHIFT) &
621 DRM_VBLANK_HIGH_CRTC_MASK;
622 else if (output->pipe > 0)
623 return DRM_VBLANK_SECONDARY;
624 else
625 return 0;
626}
627
David Herrmann1edf44c2013-10-22 17:11:26 +0200628static int
Kristian Høgsberg6ddcdae2012-02-28 22:31:58 -0500629drm_output_repaint(struct weston_output *output_base,
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400630 pixman_region32_t *damage)
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100631{
632 struct drm_output *output = (struct drm_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300633 struct drm_backend *backend =
634 (struct drm_backend *)output->base.compositor->backend;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500635 struct drm_sprite *s;
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400636 struct drm_mode *mode;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500637 int ret = 0;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100638
Xiong Zhangabd5d472013-10-11 14:43:07 +0800639 if (output->destroy_pending)
David Herrmann1edf44c2013-10-22 17:11:26 +0200640 return -1;
Xiong Zhangabd5d472013-10-11 14:43:07 +0800641
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300642 if (!output->next)
Kristian Høgsbergd7c17262012-09-05 21:54:15 -0400643 drm_output_render(output, damage);
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300644 if (!output->next)
David Herrmann1edf44c2013-10-22 17:11:26 +0200645 return -1;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +0100646
Hardeningff39efa2013-09-18 23:56:35 +0200647 mode = container_of(output->base.current_mode, struct drm_mode, base);
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +0200648 if (!output->current ||
649 output->current->stride != output->next->stride) {
Giulio Camuffo954f1832014-10-11 18:27:30 +0300650 ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300651 output->next->fb_id, 0, 0,
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400652 &output->connector_id, 1,
653 &mode->mode_info);
654 if (ret) {
Martin Minarik6d118362012-06-07 18:01:59 +0200655 weston_log("set mode failed: %m\n");
David Herrmann1edf44c2013-10-22 17:11:26 +0200656 goto err_pageflip;
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400657 }
Ander Conselvan de Oliveira722a2d52013-06-04 16:24:05 +0300658 output_base->set_dpms(output_base, WESTON_DPMS_ON);
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200659 }
660
Giulio Camuffo954f1832014-10-11 18:27:30 +0300661 if (drmModePageFlip(backend->drm.fd, output->crtc_id,
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +0300662 output->next->fb_id,
Kristian Høgsberg54f14c32012-01-18 11:47:41 -0500663 DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
Martin Minarik6d118362012-06-07 18:01:59 +0200664 weston_log("queueing pageflip failed: %m\n");
David Herrmann1edf44c2013-10-22 17:11:26 +0200665 goto err_pageflip;
Kristian Høgsberg54f14c32012-01-18 11:47:41 -0500666 }
Benjamin Franzkeec4d3422011-03-14 12:07:26 +0100667
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300668 output->page_flip_pending = 1;
669
Kristian Høgsberg5626d342012-08-03 11:50:05 -0400670 drm_output_set_cursor(output);
671
Jesse Barnes58ef3792012-02-23 09:45:49 -0500672 /*
673 * Now, update all the sprite surfaces
674 */
Giulio Camuffo954f1832014-10-11 18:27:30 +0300675 wl_list_for_each(s, &backend->sprite_list, link) {
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200676 uint32_t flags = 0, fb_id = 0;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500677 drmVBlank vbl = {
678 .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
679 .request.sequence = 1,
680 };
681
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200682 if ((!s->current && !s->next) ||
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200683 !drm_sprite_crtc_supported(output, s->possible_crtcs))
Jesse Barnes58ef3792012-02-23 09:45:49 -0500684 continue;
685
Giulio Camuffo954f1832014-10-11 18:27:30 +0300686 if (s->next && !backend->sprites_hidden)
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200687 fb_id = s->next->fb_id;
688
Giulio Camuffo954f1832014-10-11 18:27:30 +0300689 ret = drmModeSetPlane(backend->drm.fd, s->plane_id,
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200690 output->crtc_id, fb_id, flags,
Jesse Barnes58ef3792012-02-23 09:45:49 -0500691 s->dest_x, s->dest_y,
692 s->dest_w, s->dest_h,
693 s->src_x, s->src_y,
694 s->src_w, s->src_h);
695 if (ret)
Martin Minarik6d118362012-06-07 18:01:59 +0200696 weston_log("setplane failed: %d: %s\n",
Jesse Barnes58ef3792012-02-23 09:45:49 -0500697 ret, strerror(errno));
698
Mario Kleiner2ab4f4e2015-06-21 21:25:13 +0200699 vbl.request.type |= drm_waitvblank_pipe(output);
Rob Clark5ca1a472012-08-08 20:27:37 -0500700
Jesse Barnes58ef3792012-02-23 09:45:49 -0500701 /*
702 * Queue a vblank signal so we know when the surface
703 * becomes active on the display or has been replaced.
704 */
705 vbl.request.signal = (unsigned long)s;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300706 ret = drmWaitVBlank(backend->drm.fd, &vbl);
Jesse Barnes58ef3792012-02-23 09:45:49 -0500707 if (ret) {
Martin Minarik6d118362012-06-07 18:01:59 +0200708 weston_log("vblank event request failed: %d: %s\n",
Jesse Barnes58ef3792012-02-23 09:45:49 -0500709 ret, strerror(errno));
710 }
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300711
712 s->output = output;
713 output->vblank_pending = 1;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500714 }
715
David Herrmann1edf44c2013-10-22 17:11:26 +0200716 return 0;
717
718err_pageflip:
Kristian Høgsbergb3955b02014-01-23 16:25:06 -0800719 output->cursor_view = NULL;
David Herrmann1edf44c2013-10-22 17:11:26 +0200720 if (output->next) {
721 drm_output_release_fb(output, output->next);
722 output->next = NULL;
723 }
724
725 return -1;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -0400726}
727
728static void
Jonas Ådahle5a12252013-04-05 23:07:11 +0200729drm_output_start_repaint_loop(struct weston_output *output_base)
730{
731 struct drm_output *output = (struct drm_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300732 struct drm_backend *backend = (struct drm_backend *)
733 output_base->compositor->backend;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200734 uint32_t fb_id;
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +0300735 struct timespec ts;
736
Xiong Zhangabd5d472013-10-11 14:43:07 +0800737 if (output->destroy_pending)
738 return;
739
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +0300740 if (!output->current) {
741 /* We can't page flip if there's no mode set */
David Herrmann3c688c52013-10-22 17:11:25 +0200742 goto finish_frame;
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +0300743 }
744
745 fb_id = output->current->fb_id;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200746
Giulio Camuffo954f1832014-10-11 18:27:30 +0300747 if (drmModePageFlip(backend->drm.fd, output->crtc_id, fb_id,
Jonas Ådahle5a12252013-04-05 23:07:11 +0200748 DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
749 weston_log("queueing pageflip failed: %m\n");
David Herrmann3c688c52013-10-22 17:11:25 +0200750 goto finish_frame;
Jonas Ådahle5a12252013-04-05 23:07:11 +0200751 }
David Herrmann3c688c52013-10-22 17:11:25 +0200752
753 return;
754
755finish_frame:
756 /* if we cannot page-flip, immediately finish frame */
Giulio Camuffo954f1832014-10-11 18:27:30 +0300757 weston_compositor_read_presentation_clock(output_base->compositor, &ts);
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200758 weston_output_finish_frame(output_base, &ts,
759 PRESENTATION_FEEDBACK_INVALID);
Jonas Ådahle5a12252013-04-05 23:07:11 +0200760}
761
762static void
Pekka Paalanen641307c2014-09-23 22:08:47 -0400763drm_output_update_msc(struct drm_output *output, unsigned int seq)
764{
765 uint64_t msc_hi = output->base.msc >> 32;
766
767 if (seq < (output->base.msc & 0xffffffff))
768 msc_hi++;
769
770 output->base.msc = (msc_hi << 32) + seq;
771}
772
773static void
Jesse Barnes58ef3792012-02-23 09:45:49 -0500774vblank_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec,
775 void *data)
776{
777 struct drm_sprite *s = (struct drm_sprite *)data;
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300778 struct drm_output *output = s->output;
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400779 struct timespec ts;
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200780 uint32_t flags = PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
781 PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300782
Pekka Paalanen641307c2014-09-23 22:08:47 -0400783 drm_output_update_msc(output, frame);
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300784 output->vblank_pending = 0;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500785
Ander Conselvan de Oliveira526d4612013-01-25 15:13:03 +0200786 drm_output_release_fb(output, s->current);
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200787 s->current = s->next;
788 s->next = NULL;
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300789
790 if (!output->page_flip_pending) {
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400791 ts.tv_sec = sec;
792 ts.tv_nsec = usec * 1000;
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200793 weston_output_finish_frame(&output->base, &ts, flags);
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300794 }
Jesse Barnes58ef3792012-02-23 09:45:49 -0500795}
796
797static void
Xiong Zhangabd5d472013-10-11 14:43:07 +0800798drm_output_destroy(struct weston_output *output_base);
799
800static void
Kristian Høgsbergfc783d42010-06-11 12:56:24 -0400801page_flip_handler(int fd, unsigned int frame,
802 unsigned int sec, unsigned int usec, void *data)
803{
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200804 struct drm_output *output = (struct drm_output *) data;
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400805 struct timespec ts;
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200806 uint32_t flags = PRESENTATION_FEEDBACK_KIND_VSYNC |
807 PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
808 PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -0400809
Pekka Paalanen641307c2014-09-23 22:08:47 -0400810 drm_output_update_msc(output, frame);
811
Jonas Ådahle5a12252013-04-05 23:07:11 +0200812 /* We don't set page_flip_pending on start_repaint_loop, in that case
813 * we just want to page flip to the current buffer to get an accurate
814 * timestamp */
815 if (output->page_flip_pending) {
816 drm_output_release_fb(output, output->current);
817 output->current = output->next;
818 output->next = NULL;
819 }
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300820
Jonas Ådahle5a12252013-04-05 23:07:11 +0200821 output->page_flip_pending = 0;
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -0400822
Xiong Zhangabd5d472013-10-11 14:43:07 +0800823 if (output->destroy_pending)
824 drm_output_destroy(&output->base);
825 else if (!output->vblank_pending) {
Pekka Paalanenb5eedad2014-09-23 22:08:45 -0400826 ts.tv_sec = sec;
827 ts.tv_nsec = usec * 1000;
Pekka Paalanen363aa7b2014-12-17 16:20:40 +0200828 weston_output_finish_frame(&output->base, &ts, flags);
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +0300829
830 /* We can't call this from frame_notify, because the output's
831 * repaint needed flag is cleared just after that */
832 if (output->recorder)
833 weston_output_schedule_repaint(&output->base);
Ander Conselvan de Oliveiraa7326962012-06-26 17:09:13 +0300834 }
Benjamin Franzke1178a3c2011-04-10 16:49:52 +0200835}
836
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500837static uint32_t
838drm_output_check_sprite_format(struct drm_sprite *s,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500839 struct weston_view *ev, struct gbm_bo *bo)
Jesse Barnes58ef3792012-02-23 09:45:49 -0500840{
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500841 uint32_t i, format;
842
843 format = gbm_bo_get_format(bo);
844
845 if (format == GBM_FORMAT_ARGB8888) {
846 pixman_region32_t r;
847
Kristian Høgsberg63093a32013-03-01 14:29:16 -0500848 pixman_region32_init_rect(&r, 0, 0,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -0600849 ev->surface->width,
850 ev->surface->height);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500851 pixman_region32_subtract(&r, &r, &ev->surface->opaque);
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500852
853 if (!pixman_region32_not_empty(&r))
854 format = GBM_FORMAT_XRGB8888;
855
856 pixman_region32_fini(&r);
857 }
Jesse Barnes58ef3792012-02-23 09:45:49 -0500858
859 for (i = 0; i < s->count_formats; i++)
860 if (s->formats[i] == format)
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500861 return format;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500862
863 return 0;
864}
865
866static int
Jason Ekstranda7af7042013-10-12 22:38:11 -0500867drm_view_transform_supported(struct weston_view *ev)
Jesse Barnes58ef3792012-02-23 09:45:49 -0500868{
Jason Ekstranda7af7042013-10-12 22:38:11 -0500869 return !ev->transform.enabled ||
870 (ev->transform.matrix.type < WESTON_MATRIX_TRANSFORM_ROTATE);
Jesse Barnes58ef3792012-02-23 09:45:49 -0500871}
872
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400873static struct weston_plane *
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200874drm_output_prepare_overlay_view(struct drm_output *output,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500875 struct weston_view *ev)
Jesse Barnes58ef3792012-02-23 09:45:49 -0500876{
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200877 struct weston_compositor *ec = output->base.compositor;
Giulio Camuffo954f1832014-10-11 18:27:30 +0300878 struct drm_backend *b = (struct drm_backend *)ec->backend;
Pekka Paalanen952b6c82014-03-14 14:38:15 +0200879 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500880 struct drm_sprite *s;
881 int found = 0;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500882 struct gbm_bo *bo;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500883 pixman_region32_t dest_rect, src_rect;
Ander Conselvan de Oliveira409eebf2012-12-05 15:14:04 +0200884 pixman_box32_t *box, tbox;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500885 uint32_t format;
Kristian Høgsberg3b00bae2012-07-13 15:25:07 -0400886 wl_fixed_t sx1, sy1, sx2, sy2;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500887
Giulio Camuffo954f1832014-10-11 18:27:30 +0300888 if (b->gbm == NULL)
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +0200889 return NULL;
890
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200891 if (viewport->buffer.transform != output->base.transform)
Ander Conselvan de Oliveira2908a3d2012-11-27 17:03:43 +0200892 return NULL;
893
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200894 if (viewport->buffer.scale != output->base.current_scale)
Alexander Larssond9a7bb72013-05-22 14:41:39 +0200895 return NULL;
896
Giulio Camuffo954f1832014-10-11 18:27:30 +0300897 if (b->sprites_are_broken)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400898 return NULL;
Kristian Høgsberg65bec242012-03-05 19:57:35 -0500899
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200900 if (ev->output_mask != (1u << output->base.id))
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400901 return NULL;
Ander Conselvan de Oliveirad450b192012-06-26 17:09:12 +0300902
Jason Ekstranda7af7042013-10-12 22:38:11 -0500903 if (ev->surface->buffer_ref.buffer == NULL)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400904 return NULL;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500905
Jason Ekstranda7af7042013-10-12 22:38:11 -0500906 if (ev->alpha != 1.0f)
Ville Syrjälä5a84f312012-11-16 11:48:46 +0200907 return NULL;
908
Jason Ekstranda7af7042013-10-12 22:38:11 -0500909 if (wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource))
Rob Clark702ffae2012-08-09 14:18:27 -0500910 return NULL;
911
Jason Ekstranda7af7042013-10-12 22:38:11 -0500912 if (!drm_view_transform_supported(ev))
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400913 return NULL;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500914
Giulio Camuffo954f1832014-10-11 18:27:30 +0300915 wl_list_for_each(s, &b->sprite_list, link) {
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200916 if (!drm_sprite_crtc_supported(output, s->possible_crtcs))
Jesse Barnes58ef3792012-02-23 09:45:49 -0500917 continue;
918
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200919 if (!s->next) {
Jesse Barnes58ef3792012-02-23 09:45:49 -0500920 found = 1;
921 break;
922 }
923 }
924
925 /* No sprites available */
926 if (!found)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400927 return NULL;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500928
Giulio Camuffo954f1832014-10-11 18:27:30 +0300929 bo = gbm_bo_import(b->gbm, GBM_BO_IMPORT_WL_BUFFER,
Jason Ekstranda7af7042013-10-12 22:38:11 -0500930 ev->surface->buffer_ref.buffer->resource,
Kristian Høgsberg63996462013-09-03 22:27:08 -0700931 GBM_BO_USE_SCANOUT);
Kristian Høgsberg2763a2e2012-07-13 22:54:43 -0400932 if (!bo)
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400933 return NULL;
Kristian Høgsberg2763a2e2012-07-13 22:54:43 -0400934
Jason Ekstranda7af7042013-10-12 22:38:11 -0500935 format = drm_output_check_sprite_format(s, ev, bo);
Kristian Høgsberga2f84cc2012-12-07 12:37:58 -0500936 if (format == 0) {
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200937 gbm_bo_destroy(bo);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400938 return NULL;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500939 }
940
Giulio Camuffo954f1832014-10-11 18:27:30 +0300941 s->next = drm_fb_get_from_bo(bo, b, format);
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +0200942 if (!s->next) {
943 gbm_bo_destroy(bo);
944 return NULL;
945 }
946
Jason Ekstranda7af7042013-10-12 22:38:11 -0500947 drm_fb_set_buffer(s->next, ev->surface->buffer_ref.buffer);
Jesse Barnes58ef3792012-02-23 09:45:49 -0500948
Jason Ekstranda7af7042013-10-12 22:38:11 -0500949 box = pixman_region32_extents(&ev->transform.boundingbox);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -0400950 s->plane.x = box->x1;
951 s->plane.y = box->y1;
952
Jesse Barnes58ef3792012-02-23 09:45:49 -0500953 /*
954 * Calculate the source & dest rects properly based on actual
Derek Foreman4b1a0a12014-09-10 15:37:33 -0500955 * position (note the caller has called weston_view_update_transform()
Jesse Barnes58ef3792012-02-23 09:45:49 -0500956 * for us already).
957 */
958 pixman_region32_init(&dest_rect);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500959 pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox,
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200960 &output->base.region);
961 pixman_region32_translate(&dest_rect, -output->base.x, -output->base.y);
Jesse Barnes58ef3792012-02-23 09:45:49 -0500962 box = pixman_region32_extents(&dest_rect);
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200963 tbox = weston_transformed_rect(output->base.width,
964 output->base.height,
965 output->base.transform,
966 output->base.current_scale,
Alexander Larssond9a7bb72013-05-22 14:41:39 +0200967 *box);
Ander Conselvan de Oliveira409eebf2012-12-05 15:14:04 +0200968 s->dest_x = tbox.x1;
969 s->dest_y = tbox.y1;
970 s->dest_w = tbox.x2 - tbox.x1;
971 s->dest_h = tbox.y2 - tbox.y1;
Jesse Barnes58ef3792012-02-23 09:45:49 -0500972 pixman_region32_fini(&dest_rect);
973
974 pixman_region32_init(&src_rect);
Jason Ekstranda7af7042013-10-12 22:38:11 -0500975 pixman_region32_intersect(&src_rect, &ev->transform.boundingbox,
Pekka Paalanen050c1ba2014-12-17 16:20:38 +0200976 &output->base.region);
Jesse Barnes58ef3792012-02-23 09:45:49 -0500977 box = pixman_region32_extents(&src_rect);
Kristian Høgsberg3b00bae2012-07-13 15:25:07 -0400978
Jason Ekstranda7af7042013-10-12 22:38:11 -0500979 weston_view_from_global_fixed(ev,
980 wl_fixed_from_int(box->x1),
981 wl_fixed_from_int(box->y1),
982 &sx1, &sy1);
983 weston_view_from_global_fixed(ev,
984 wl_fixed_from_int(box->x2),
985 wl_fixed_from_int(box->y2),
986 &sx2, &sy2);
Kristian Høgsberg3b00bae2012-07-13 15:25:07 -0400987
988 if (sx1 < 0)
989 sx1 = 0;
990 if (sy1 < 0)
991 sy1 = 0;
Jason Ekstrand918f2dd2013-12-02 21:01:53 -0600992 if (sx2 > wl_fixed_from_int(ev->surface->width))
993 sx2 = wl_fixed_from_int(ev->surface->width);
994 if (sy2 > wl_fixed_from_int(ev->surface->height))
995 sy2 = wl_fixed_from_int(ev->surface->height);
Kristian Høgsberg3b00bae2012-07-13 15:25:07 -0400996
Ander Conselvan de Oliveira409eebf2012-12-05 15:14:04 +0200997 tbox.x1 = sx1;
998 tbox.y1 = sy1;
999 tbox.x2 = sx2;
1000 tbox.y2 = sy2;
1001
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001002 tbox = weston_transformed_rect(wl_fixed_from_int(ev->surface->width),
1003 wl_fixed_from_int(ev->surface->height),
Pekka Paalanen952b6c82014-03-14 14:38:15 +02001004 viewport->buffer.transform,
1005 viewport->buffer.scale,
Pekka Paalanen1fd9c0f2013-11-26 18:19:41 +01001006 tbox);
Ander Conselvan de Oliveira409eebf2012-12-05 15:14:04 +02001007
1008 s->src_x = tbox.x1 << 8;
1009 s->src_y = tbox.y1 << 8;
1010 s->src_w = (tbox.x2 - tbox.x1) << 8;
1011 s->src_h = (tbox.y2 - tbox.y1) << 8;
Jesse Barnes58ef3792012-02-23 09:45:49 -05001012 pixman_region32_fini(&src_rect);
1013
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001014 return &s->plane;
Jesse Barnes58ef3792012-02-23 09:45:49 -05001015}
1016
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001017static struct weston_plane *
Pekka Paalanen050c1ba2014-12-17 16:20:38 +02001018drm_output_prepare_cursor_view(struct drm_output *output,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001019 struct weston_view *ev)
Kristian Høgsbergd8bf90c2012-02-23 23:03:14 -05001020{
Giulio Camuffo954f1832014-10-11 18:27:30 +03001021 struct drm_backend *b =
1022 (struct drm_backend *)output->base.compositor->backend;
Neil Robertsf37f82c2014-05-01 18:00:41 +01001023 struct weston_buffer_viewport *viewport = &ev->surface->buffer_viewport;
Kristian Høgsberg5626d342012-08-03 11:50:05 -04001024
Giulio Camuffo954f1832014-10-11 18:27:30 +03001025 if (b->gbm == NULL)
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001026 return NULL;
Ander Conselvan de Oliveira2908a3d2012-11-27 17:03:43 +02001027 if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
1028 return NULL;
Pekka Paalanen050c1ba2014-12-17 16:20:38 +02001029 if (viewport->buffer.scale != output->base.current_scale)
Neil Robertsf37f82c2014-05-01 18:00:41 +01001030 return NULL;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001031 if (output->cursor_view)
Kristian Høgsberg5626d342012-08-03 11:50:05 -04001032 return NULL;
Pekka Paalanen050c1ba2014-12-17 16:20:38 +02001033 if (ev->output_mask != (1u << output->base.id))
Kristian Høgsberg5626d342012-08-03 11:50:05 -04001034 return NULL;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001035 if (b->cursors_are_broken)
Kristian Høgsberg8a015802012-08-09 17:19:23 -04001036 return NULL;
Pekka Paalanen5580f222015-02-17 16:33:18 +02001037 if (ev->geometry.scissor_enabled)
1038 return NULL;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001039 if (ev->surface->buffer_ref.buffer == NULL ||
1040 !wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource) ||
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001041 ev->surface->width > 64 || ev->surface->height > 64)
Kristian Høgsberg5626d342012-08-03 11:50:05 -04001042 return NULL;
1043
Jason Ekstranda7af7042013-10-12 22:38:11 -05001044 output->cursor_view = ev;
Kristian Høgsberg5626d342012-08-03 11:50:05 -04001045
1046 return &output->cursor_plane;
1047}
1048
1049static void
1050drm_output_set_cursor(struct drm_output *output)
1051{
Jason Ekstranda7af7042013-10-12 22:38:11 -05001052 struct weston_view *ev = output->cursor_view;
Neil Robertse5051712013-11-13 15:44:06 +00001053 struct weston_buffer *buffer;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001054 struct drm_backend *b =
1055 (struct drm_backend *) output->base.compositor->backend;
Kristian Høgsberga6edab32012-07-14 01:06:28 -04001056 EGLint handle, stride;
1057 struct gbm_bo *bo;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001058 uint32_t buf[b->cursor_width * b->cursor_height];
Kristian Høgsberga6edab32012-07-14 01:06:28 -04001059 unsigned char *s;
Kristian Høgsberg24e42752012-07-18 12:08:37 -04001060 int i, x, y;
Kristian Høgsbergd8bf90c2012-02-23 23:03:14 -05001061
Jason Ekstranda7af7042013-10-12 22:38:11 -05001062 output->cursor_view = NULL;
1063 if (ev == NULL) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03001064 drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
Kristian Høgsberg5626d342012-08-03 11:50:05 -04001065 return;
1066 }
Kristian Høgsbergd8bf90c2012-02-23 23:03:14 -05001067
Neil Robertse5051712013-11-13 15:44:06 +00001068 buffer = ev->surface->buffer_ref.buffer;
1069
1070 if (buffer &&
Pekka Paalanende685b82012-12-04 15:58:12 +02001071 pixman_region32_not_empty(&output->cursor_plane.damage)) {
Kristian Høgsberg5626d342012-08-03 11:50:05 -04001072 pixman_region32_fini(&output->cursor_plane.damage);
1073 pixman_region32_init(&output->cursor_plane.damage);
Kristian Høgsberg1f5de352012-07-18 12:09:58 -04001074 output->current_cursor ^= 1;
1075 bo = output->cursor_bo[output->current_cursor];
1076 memset(buf, 0, sizeof buf);
Neil Robertse5051712013-11-13 15:44:06 +00001077 stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
1078 s = wl_shm_buffer_get_data(buffer->shm_buffer);
1079 wl_shm_buffer_begin_access(buffer->shm_buffer);
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001080 for (i = 0; i < ev->surface->height; i++)
Giulio Camuffo954f1832014-10-11 18:27:30 +03001081 memcpy(buf + i * b->cursor_width, s + i * stride,
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001082 ev->surface->width * 4);
Neil Robertse5051712013-11-13 15:44:06 +00001083 wl_shm_buffer_end_access(buffer->shm_buffer);
Kristian Høgsbergd8bf90c2012-02-23 23:03:14 -05001084
Kristian Høgsberg1f5de352012-07-18 12:09:58 -04001085 if (gbm_bo_write(bo, buf, sizeof buf) < 0)
Pekka Paalanenae29da22012-08-06 14:57:05 +03001086 weston_log("failed update cursor: %m\n");
Kristian Høgsberga6edab32012-07-14 01:06:28 -04001087
Kristian Høgsberg1f5de352012-07-18 12:09:58 -04001088 handle = gbm_bo_get_handle(bo).s32;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001089 if (drmModeSetCursor(b->drm.fd, output->crtc_id, handle,
1090 b->cursor_width, b->cursor_height)) {
Pekka Paalanenae29da22012-08-06 14:57:05 +03001091 weston_log("failed to set cursor: %m\n");
Giulio Camuffo954f1832014-10-11 18:27:30 +03001092 b->cursors_are_broken = 1;
Rob Clarkab5b1e32012-08-09 13:24:45 -05001093 }
Kristian Høgsberga6edab32012-07-14 01:06:28 -04001094 }
1095
Jason Ekstranda7af7042013-10-12 22:38:11 -05001096 x = (ev->geometry.x - output->base.x) * output->base.current_scale;
1097 y = (ev->geometry.y - output->base.y) * output->base.current_scale;
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001098 if (output->cursor_plane.x != x || output->cursor_plane.y != y) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03001099 if (drmModeMoveCursor(b->drm.fd, output->crtc_id, x, y)) {
Kristian Høgsberg24e42752012-07-18 12:08:37 -04001100 weston_log("failed to move cursor: %m\n");
Giulio Camuffo954f1832014-10-11 18:27:30 +03001101 b->cursors_are_broken = 1;
Rob Clarkab5b1e32012-08-09 13:24:45 -05001102 }
1103
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001104 output->cursor_plane.x = x;
1105 output->cursor_plane.y = y;
Kristian Høgsberga6edab32012-07-14 01:06:28 -04001106 }
Kristian Høgsbergd8bf90c2012-02-23 23:03:14 -05001107}
1108
Jesse Barnes58ef3792012-02-23 09:45:49 -05001109static void
Pekka Paalanen050c1ba2014-12-17 16:20:38 +02001110drm_assign_planes(struct weston_output *output_base)
Jesse Barnes58ef3792012-02-23 09:45:49 -05001111{
Giulio Camuffo954f1832014-10-11 18:27:30 +03001112 struct drm_backend *b =
1113 (struct drm_backend *)output_base->compositor->backend;
Pekka Paalanen050c1ba2014-12-17 16:20:38 +02001114 struct drm_output *output = (struct drm_output *)output_base;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001115 struct weston_view *ev, *next;
Jesse Barnes58ef3792012-02-23 09:45:49 -05001116 pixman_region32_t overlap, surface_overlap;
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001117 struct weston_plane *primary, *next_plane;
Jesse Barnes58ef3792012-02-23 09:45:49 -05001118
1119 /*
1120 * Find a surface for each sprite in the output using some heuristics:
1121 * 1) size
1122 * 2) frequency of update
1123 * 3) opacity (though some hw might support alpha blending)
1124 * 4) clipping (this can be fixed with color keys)
1125 *
1126 * The idea is to save on blitting since this should save power.
1127 * If we can get a large video surface on the sprite for example,
1128 * the main display surface may not need to update at all, and
1129 * the client buffer can be used directly for the sprite surface
1130 * as we do for flipping full screen surfaces.
1131 */
1132 pixman_region32_init(&overlap);
Giulio Camuffo954f1832014-10-11 18:27:30 +03001133 primary = &output_base->compositor->primary_plane;
Jason Ekstranda7af7042013-10-12 22:38:11 -05001134
Giulio Camuffo954f1832014-10-11 18:27:30 +03001135 wl_list_for_each_safe(ev, next, &output_base->compositor->view_list, link) {
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001136 struct weston_surface *es = ev->surface;
1137
1138 /* Test whether this buffer can ever go into a plane:
1139 * non-shm, or small enough to be a cursor.
1140 *
1141 * Also, keep a reference when using the pixman renderer.
1142 * That makes it possible to do a seamless switch to the GL
1143 * renderer and since the pixman renderer keeps a reference
1144 * to the buffer anyway, there is no side effects.
Pekka Paalanenccfeae22012-12-04 15:58:14 +02001145 */
Giulio Camuffo954f1832014-10-11 18:27:30 +03001146 if (b->use_pixman ||
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001147 (es->buffer_ref.buffer &&
1148 (!wl_shm_buffer_get(es->buffer_ref.buffer->resource) ||
Jason Ekstrand918f2dd2013-12-02 21:01:53 -06001149 (ev->surface->width <= 64 && ev->surface->height <= 64))))
Derek Foreman0fd6d4e2014-10-10 09:36:45 -05001150 es->keep_buffer = true;
Ander Conselvan de Oliveira895b1fd2013-11-19 15:22:05 +02001151 else
Derek Foreman0fd6d4e2014-10-10 09:36:45 -05001152 es->keep_buffer = false;
Pekka Paalanenccfeae22012-12-04 15:58:14 +02001153
Jesse Barnes58ef3792012-02-23 09:45:49 -05001154 pixman_region32_init(&surface_overlap);
1155 pixman_region32_intersect(&surface_overlap, &overlap,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001156 &ev->transform.boundingbox);
Jesse Barnes58ef3792012-02-23 09:45:49 -05001157
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001158 next_plane = NULL;
Kristian Høgsberg6143f7d2012-07-14 00:31:32 -04001159 if (pixman_region32_not_empty(&surface_overlap))
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001160 next_plane = primary;
1161 if (next_plane == NULL)
Jason Ekstranda7af7042013-10-12 22:38:11 -05001162 next_plane = drm_output_prepare_cursor_view(output, ev);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001163 if (next_plane == NULL)
Jason Ekstranda7af7042013-10-12 22:38:11 -05001164 next_plane = drm_output_prepare_scanout_view(output, ev);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001165 if (next_plane == NULL)
Jason Ekstranda7af7042013-10-12 22:38:11 -05001166 next_plane = drm_output_prepare_overlay_view(output, ev);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001167 if (next_plane == NULL)
1168 next_plane = primary;
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02001169
Jason Ekstranda7af7042013-10-12 22:38:11 -05001170 weston_view_move_to_plane(ev, next_plane);
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02001171
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001172 if (next_plane == primary)
Jesse Barnes58ef3792012-02-23 09:45:49 -05001173 pixman_region32_union(&overlap, &overlap,
Jason Ekstranda7af7042013-10-12 22:38:11 -05001174 &ev->transform.boundingbox);
Kristian Høgsberg6143f7d2012-07-14 00:31:32 -04001175
Pekka Paalanenbf0e0312014-12-17 16:20:41 +02001176 if (next_plane == primary ||
1177 next_plane == &output->cursor_plane) {
1178 /* cursor plane involves a copy */
1179 ev->psf_flags = 0;
1180 } else {
1181 /* All other planes are a direct scanout of a
1182 * single client buffer.
1183 */
1184 ev->psf_flags = PRESENTATION_FEEDBACK_KIND_ZERO_COPY;
1185 }
1186
Jesse Barnes58ef3792012-02-23 09:45:49 -05001187 pixman_region32_fini(&surface_overlap);
1188 }
1189 pixman_region32_fini(&overlap);
Jesse Barnes58ef3792012-02-23 09:45:49 -05001190}
1191
Matt Roper361d2ad2011-08-29 13:52:23 -07001192static void
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001193drm_output_fini_pixman(struct drm_output *output);
1194
1195static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001196drm_output_destroy(struct weston_output *output_base)
Matt Roper361d2ad2011-08-29 13:52:23 -07001197{
1198 struct drm_output *output = (struct drm_output *) output_base;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001199 struct drm_backend *b =
1200 (struct drm_backend *)output->base.compositor->backend;
Matt Roper361d2ad2011-08-29 13:52:23 -07001201 drmModeCrtcPtr origcrtc = output->original_crtc;
Matt Roper361d2ad2011-08-29 13:52:23 -07001202
Xiong Zhangabd5d472013-10-11 14:43:07 +08001203 if (output->page_flip_pending) {
1204 output->destroy_pending = 1;
1205 weston_log("destroy output while page flip pending\n");
1206 return;
1207 }
1208
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001209 if (output->backlight)
1210 backlight_destroy(output->backlight);
1211
Ander Conselvan de Oliveiraa0a433a2013-06-04 16:24:04 +03001212 drmModeFreeProperty(output->dpms_prop);
1213
Matt Roper361d2ad2011-08-29 13:52:23 -07001214 /* Turn off hardware cursor */
Giulio Camuffo954f1832014-10-11 18:27:30 +03001215 drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
Matt Roper361d2ad2011-08-29 13:52:23 -07001216
1217 /* Restore original CRTC state */
Giulio Camuffo954f1832014-10-11 18:27:30 +03001218 drmModeSetCrtc(b->drm.fd, origcrtc->crtc_id, origcrtc->buffer_id,
Benjamin Franzke117483d2011-08-30 11:38:26 +02001219 origcrtc->x, origcrtc->y,
1220 &output->connector_id, 1, &origcrtc->mode);
Matt Roper361d2ad2011-08-29 13:52:23 -07001221 drmModeFreeCrtc(origcrtc);
1222
Giulio Camuffo954f1832014-10-11 18:27:30 +03001223 b->crtc_allocator &= ~(1 << output->crtc_id);
1224 b->connector_allocator &= ~(1 << output->connector_id);
Benjamin Franzke48c4ea22011-08-30 11:44:56 +02001225
Giulio Camuffo954f1832014-10-11 18:27:30 +03001226 if (b->use_pixman) {
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001227 drm_output_fini_pixman(output);
1228 } else {
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001229 gl_renderer->output_destroy(output_base);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001230 gbm_surface_destroy(output->surface);
1231 }
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -04001232
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04001233 weston_plane_release(&output->fb_plane);
1234 weston_plane_release(&output->cursor_plane);
1235
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001236 weston_output_destroy(&output->base);
Benjamin Franzke48c4ea22011-08-30 11:44:56 +02001237
Matt Roper361d2ad2011-08-29 13:52:23 -07001238 free(output);
1239}
1240
Alex Wub7b8bda2012-04-17 17:20:48 +08001241static struct drm_mode *
1242choose_mode (struct drm_output *output, struct weston_mode *target_mode)
1243{
1244 struct drm_mode *tmp_mode = NULL, *mode;
1245
Hardeningff39efa2013-09-18 23:56:35 +02001246 if (output->base.current_mode->width == target_mode->width &&
1247 output->base.current_mode->height == target_mode->height &&
1248 (output->base.current_mode->refresh == target_mode->refresh ||
Alex Wub7b8bda2012-04-17 17:20:48 +08001249 target_mode->refresh == 0))
Hardeningff39efa2013-09-18 23:56:35 +02001250 return (struct drm_mode *)output->base.current_mode;
Alex Wub7b8bda2012-04-17 17:20:48 +08001251
1252 wl_list_for_each(mode, &output->base.mode_list, base.link) {
1253 if (mode->mode_info.hdisplay == target_mode->width &&
1254 mode->mode_info.vdisplay == target_mode->height) {
Mario Kleiner872797c2015-06-21 21:25:09 +02001255 if (mode->base.refresh == target_mode->refresh ||
1256 target_mode->refresh == 0) {
Alex Wub7b8bda2012-04-17 17:20:48 +08001257 return mode;
Daniel Stonef556ebe2015-05-21 08:28:58 +01001258 } else if (!tmp_mode)
Alex Wub7b8bda2012-04-17 17:20:48 +08001259 tmp_mode = mode;
1260 }
1261 }
1262
1263 return tmp_mode;
1264}
1265
1266static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001267drm_output_init_egl(struct drm_output *output, struct drm_backend *b);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001268static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001269drm_output_init_pixman(struct drm_output *output, struct drm_backend *b);
Ander Conselvan de Oliveira6c01c9c2012-12-14 13:37:30 -02001270
1271static int
Alex Wub7b8bda2012-04-17 17:20:48 +08001272drm_output_switch_mode(struct weston_output *output_base, struct weston_mode *mode)
1273{
1274 struct drm_output *output;
1275 struct drm_mode *drm_mode;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001276 struct drm_backend *b;
Alex Wub7b8bda2012-04-17 17:20:48 +08001277
1278 if (output_base == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02001279 weston_log("output is NULL.\n");
Alex Wub7b8bda2012-04-17 17:20:48 +08001280 return -1;
1281 }
1282
1283 if (mode == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02001284 weston_log("mode is NULL.\n");
Alex Wub7b8bda2012-04-17 17:20:48 +08001285 return -1;
1286 }
1287
Giulio Camuffo954f1832014-10-11 18:27:30 +03001288 b = (struct drm_backend *)output_base->compositor->backend;
Alex Wub7b8bda2012-04-17 17:20:48 +08001289 output = (struct drm_output *)output_base;
1290 drm_mode = choose_mode (output, mode);
1291
1292 if (!drm_mode) {
Martin Minarik6d118362012-06-07 18:01:59 +02001293 weston_log("%s, invalid resolution:%dx%d\n", __func__, mode->width, mode->height);
Alex Wub7b8bda2012-04-17 17:20:48 +08001294 return -1;
Ander Conselvan de Oliveira6c01c9c2012-12-14 13:37:30 -02001295 }
1296
Hardeningff39efa2013-09-18 23:56:35 +02001297 if (&drm_mode->base == output->base.current_mode)
Alex Wub7b8bda2012-04-17 17:20:48 +08001298 return 0;
Alex Wub7b8bda2012-04-17 17:20:48 +08001299
Hardeningff39efa2013-09-18 23:56:35 +02001300 output->base.current_mode->flags = 0;
Alex Wub7b8bda2012-04-17 17:20:48 +08001301
Hardeningff39efa2013-09-18 23:56:35 +02001302 output->base.current_mode = &drm_mode->base;
1303 output->base.current_mode->flags =
Alex Wub7b8bda2012-04-17 17:20:48 +08001304 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
1305
Alex Wub7b8bda2012-04-17 17:20:48 +08001306 /* reset rendering stuff. */
Ander Conselvan de Oliveira526d4612013-01-25 15:13:03 +02001307 drm_output_release_fb(output, output->current);
1308 drm_output_release_fb(output, output->next);
1309 output->current = output->next = NULL;
Alex Wub7b8bda2012-04-17 17:20:48 +08001310
Giulio Camuffo954f1832014-10-11 18:27:30 +03001311 if (b->use_pixman) {
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001312 drm_output_fini_pixman(output);
Giulio Camuffo954f1832014-10-11 18:27:30 +03001313 if (drm_output_init_pixman(output, b) < 0) {
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001314 weston_log("failed to init output pixman state with "
1315 "new mode\n");
1316 return -1;
1317 }
1318 } else {
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001319 gl_renderer->output_destroy(&output->base);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001320 gbm_surface_destroy(output->surface);
Alex Wub7b8bda2012-04-17 17:20:48 +08001321
Giulio Camuffo954f1832014-10-11 18:27:30 +03001322 if (drm_output_init_egl(output, b) < 0) {
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001323 weston_log("failed to init output egl state with "
1324 "new mode");
1325 return -1;
1326 }
Ander Conselvan de Oliveira6c01c9c2012-12-14 13:37:30 -02001327 }
1328
Alex Wub7b8bda2012-04-17 17:20:48 +08001329 return 0;
Alex Wub7b8bda2012-04-17 17:20:48 +08001330}
1331
Kristian Høgsbergb1868472011-04-22 12:27:57 -04001332static int
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001333on_drm_input(int fd, uint32_t mask, void *data)
1334{
1335 drmEventContext evctx;
1336
1337 memset(&evctx, 0, sizeof evctx);
1338 evctx.version = DRM_EVENT_CONTEXT_VERSION;
1339 evctx.page_flip_handler = page_flip_handler;
Jesse Barnes58ef3792012-02-23 09:45:49 -05001340 evctx.vblank_handler = vblank_handler;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001341 drmHandleEvent(fd, &evctx);
Kristian Høgsbergb1868472011-04-22 12:27:57 -04001342
1343 return 1;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001344}
1345
1346static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001347init_drm(struct drm_backend *b, struct udev_device *device)
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001348{
Kristian Høgsbergb5ef5912012-03-28 22:53:49 -04001349 const char *filename, *sysnum;
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +03001350 uint64_t cap;
1351 int fd, ret;
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04001352 clockid_t clk_id;
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -04001353
Kristian Høgsbergb71302e2012-05-10 12:28:35 -04001354 sysnum = udev_device_get_sysnum(device);
1355 if (sysnum)
Giulio Camuffo954f1832014-10-11 18:27:30 +03001356 b->drm.id = atoi(sysnum);
1357 if (!sysnum || b->drm.id < 0) {
Martin Minarik6d118362012-06-07 18:01:59 +02001358 weston_log("cannot get device sysnum\n");
Kristian Høgsbergb71302e2012-05-10 12:28:35 -04001359 return -1;
1360 }
1361
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -04001362 filename = udev_device_get_devnode(device);
Giulio Camuffo954f1832014-10-11 18:27:30 +03001363 fd = weston_launcher_open(b->compositor->launcher, filename, O_RDWR);
Kristian Høgsberg5fcd0aa2010-08-09 14:43:33 -04001364 if (fd < 0) {
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001365 /* Probably permissions error */
Martin Minarik6d118362012-06-07 18:01:59 +02001366 weston_log("couldn't open %s, skipping\n",
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001367 udev_device_get_devnode(device));
1368 return -1;
1369 }
1370
Kristian Høgsbergfc9c5e02012-06-08 16:45:33 -04001371 weston_log("using %s\n", filename);
1372
Giulio Camuffo954f1832014-10-11 18:27:30 +03001373 b->drm.fd = fd;
1374 b->drm.filename = strdup(filename);
Ander Conselvan de Oliveira22929172013-01-25 15:13:02 +02001375
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +03001376 ret = drmGetCap(fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
1377 if (ret == 0 && cap == 1)
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04001378 clk_id = CLOCK_MONOTONIC;
Ander Conselvan de Oliveira95eb3a22013-05-07 14:16:59 +03001379 else
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04001380 clk_id = CLOCK_REALTIME;
1381
Giulio Camuffo954f1832014-10-11 18:27:30 +03001382 if (weston_compositor_set_presentation_clock(b->compositor, clk_id) < 0) {
Pekka Paalanenb5eedad2014-09-23 22:08:45 -04001383 weston_log("Error: failed to set presentation clock %d.\n",
1384 clk_id);
1385 return -1;
1386 }
Ander Conselvan de Oliveira1d41ad42013-01-25 15:13:04 +02001387
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -03001388 ret = drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &cap);
1389 if (ret == 0)
Giulio Camuffo954f1832014-10-11 18:27:30 +03001390 b->cursor_width = cap;
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -03001391 else
Giulio Camuffo954f1832014-10-11 18:27:30 +03001392 b->cursor_width = 64;
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -03001393
1394 ret = drmGetCap(fd, DRM_CAP_CURSOR_HEIGHT, &cap);
1395 if (ret == 0)
Giulio Camuffo954f1832014-10-11 18:27:30 +03001396 b->cursor_height = cap;
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -03001397 else
Giulio Camuffo954f1832014-10-11 18:27:30 +03001398 b->cursor_height = 64;
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -03001399
Ander Conselvan de Oliveira22929172013-01-25 15:13:02 +02001400 return 0;
1401}
1402
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001403static struct gbm_device *
1404create_gbm_device(int fd)
Ander Conselvan de Oliveira22929172013-01-25 15:13:02 +02001405{
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001406 struct gbm_device *gbm;
Alexandru DAMIANbe0ac5b2013-10-02 17:51:05 +01001407
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001408 gl_renderer = weston_load_module("gl-renderer.so",
1409 "gl_renderer_interface");
1410 if (!gl_renderer)
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001411 return NULL;
Ander Conselvan de Oliveira97f29522013-10-14 15:57:11 +03001412
1413 /* GBM will load a dri driver, but even though they need symbols from
1414 * libglapi, in some version of Mesa they are not linked to it. Since
1415 * only the gl-renderer module links to it, the call above won't make
1416 * these symbols globally available, and loading the DRI driver fails.
1417 * Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
1418 dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
1419
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001420 gbm = gbm_create_device(fd);
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001421
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001422 return gbm;
1423}
1424
Bryce Harringtonc056a982015-05-19 15:25:18 -07001425/* When initializing EGL, if the preferred buffer format isn't available
Derek Foremanc4cfe852015-05-15 12:12:40 -05001426 * we may be able to susbstitute an ARGB format for an XRGB one.
1427 *
1428 * This returns 0 if substitution isn't possible, but 0 might be a
1429 * legitimate format for other EGL platforms, so the caller is
1430 * responsible for checking for 0 before calling gl_renderer->create().
1431 *
1432 * This works around https://bugs.freedesktop.org/show_bug.cgi?id=89689
1433 * but it's entirely possible we'll see this again on other implementations.
1434 */
1435static int
1436fallback_format_for(uint32_t format)
1437{
1438 switch (format) {
1439 case GBM_FORMAT_XRGB8888:
1440 return GBM_FORMAT_ARGB8888;
1441 case GBM_FORMAT_XRGB2101010:
1442 return GBM_FORMAT_ARGB2101010;
1443 default:
1444 return 0;
1445 }
1446}
1447
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001448static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001449drm_backend_create_gl_renderer(struct drm_backend *b)
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001450{
Derek Foremanc4cfe852015-05-15 12:12:40 -05001451 EGLint format[2] = {
Giulio Camuffo954f1832014-10-11 18:27:30 +03001452 b->format,
1453 fallback_format_for(b->format),
Derek Foremanc4cfe852015-05-15 12:12:40 -05001454 };
1455 int n_formats = 1;
John Kåre Alsakeref591aa2013-03-02 12:27:39 +01001456
Derek Foremanc4cfe852015-05-15 12:12:40 -05001457 if (format[1])
1458 n_formats = 2;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001459 if (gl_renderer->create(b->compositor,
Derek Foremanc4cfe852015-05-15 12:12:40 -05001460 EGL_PLATFORM_GBM_KHR,
Giulio Camuffo954f1832014-10-11 18:27:30 +03001461 (void *)b->gbm,
Derek Foremanc4cfe852015-05-15 12:12:40 -05001462 gl_renderer->opaque_attribs,
1463 format,
1464 n_formats) < 0) {
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001465 return -1;
1466 }
1467
1468 return 0;
1469}
1470
1471static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001472init_egl(struct drm_backend *b)
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001473{
Giulio Camuffo954f1832014-10-11 18:27:30 +03001474 b->gbm = create_gbm_device(b->drm.fd);
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001475
Giulio Camuffo954f1832014-10-11 18:27:30 +03001476 if (!b->gbm)
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02001477 return -1;
1478
Giulio Camuffo954f1832014-10-11 18:27:30 +03001479 if (drm_backend_create_gl_renderer(b) < 0) {
1480 gbm_device_destroy(b->gbm);
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -04001481 return -1;
1482 }
1483
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001484 return 0;
1485}
1486
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001487static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001488init_pixman(struct drm_backend *b)
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001489{
Giulio Camuffo954f1832014-10-11 18:27:30 +03001490 return pixman_renderer_init(b->compositor);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001491}
1492
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03001493static struct drm_mode *
Alexander Larsson0b135062013-05-28 16:23:36 +02001494drm_output_add_mode(struct drm_output *output, drmModeModeInfo *info)
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001495{
1496 struct drm_mode *mode;
Kristian Høgsbergc4621b02012-05-10 12:23:53 -04001497 uint64_t refresh;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001498
1499 mode = malloc(sizeof *mode);
1500 if (mode == NULL)
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03001501 return NULL;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001502
1503 mode->base.flags = 0;
Alexander Larsson0b135062013-05-28 16:23:36 +02001504 mode->base.width = info->hdisplay;
1505 mode->base.height = info->vdisplay;
Kristian Høgsbergc4621b02012-05-10 12:23:53 -04001506
1507 /* Calculate higher precision (mHz) refresh rate */
1508 refresh = (info->clock * 1000000LL / info->htotal +
1509 info->vtotal / 2) / info->vtotal;
1510
1511 if (info->flags & DRM_MODE_FLAG_INTERLACE)
1512 refresh *= 2;
1513 if (info->flags & DRM_MODE_FLAG_DBLSCAN)
1514 refresh /= 2;
1515 if (info->vscan > 1)
1516 refresh /= info->vscan;
1517
1518 mode->base.refresh = refresh;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001519 mode->mode_info = *info;
Kristian Høgsberg061c4252012-06-28 11:28:15 -04001520
1521 if (info->type & DRM_MODE_TYPE_PREFERRED)
1522 mode->base.flags |= WL_OUTPUT_MODE_PREFERRED;
1523
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001524 wl_list_insert(output->base.mode_list.prev, &mode->base.link);
1525
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03001526 return mode;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04001527}
1528
1529static int
1530drm_subpixel_to_wayland(int drm_value)
1531{
1532 switch (drm_value) {
1533 default:
1534 case DRM_MODE_SUBPIXEL_UNKNOWN:
1535 return WL_OUTPUT_SUBPIXEL_UNKNOWN;
1536 case DRM_MODE_SUBPIXEL_NONE:
1537 return WL_OUTPUT_SUBPIXEL_NONE;
1538 case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
1539 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB;
1540 case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
1541 return WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR;
1542 case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
1543 return WL_OUTPUT_SUBPIXEL_VERTICAL_RGB;
1544 case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
1545 return WL_OUTPUT_SUBPIXEL_VERTICAL_BGR;
1546 }
1547}
1548
Tiago Vignatti5ab91ad2012-03-12 19:40:09 -03001549/* returns a value between 0-255 range, where higher is brighter */
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001550static uint32_t
1551drm_get_backlight(struct drm_output *output)
1552{
1553 long brightness, max_brightness, norm;
1554
1555 brightness = backlight_get_brightness(output->backlight);
1556 max_brightness = backlight_get_max_brightness(output->backlight);
1557
Tiago Vignatti5ab91ad2012-03-12 19:40:09 -03001558 /* convert it on a scale of 0 to 255 */
1559 norm = (brightness * 255)/(max_brightness);
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001560
1561 return (uint32_t) norm;
1562}
1563
Tiago Vignatti5ab91ad2012-03-12 19:40:09 -03001564/* values accepted are between 0-255 range */
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001565static void
1566drm_set_backlight(struct weston_output *output_base, uint32_t value)
1567{
1568 struct drm_output *output = (struct drm_output *) output_base;
1569 long max_brightness, new_brightness;
1570
1571 if (!output->backlight)
1572 return;
1573
Kristian Høgsberg875ab9e2012-03-30 11:52:39 -04001574 if (value > 255)
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001575 return;
1576
1577 max_brightness = backlight_get_max_brightness(output->backlight);
1578
1579 /* get denormalized value */
Tiago Vignatti5ab91ad2012-03-12 19:40:09 -03001580 new_brightness = (value * max_brightness) / 255;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001581
1582 backlight_set_brightness(output->backlight, new_brightness);
1583}
1584
1585static drmModePropertyPtr
1586drm_get_prop(int fd, drmModeConnectorPtr connector, const char *name)
1587{
1588 drmModePropertyPtr props;
1589 int i;
1590
1591 for (i = 0; i < connector->count_props; i++) {
1592 props = drmModeGetProperty(fd, connector->props[i]);
1593 if (!props)
1594 continue;
1595
1596 if (!strcmp(props->name, name))
1597 return props;
1598
1599 drmModeFreeProperty(props);
1600 }
1601
1602 return NULL;
1603}
1604
1605static void
1606drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
1607{
1608 struct drm_output *output = (struct drm_output *) output_base;
1609 struct weston_compositor *ec = output_base->compositor;
Giulio Camuffo954f1832014-10-11 18:27:30 +03001610 struct drm_backend *b = (struct drm_backend *)ec->backend;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001611
Ander Conselvan de Oliveiraa0a433a2013-06-04 16:24:04 +03001612 if (!output->dpms_prop)
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001613 return;
1614
Giulio Camuffo954f1832014-10-11 18:27:30 +03001615 drmModeConnectorSetProperty(b->drm.fd, output->connector_id,
Ander Conselvan de Oliveiraa0a433a2013-06-04 16:24:04 +03001616 output->dpms_prop->prop_id, level);
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02001617}
1618
Kristian Høgsberg2f9ed712012-07-26 17:57:15 -04001619static const char *connector_type_names[] = {
1620 "None",
1621 "VGA",
1622 "DVI",
1623 "DVI",
1624 "DVI",
1625 "Composite",
1626 "TV",
1627 "LVDS",
1628 "CTV",
1629 "DIN",
1630 "DP",
1631 "HDMI",
1632 "HDMI",
1633 "TV",
1634 "eDP",
1635};
1636
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04001637static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001638find_crtc_for_connector(struct drm_backend *b,
Kristian Høgsberg9ca38462012-07-26 22:44:55 -04001639 drmModeRes *resources, drmModeConnector *connector)
1640{
1641 drmModeEncoder *encoder;
1642 uint32_t possible_crtcs;
1643 int i, j;
1644
1645 for (j = 0; j < connector->count_encoders; j++) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03001646 encoder = drmModeGetEncoder(b->drm.fd, connector->encoders[j]);
Kristian Høgsberg9ca38462012-07-26 22:44:55 -04001647 if (encoder == NULL) {
1648 weston_log("Failed to get encoder.\n");
1649 return -1;
1650 }
1651 possible_crtcs = encoder->possible_crtcs;
1652 drmModeFreeEncoder(encoder);
1653
1654 for (i = 0; i < resources->count_crtcs; i++) {
1655 if (possible_crtcs & (1 << i) &&
Giulio Camuffo954f1832014-10-11 18:27:30 +03001656 !(b->crtc_allocator & (1 << resources->crtcs[i])))
Kristian Høgsberg9ca38462012-07-26 22:44:55 -04001657 return i;
1658 }
1659 }
1660
1661 return -1;
1662}
1663
Ander Conselvan de Oliveira475cf152012-12-14 13:37:29 -02001664/* Init output state that depends on gl or gbm */
1665static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001666drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
Ander Conselvan de Oliveira475cf152012-12-14 13:37:29 -02001667{
Derek Foremanc4cfe852015-05-15 12:12:40 -05001668 EGLint format[2] = {
1669 output->format,
1670 fallback_format_for(output->format),
1671 };
1672 int i, flags, n_formats = 1;
Ander Conselvan de Oliveira6c01c9c2012-12-14 13:37:30 -02001673
Giulio Camuffo954f1832014-10-11 18:27:30 +03001674 output->surface = gbm_surface_create(b->gbm,
Hardeningff39efa2013-09-18 23:56:35 +02001675 output->base.current_mode->width,
1676 output->base.current_mode->height,
Derek Foremanc4cfe852015-05-15 12:12:40 -05001677 format[0],
Ander Conselvan de Oliveira475cf152012-12-14 13:37:29 -02001678 GBM_BO_USE_SCANOUT |
1679 GBM_BO_USE_RENDERING);
1680 if (!output->surface) {
1681 weston_log("failed to create gbm surface\n");
1682 return -1;
1683 }
1684
Derek Foremanc4cfe852015-05-15 12:12:40 -05001685 if (format[1])
1686 n_formats = 2;
Jonny Lamb671148f2015-03-20 15:26:52 +01001687 if (gl_renderer->output_create(&output->base,
Jonny Lamb445fb692015-03-24 13:12:01 +01001688 (EGLNativeDisplayType)output->surface,
1689 output->surface,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001690 gl_renderer->opaque_attribs,
Derek Foremanc4cfe852015-05-15 12:12:40 -05001691 format,
1692 n_formats) < 0) {
Ander Conselvan de Oliveira6c01c9c2012-12-14 13:37:30 -02001693 weston_log("failed to create gl renderer output state\n");
Ander Conselvan de Oliveira475cf152012-12-14 13:37:29 -02001694 gbm_surface_destroy(output->surface);
1695 return -1;
1696 }
1697
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -03001698 flags = GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE;
Ander Conselvan de Oliveira6c01c9c2012-12-14 13:37:30 -02001699
1700 for (i = 0; i < 2; i++) {
1701 if (output->cursor_bo[i])
1702 continue;
1703
1704 output->cursor_bo[i] =
Giulio Camuffo954f1832014-10-11 18:27:30 +03001705 gbm_bo_create(b->gbm, b->cursor_width, b->cursor_height,
Alvaro Fernando Garcíadce7c6e2014-07-28 18:30:17 -03001706 GBM_FORMAT_ARGB8888, flags);
Ander Conselvan de Oliveira6c01c9c2012-12-14 13:37:30 -02001707 }
1708
Ander Conselvan de Oliveira475cf152012-12-14 13:37:29 -02001709 if (output->cursor_bo[0] == NULL || output->cursor_bo[1] == NULL) {
1710 weston_log("cursor buffers unavailable, using gl cursors\n");
Giulio Camuffo954f1832014-10-11 18:27:30 +03001711 b->cursors_are_broken = 1;
Ander Conselvan de Oliveira475cf152012-12-14 13:37:29 -02001712 }
1713
1714 return 0;
1715}
1716
Kristian Høgsberg9ca38462012-07-26 22:44:55 -04001717static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03001718drm_output_init_pixman(struct drm_output *output, struct drm_backend *b)
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001719{
Hardeningff39efa2013-09-18 23:56:35 +02001720 int w = output->base.current_mode->width;
1721 int h = output->base.current_mode->height;
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001722 unsigned int i;
1723
1724 /* FIXME error checking */
1725
1726 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03001727 output->dumb[i] = drm_fb_create_dumb(b, w, h);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001728 if (!output->dumb[i])
1729 goto err;
1730
1731 output->image[i] =
Alexander Larsson0b135062013-05-28 16:23:36 +02001732 pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001733 output->dumb[i]->map,
1734 output->dumb[i]->stride);
1735 if (!output->image[i])
1736 goto err;
1737 }
1738
1739 if (pixman_renderer_output_create(&output->base) < 0)
1740 goto err;
1741
1742 pixman_region32_init_rect(&output->previous_damage,
Alexander Larsson0b135062013-05-28 16:23:36 +02001743 output->base.x, output->base.y, output->base.width, output->base.height);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001744
1745 return 0;
1746
1747err:
1748 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1749 if (output->dumb[i])
1750 drm_fb_destroy_dumb(output->dumb[i]);
1751 if (output->image[i])
1752 pixman_image_unref(output->image[i]);
1753
1754 output->dumb[i] = NULL;
1755 output->image[i] = NULL;
1756 }
1757
1758 return -1;
1759}
1760
1761static void
1762drm_output_fini_pixman(struct drm_output *output)
1763{
1764 unsigned int i;
1765
1766 pixman_renderer_output_destroy(&output->base);
1767 pixman_region32_fini(&output->previous_damage);
1768
1769 for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
1770 drm_fb_destroy_dumb(output->dumb[i]);
1771 pixman_image_unref(output->image[i]);
1772 output->dumb[i] = NULL;
1773 output->image[i] = NULL;
1774 }
1775}
1776
Richard Hughes2b2092a2013-04-24 14:58:02 +01001777static void
1778edid_parse_string(const uint8_t *data, char text[])
1779{
1780 int i;
1781 int replaced = 0;
1782
1783 /* this is always 12 bytes, but we can't guarantee it's null
1784 * terminated or not junk. */
1785 strncpy(text, (const char *) data, 12);
1786
1787 /* remove insane chars */
1788 for (i = 0; text[i] != '\0'; i++) {
1789 if (text[i] == '\n' ||
1790 text[i] == '\r') {
1791 text[i] = '\0';
1792 break;
1793 }
1794 }
1795
1796 /* ensure string is printable */
1797 for (i = 0; text[i] != '\0'; i++) {
1798 if (!isprint(text[i])) {
1799 text[i] = '-';
1800 replaced++;
1801 }
1802 }
1803
1804 /* if the string is random junk, ignore the string */
1805 if (replaced > 4)
1806 text[0] = '\0';
1807}
1808
1809#define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe
1810#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc
1811#define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff
1812#define EDID_OFFSET_DATA_BLOCKS 0x36
1813#define EDID_OFFSET_LAST_BLOCK 0x6c
1814#define EDID_OFFSET_PNPID 0x08
1815#define EDID_OFFSET_SERIAL 0x0c
1816
1817static int
1818edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
1819{
1820 int i;
1821 uint32_t serial_number;
1822
1823 /* check header */
1824 if (length < 128)
1825 return -1;
1826 if (data[0] != 0x00 || data[1] != 0xff)
1827 return -1;
1828
1829 /* decode the PNP ID from three 5 bit words packed into 2 bytes
1830 * /--08--\/--09--\
1831 * 7654321076543210
1832 * |\---/\---/\---/
1833 * R C1 C2 C3 */
1834 edid->pnp_id[0] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x7c) / 4) - 1;
1835 edid->pnp_id[1] = 'A' + ((data[EDID_OFFSET_PNPID + 0] & 0x3) * 8) + ((data[EDID_OFFSET_PNPID + 1] & 0xe0) / 32) - 1;
1836 edid->pnp_id[2] = 'A' + (data[EDID_OFFSET_PNPID + 1] & 0x1f) - 1;
1837 edid->pnp_id[3] = '\0';
1838
1839 /* maybe there isn't a ASCII serial number descriptor, so use this instead */
1840 serial_number = (uint32_t) data[EDID_OFFSET_SERIAL + 0];
1841 serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 1] * 0x100;
1842 serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 2] * 0x10000;
1843 serial_number += (uint32_t) data[EDID_OFFSET_SERIAL + 3] * 0x1000000;
1844 if (serial_number > 0)
1845 sprintf(edid->serial_number, "%lu", (unsigned long) serial_number);
1846
1847 /* parse EDID data */
1848 for (i = EDID_OFFSET_DATA_BLOCKS;
1849 i <= EDID_OFFSET_LAST_BLOCK;
1850 i += 18) {
1851 /* ignore pixel clock data */
1852 if (data[i] != 0)
1853 continue;
1854 if (data[i+2] != 0)
1855 continue;
1856
1857 /* any useful blocks? */
1858 if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME) {
1859 edid_parse_string(&data[i+5],
1860 edid->monitor_name);
1861 } else if (data[i+3] == EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER) {
1862 edid_parse_string(&data[i+5],
1863 edid->serial_number);
1864 } else if (data[i+3] == EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING) {
1865 edid_parse_string(&data[i+5],
1866 edid->eisa_id);
1867 }
1868 }
1869 return 0;
1870}
1871
1872static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03001873find_and_parse_output_edid(struct drm_backend *b,
Richard Hughes2b2092a2013-04-24 14:58:02 +01001874 struct drm_output *output,
1875 drmModeConnector *connector)
1876{
1877 drmModePropertyBlobPtr edid_blob = NULL;
1878 drmModePropertyPtr property;
1879 int i;
1880 int rc;
1881
1882 for (i = 0; i < connector->count_props && !edid_blob; i++) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03001883 property = drmModeGetProperty(b->drm.fd, connector->props[i]);
Richard Hughes2b2092a2013-04-24 14:58:02 +01001884 if (!property)
1885 continue;
1886 if ((property->flags & DRM_MODE_PROP_BLOB) &&
1887 !strcmp(property->name, "EDID")) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03001888 edid_blob = drmModeGetPropertyBlob(b->drm.fd,
Richard Hughes2b2092a2013-04-24 14:58:02 +01001889 connector->prop_values[i]);
1890 }
1891 drmModeFreeProperty(property);
1892 }
1893 if (!edid_blob)
1894 return;
1895
1896 rc = edid_parse(&output->edid,
1897 edid_blob->data,
1898 edid_blob->length);
1899 if (!rc) {
1900 weston_log("EDID data '%s', '%s', '%s'\n",
1901 output->edid.pnp_id,
1902 output->edid.monitor_name,
1903 output->edid.serial_number);
1904 if (output->edid.pnp_id[0] != '\0')
1905 output->base.make = output->edid.pnp_id;
1906 if (output->edid.monitor_name[0] != '\0')
1907 output->base.model = output->edid.monitor_name;
1908 if (output->edid.serial_number[0] != '\0')
1909 output->base.serial_number = output->edid.serial_number;
1910 }
1911 drmModeFreePropertyBlob(edid_blob);
1912}
1913
Kristian Høgsberga30989a2013-05-23 17:23:15 -04001914
1915
1916static int
1917parse_modeline(const char *s, drmModeModeInfo *mode)
1918{
1919 char hsync[16];
1920 char vsync[16];
1921 float fclock;
1922
1923 mode->type = DRM_MODE_TYPE_USERDEF;
1924 mode->hskew = 0;
1925 mode->vscan = 0;
1926 mode->vrefresh = 0;
1927 mode->flags = 0;
1928
Rob Bradford307e09e2013-07-26 16:29:40 +01001929 if (sscanf(s, "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
Kristian Høgsberga30989a2013-05-23 17:23:15 -04001930 &fclock,
1931 &mode->hdisplay,
1932 &mode->hsync_start,
1933 &mode->hsync_end,
1934 &mode->htotal,
1935 &mode->vdisplay,
1936 &mode->vsync_start,
1937 &mode->vsync_end,
1938 &mode->vtotal, hsync, vsync) != 11)
1939 return -1;
1940
1941 mode->clock = fclock * 1000;
1942 if (strcmp(hsync, "+hsync") == 0)
1943 mode->flags |= DRM_MODE_FLAG_PHSYNC;
1944 else if (strcmp(hsync, "-hsync") == 0)
1945 mode->flags |= DRM_MODE_FLAG_NHSYNC;
1946 else
1947 return -1;
1948
1949 if (strcmp(vsync, "+vsync") == 0)
1950 mode->flags |= DRM_MODE_FLAG_PVSYNC;
1951 else if (strcmp(vsync, "-vsync") == 0)
1952 mode->flags |= DRM_MODE_FLAG_NVSYNC;
1953 else
1954 return -1;
1955
1956 return 0;
1957}
1958
Rob Bradford66bd9f52013-06-25 18:56:42 +01001959static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03001960setup_output_seat_constraint(struct drm_backend *b,
Rob Bradford66bd9f52013-06-25 18:56:42 +01001961 struct weston_output *output,
1962 const char *s)
1963{
1964 if (strcmp(s, "") != 0) {
1965 struct udev_seat *seat;
1966
Giulio Camuffo954f1832014-10-11 18:27:30 +03001967 seat = udev_seat_get_named(&b->input, s);
Rob Bradford66bd9f52013-06-25 18:56:42 +01001968 if (seat)
1969 seat->base.output = output;
1970
1971 if (seat && seat->base.pointer)
1972 weston_pointer_clamp(seat->base.pointer,
1973 &seat->base.pointer->x,
1974 &seat->base.pointer->y);
1975 }
1976}
1977
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02001978static int
Neil Roberts77c1a5b2014-03-07 18:05:50 +00001979get_gbm_format_from_section(struct weston_config_section *section,
1980 uint32_t default_value,
1981 uint32_t *format)
1982{
1983 char *s;
1984 int ret = 0;
1985
1986 weston_config_section_get_string(section,
1987 "gbm-format", &s, NULL);
1988
1989 if (s == NULL)
1990 *format = default_value;
1991 else if (strcmp(s, "xrgb8888") == 0)
1992 *format = GBM_FORMAT_XRGB8888;
1993 else if (strcmp(s, "rgb565") == 0)
1994 *format = GBM_FORMAT_RGB565;
1995 else if (strcmp(s, "xrgb2101010") == 0)
1996 *format = GBM_FORMAT_XRGB2101010;
1997 else {
1998 weston_log("fatal: unrecognized pixel format: %s\n", s);
1999 ret = -1;
2000 }
2001
2002 free(s);
2003
2004 return ret;
2005}
2006
2007static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03002008create_output_for_connector(struct drm_backend *b,
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002009 drmModeRes *resources,
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +01002010 drmModeConnector *connector,
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002011 int x, int y, struct udev_device *drm_device)
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002012{
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04002013 struct drm_output *output;
Fabien DESSENNE4b255872013-12-12 17:13:56 +01002014 struct drm_mode *drm_mode, *next, *preferred, *current, *configured, *best;
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03002015 struct weston_mode *m;
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002016 struct weston_config_section *section;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002017 drmModeEncoder *encoder;
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002018 drmModeModeInfo crtc_mode, modeline;
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002019 drmModeCrtc *crtc;
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002020 int i, width, height, scale;
2021 char name[32], *s;
Kristian Høgsberg2f9ed712012-07-26 17:57:15 -04002022 const char *type_name;
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002023 enum output_config config;
2024 uint32_t transform;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002025
Giulio Camuffo954f1832014-10-11 18:27:30 +03002026 i = find_crtc_for_connector(b, resources, connector);
Kristian Høgsberg9ca38462012-07-26 22:44:55 -04002027 if (i < 0) {
2028 weston_log("No usable crtc/encoder pair for connector.\n");
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002029 return -1;
2030 }
2031
Peter Huttererf3d62272013-08-08 11:57:05 +10002032 output = zalloc(sizeof *output);
Kristian Høgsberg9ca38462012-07-26 22:44:55 -04002033 if (output == NULL)
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04002034 return -1;
2035
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04002036 output->base.subpixel = drm_subpixel_to_wayland(connector->subpixel);
2037 output->base.make = "unknown";
2038 output->base.model = "unknown";
Richard Hughes2b2092a2013-04-24 14:58:02 +01002039 output->base.serial_number = "unknown";
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04002040 wl_list_init(&output->base.mode_list);
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04002041
Kristian Høgsberg2f9ed712012-07-26 17:57:15 -04002042 if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
2043 type_name = connector_type_names[connector->connector_type];
2044 else
2045 type_name = "UNKNOWN";
2046 snprintf(name, 32, "%s%d", type_name, connector->connector_type_id);
Richard Hughesafe690c2013-05-02 10:10:04 +01002047 output->base.name = strdup(name);
Kristian Høgsberg2f9ed712012-07-26 17:57:15 -04002048
Giulio Camuffo954f1832014-10-11 18:27:30 +03002049 section = weston_config_get_section(b->compositor->config, "output", "name",
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002050 output->base.name);
2051 weston_config_section_get_string(section, "mode", &s, "preferred");
2052 if (strcmp(s, "off") == 0)
2053 config = OUTPUT_CONFIG_OFF;
2054 else if (strcmp(s, "preferred") == 0)
2055 config = OUTPUT_CONFIG_PREFERRED;
2056 else if (strcmp(s, "current") == 0)
2057 config = OUTPUT_CONFIG_CURRENT;
2058 else if (sscanf(s, "%dx%d", &width, &height) == 2)
2059 config = OUTPUT_CONFIG_MODE;
2060 else if (parse_modeline(s, &modeline) == 0)
2061 config = OUTPUT_CONFIG_MODELINE;
2062 else {
2063 weston_log("Invalid mode \"%s\" for output %s\n",
2064 s, output->base.name);
2065 config = OUTPUT_CONFIG_PREFERRED;
Alexander Larssond9a7bb72013-05-22 14:41:39 +02002066 }
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002067 free(s);
2068
2069 weston_config_section_get_int(section, "scale", &scale, 1);
2070 weston_config_section_get_string(section, "transform", &s, "normal");
Derek Foreman64a3df02014-10-23 12:24:18 -05002071 if (weston_parse_transform(s, &transform) < 0)
2072 weston_log("Invalid transform \"%s\" for output %s\n",
2073 s, output->base.name);
2074
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002075 free(s);
Alexander Larssond9a7bb72013-05-22 14:41:39 +02002076
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002077 if (get_gbm_format_from_section(section,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002078 b->format,
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002079 &output->format) == -1)
Giulio Camuffo954f1832014-10-11 18:27:30 +03002080 output->format = b->format;
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002081
Rob Bradford66bd9f52013-06-25 18:56:42 +01002082 weston_config_section_get_string(section, "seat", &s, "");
Giulio Camuffo954f1832014-10-11 18:27:30 +03002083 setup_output_seat_constraint(b, &output->base, s);
Rob Bradford66bd9f52013-06-25 18:56:42 +01002084 free(s);
2085
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002086 output->crtc_id = resources->crtcs[i];
Rob Clark5ca1a472012-08-08 20:27:37 -05002087 output->pipe = i;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002088 b->crtc_allocator |= (1 << output->crtc_id);
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002089 output->connector_id = connector->connector_id;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002090 b->connector_allocator |= (1 << output->connector_id);
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04002091
Giulio Camuffo954f1832014-10-11 18:27:30 +03002092 output->original_crtc = drmModeGetCrtc(b->drm.fd, output->crtc_id);
2093 output->dpms_prop = drm_get_prop(b->drm.fd, connector, "DPMS");
Matt Roper361d2ad2011-08-29 13:52:23 -07002094
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002095 /* Get the current mode on the crtc that's currently driving
2096 * this connector. */
Giulio Camuffo954f1832014-10-11 18:27:30 +03002097 encoder = drmModeGetEncoder(b->drm.fd, connector->encoder_id);
Wang Quanxianacb805a2012-07-30 18:09:46 -04002098 memset(&crtc_mode, 0, sizeof crtc_mode);
2099 if (encoder != NULL) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002100 crtc = drmModeGetCrtc(b->drm.fd, encoder->crtc_id);
Wang Quanxianacb805a2012-07-30 18:09:46 -04002101 drmModeFreeEncoder(encoder);
2102 if (crtc == NULL)
2103 goto err_free;
2104 if (crtc->mode_valid)
2105 crtc_mode = crtc->mode;
2106 drmModeFreeCrtc(crtc);
2107 }
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002108
David Herrmann0f0d54e2011-12-08 17:05:45 +01002109 for (i = 0; i < connector->count_modes; i++) {
Alexander Larsson0b135062013-05-28 16:23:36 +02002110 drm_mode = drm_output_add_mode(output, &connector->modes[i]);
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03002111 if (!drm_mode)
David Herrmann0f0d54e2011-12-08 17:05:45 +01002112 goto err_free;
2113 }
2114
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002115 if (config == OUTPUT_CONFIG_OFF) {
2116 weston_log("Disabling output %s\n", output->base.name);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002117 drmModeSetCrtc(b->drm.fd, output->crtc_id,
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002118 0, 0, 0, 0, 0, NULL);
2119 goto err_free;
2120 }
2121
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002122 preferred = NULL;
2123 current = NULL;
Scott Moreau8ab5d452012-07-30 19:51:08 -06002124 configured = NULL;
Fabien DESSENNE4b255872013-12-12 17:13:56 +01002125 best = NULL;
Scott Moreau8ab5d452012-07-30 19:51:08 -06002126
Giulio Camuffoc0b94872013-06-19 15:19:19 +02002127 wl_list_for_each_reverse(drm_mode, &output->base.mode_list, base.link) {
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002128 if (config == OUTPUT_CONFIG_MODE &&
Alexander Larsson0b135062013-05-28 16:23:36 +02002129 width == drm_mode->base.width &&
2130 height == drm_mode->base.height)
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03002131 configured = drm_mode;
Wang Quanxianacb805a2012-07-30 18:09:46 -04002132 if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03002133 current = drm_mode;
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002134 if (drm_mode->base.flags & WL_OUTPUT_MODE_PREFERRED)
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03002135 preferred = drm_mode;
Fabien DESSENNE4b255872013-12-12 17:13:56 +01002136 best = drm_mode;
David Herrmann0f0d54e2011-12-08 17:05:45 +01002137 }
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04002138
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002139 if (config == OUTPUT_CONFIG_MODELINE) {
Alexander Larsson0b135062013-05-28 16:23:36 +02002140 configured = drm_output_add_mode(output, &modeline);
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03002141 if (!configured)
Scott Moreau8f37e0b2012-07-31 15:30:41 -06002142 goto err_free;
Scott Moreau8f37e0b2012-07-31 15:30:41 -06002143 }
2144
Wang Quanxianacb805a2012-07-30 18:09:46 -04002145 if (current == NULL && crtc_mode.clock != 0) {
Alexander Larsson0b135062013-05-28 16:23:36 +02002146 current = drm_output_add_mode(output, &crtc_mode);
Ander Conselvan de Oliveira42c46462012-08-09 16:45:00 +03002147 if (!current)
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002148 goto err_free;
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002149 }
2150
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002151 if (config == OUTPUT_CONFIG_CURRENT)
Scott Moreau8ab5d452012-07-30 19:51:08 -06002152 configured = current;
2153
Wang Quanxianacb805a2012-07-30 18:09:46 -04002154 if (option_current_mode && current)
Hardeningff39efa2013-09-18 23:56:35 +02002155 output->base.current_mode = &current->base;
Scott Moreau8ab5d452012-07-30 19:51:08 -06002156 else if (configured)
Hardeningff39efa2013-09-18 23:56:35 +02002157 output->base.current_mode = &configured->base;
Wang Quanxianacb805a2012-07-30 18:09:46 -04002158 else if (preferred)
Hardeningff39efa2013-09-18 23:56:35 +02002159 output->base.current_mode = &preferred->base;
Wang Quanxianacb805a2012-07-30 18:09:46 -04002160 else if (current)
Hardeningff39efa2013-09-18 23:56:35 +02002161 output->base.current_mode = &current->base;
Fabien DESSENNE4b255872013-12-12 17:13:56 +01002162 else if (best)
2163 output->base.current_mode = &best->base;
Wang Quanxianacb805a2012-07-30 18:09:46 -04002164
Hardeningff39efa2013-09-18 23:56:35 +02002165 if (output->base.current_mode == NULL) {
Richard Hughesafe690c2013-05-02 10:10:04 +01002166 weston_log("no available modes for %s\n", output->base.name);
Wang Quanxianacb805a2012-07-30 18:09:46 -04002167 goto err_free;
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002168 }
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -04002169
Hardeningff39efa2013-09-18 23:56:35 +02002170 output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
Wang Quanxianacb805a2012-07-30 18:09:46 -04002171
Giulio Camuffo954f1832014-10-11 18:27:30 +03002172 weston_output_init(&output->base, b->compositor, x, y,
John Kåre Alsaker94659272012-11-13 19:10:18 +01002173 connector->mmWidth, connector->mmHeight,
Kristian Høgsberga30989a2013-05-23 17:23:15 -04002174 transform, scale);
John Kåre Alsaker94659272012-11-13 19:10:18 +01002175
Giulio Camuffo954f1832014-10-11 18:27:30 +03002176 if (b->use_pixman) {
2177 if (drm_output_init_pixman(output, b) < 0) {
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02002178 weston_log("Failed to init output pixman state\n");
2179 goto err_output;
2180 }
Giulio Camuffo954f1832014-10-11 18:27:30 +03002181 } else if (drm_output_init_egl(output, b) < 0) {
Ander Conselvan de Oliveira475cf152012-12-14 13:37:29 -02002182 weston_log("Failed to init output gl state\n");
John Kåre Alsaker94659272012-11-13 19:10:18 +01002183 goto err_output;
Kristian Høgsberg1d1e0a52012-10-21 13:29:26 -04002184 }
Kristian Høgsberg8e1f77f2012-05-03 11:39:35 -04002185
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002186 output->backlight = backlight_init(drm_device,
2187 connector->connector_type);
2188 if (output->backlight) {
Kristian Høgsberg220819f2013-05-23 20:29:40 -04002189 weston_log("Initialized backlight, device %s\n",
2190 output->backlight->path);
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002191 output->base.set_backlight = drm_set_backlight;
2192 output->base.backlight_current = drm_get_backlight(output);
Kristian Høgsberg220819f2013-05-23 20:29:40 -04002193 } else {
2194 weston_log("Failed to initialize backlight\n");
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002195 }
2196
Giulio Camuffo954f1832014-10-11 18:27:30 +03002197 weston_compositor_add_output(b->compositor, &output->base);
Kristian Høgsberga4b7e202011-10-24 13:26:32 -04002198
Giulio Camuffo954f1832014-10-11 18:27:30 +03002199 find_and_parse_output_edid(b, output, connector);
Richard Hughesb24e48e2013-05-09 20:31:09 +01002200 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
2201 output->base.connection_internal = 1;
Richard Hughes2b2092a2013-04-24 14:58:02 +01002202
Jonas Ådahle5a12252013-04-05 23:07:11 +02002203 output->base.start_repaint_loop = drm_output_start_repaint_loop;
Kristian Høgsberg68c479a2012-01-25 23:32:28 -05002204 output->base.repaint = drm_output_repaint;
Matt Roper361d2ad2011-08-29 13:52:23 -07002205 output->base.destroy = drm_output_destroy;
Jesse Barnes58ef3792012-02-23 09:45:49 -05002206 output->base.assign_planes = drm_assign_planes;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002207 output->base.set_dpms = drm_set_dpms;
Alex Wub7b8bda2012-04-17 17:20:48 +08002208 output->base.switch_mode = drm_output_switch_mode;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +01002209
Richard Hughese7299962013-05-01 21:52:12 +01002210 output->base.gamma_size = output->original_crtc->gamma_size;
2211 output->base.set_gamma = drm_output_set_gamma;
2212
Giulio Camuffo954f1832014-10-11 18:27:30 +03002213 weston_plane_init(&output->cursor_plane, b->compositor, 0, 0);
2214 weston_plane_init(&output->fb_plane, b->compositor, 0, 0);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04002215
Giulio Camuffo954f1832014-10-11 18:27:30 +03002216 weston_compositor_stack_plane(b->compositor, &output->cursor_plane, NULL);
2217 weston_compositor_stack_plane(b->compositor, &output->fb_plane,
2218 &b->compositor->primary_plane);
Ander Conselvan de Oliveira8ad19822013-03-05 17:30:27 +02002219
Kristian Høgsberg2f9ed712012-07-26 17:57:15 -04002220 weston_log("Output %s, (connector %d, crtc %d)\n",
Richard Hughesafe690c2013-05-02 10:10:04 +01002221 output->base.name, output->connector_id, output->crtc_id);
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002222 wl_list_for_each(m, &output->base.mode_list, link)
U. Artie Eoffd3ed6cb2014-01-10 10:15:17 -08002223 weston_log_continue(STAMP_SPACE "mode %dx%d@%.1f%s%s%s\n",
Kristian Høgsberg061c4252012-06-28 11:28:15 -04002224 m->width, m->height, m->refresh / 1000.0,
2225 m->flags & WL_OUTPUT_MODE_PREFERRED ?
2226 ", preferred" : "",
2227 m->flags & WL_OUTPUT_MODE_CURRENT ?
2228 ", current" : "",
2229 connector->count_modes == 0 ?
2230 ", built-in" : "");
Kristian Høgsbergfc9c5e02012-06-08 16:45:33 -04002231
Mario Kleiner80817042015-06-21 21:25:11 +02002232 /* Set native_ fields, so weston_output_mode_switch_to_native() works */
2233 output->base.native_mode = output->base.current_mode;
2234 output->base.native_scale = output->base.current_scale;
2235
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002236 return 0;
David Herrmann0f0d54e2011-12-08 17:05:45 +01002237
John Kåre Alsaker94659272012-11-13 19:10:18 +01002238err_output:
2239 weston_output_destroy(&output->base);
David Herrmann0f0d54e2011-12-08 17:05:45 +01002240err_free:
2241 wl_list_for_each_safe(drm_mode, next, &output->base.mode_list,
2242 base.link) {
2243 wl_list_remove(&drm_mode->base.link);
2244 free(drm_mode);
2245 }
2246
2247 drmModeFreeCrtc(output->original_crtc);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002248 b->crtc_allocator &= ~(1 << output->crtc_id);
2249 b->connector_allocator &= ~(1 << output->connector_id);
David Herrmann0f0d54e2011-12-08 17:05:45 +01002250 free(output);
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -04002251
David Herrmann0f0d54e2011-12-08 17:05:45 +01002252 return -1;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002253}
2254
Jesse Barnes58ef3792012-02-23 09:45:49 -05002255static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002256create_sprites(struct drm_backend *b)
Jesse Barnes58ef3792012-02-23 09:45:49 -05002257{
2258 struct drm_sprite *sprite;
2259 drmModePlaneRes *plane_res;
2260 drmModePlane *plane;
Kristian Høgsberg875ab9e2012-03-30 11:52:39 -04002261 uint32_t i;
Jesse Barnes58ef3792012-02-23 09:45:49 -05002262
Giulio Camuffo954f1832014-10-11 18:27:30 +03002263 plane_res = drmModeGetPlaneResources(b->drm.fd);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002264 if (!plane_res) {
Martin Minarik6d118362012-06-07 18:01:59 +02002265 weston_log("failed to get plane resources: %s\n",
Jesse Barnes58ef3792012-02-23 09:45:49 -05002266 strerror(errno));
2267 return;
2268 }
2269
2270 for (i = 0; i < plane_res->count_planes; i++) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002271 plane = drmModeGetPlane(b->drm.fd, plane_res->planes[i]);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002272 if (!plane)
2273 continue;
2274
Peter Huttererf3d62272013-08-08 11:57:05 +10002275 sprite = zalloc(sizeof(*sprite) + ((sizeof(uint32_t)) *
Jesse Barnes58ef3792012-02-23 09:45:49 -05002276 plane->count_formats));
2277 if (!sprite) {
Martin Minarik6d118362012-06-07 18:01:59 +02002278 weston_log("%s: out of memory\n",
Jesse Barnes58ef3792012-02-23 09:45:49 -05002279 __func__);
Chris Michael8b376872014-01-02 11:39:40 +00002280 drmModeFreePlane(plane);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002281 continue;
2282 }
2283
Jesse Barnes58ef3792012-02-23 09:45:49 -05002284 sprite->possible_crtcs = plane->possible_crtcs;
2285 sprite->plane_id = plane->plane_id;
Ander Conselvan de Oliveira8d360b42012-11-09 14:19:05 +02002286 sprite->current = NULL;
2287 sprite->next = NULL;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002288 sprite->backend = b;
Jesse Barnes58ef3792012-02-23 09:45:49 -05002289 sprite->count_formats = plane->count_formats;
2290 memcpy(sprite->formats, plane->formats,
Rob Clark8efbc8e2012-03-11 19:48:44 -05002291 plane->count_formats * sizeof(plane->formats[0]));
Jesse Barnes58ef3792012-02-23 09:45:49 -05002292 drmModeFreePlane(plane);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002293 weston_plane_init(&sprite->plane, b->compositor, 0, 0);
2294 weston_compositor_stack_plane(b->compositor, &sprite->plane,
2295 &b->compositor->primary_plane);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002296
Giulio Camuffo954f1832014-10-11 18:27:30 +03002297 wl_list_insert(&b->sprite_list, &sprite->link);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002298 }
2299
Samuel Iglesias Gonsalvezde466732013-06-13 10:03:33 +02002300 drmModeFreePlaneResources(plane_res);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002301}
2302
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002303static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002304destroy_sprites(struct drm_backend *backend)
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002305{
2306 struct drm_sprite *sprite, *next;
2307 struct drm_output *output;
2308
Giulio Camuffo954f1832014-10-11 18:27:30 +03002309 output = container_of(backend->compositor->output_list.next,
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002310 struct drm_output, base.link);
2311
Giulio Camuffo954f1832014-10-11 18:27:30 +03002312 wl_list_for_each_safe(sprite, next, &backend->sprite_list, link) {
2313 drmModeSetPlane(backend->drm.fd,
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002314 sprite->plane_id,
2315 output->crtc_id, 0, 0,
2316 0, 0, 0, 0, 0, 0, 0, 0);
Ander Conselvan de Oliveira526d4612013-01-25 15:13:03 +02002317 drm_output_release_fb(output, sprite->current);
2318 drm_output_release_fb(output, sprite->next);
Kristian Høgsberg65a11e12012-08-03 11:30:18 -04002319 weston_plane_release(&sprite->plane);
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002320 free(sprite);
2321 }
2322}
Jesse Barnes58ef3792012-02-23 09:45:49 -05002323
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002324static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03002325create_outputs(struct drm_backend *b, uint32_t option_connector,
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002326 struct udev_device *drm_device)
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002327{
2328 drmModeConnector *connector;
2329 drmModeRes *resources;
2330 int i;
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +01002331 int x = 0, y = 0;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002332
Giulio Camuffo954f1832014-10-11 18:27:30 +03002333 resources = drmModeGetResources(b->drm.fd);
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002334 if (!resources) {
Martin Minarik6d118362012-06-07 18:01:59 +02002335 weston_log("drmModeGetResources failed\n");
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002336 return -1;
2337 }
2338
Giulio Camuffo954f1832014-10-11 18:27:30 +03002339 b->crtcs = calloc(resources->count_crtcs, sizeof(uint32_t));
2340 if (!b->crtcs) {
Christopher Michaeleb866cd2012-03-07 14:55:21 -05002341 drmModeFreeResources(resources);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002342 return -1;
Christopher Michaeleb866cd2012-03-07 14:55:21 -05002343 }
Jesse Barnes58ef3792012-02-23 09:45:49 -05002344
Giulio Camuffo954f1832014-10-11 18:27:30 +03002345 b->min_width = resources->min_width;
2346 b->max_width = resources->max_width;
2347 b->min_height = resources->min_height;
2348 b->max_height = resources->max_height;
Rob Clark4339add2012-08-09 14:18:28 -05002349
Giulio Camuffo954f1832014-10-11 18:27:30 +03002350 b->num_crtcs = resources->count_crtcs;
2351 memcpy(b->crtcs, resources->crtcs, sizeof(uint32_t) * b->num_crtcs);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002352
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002353 for (i = 0; i < resources->count_connectors; i++) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002354 connector = drmModeGetConnector(b->drm.fd,
Benjamin Franzke117483d2011-08-30 11:38:26 +02002355 resources->connectors[i]);
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002356 if (connector == NULL)
2357 continue;
2358
2359 if (connector->connection == DRM_MODE_CONNECTED &&
2360 (option_connector == 0 ||
Benjamin Franzke9eaee352011-08-02 13:03:54 +02002361 connector->connector_id == option_connector)) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002362 if (create_output_for_connector(b, resources,
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002363 connector, x, y,
2364 drm_device) < 0) {
Benjamin Franzke439d9862011-10-07 08:20:53 +02002365 drmModeFreeConnector(connector);
2366 continue;
2367 }
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002368
Giulio Camuffo954f1832014-10-11 18:27:30 +03002369 x += container_of(b->compositor->output_list.prev,
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002370 struct weston_output,
Scott Moreau1bad5db2012-08-18 01:04:05 -06002371 link)->width;
Benjamin Franzke9eaee352011-08-02 13:03:54 +02002372 }
Benjamin Franzkeeefc36c2011-03-11 16:39:20 +01002373
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002374 drmModeFreeConnector(connector);
2375 }
2376
Giulio Camuffo954f1832014-10-11 18:27:30 +03002377 if (wl_list_empty(&b->compositor->output_list)) {
Martin Minarik6d118362012-06-07 18:01:59 +02002378 weston_log("No currently active connector found.\n");
Christopher Michaeleb866cd2012-03-07 14:55:21 -05002379 drmModeFreeResources(resources);
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002380 return -1;
2381 }
2382
2383 drmModeFreeResources(resources);
2384
2385 return 0;
2386}
2387
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002388static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002389update_outputs(struct drm_backend *b, struct udev_device *drm_device)
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002390{
2391 drmModeConnector *connector;
2392 drmModeRes *resources;
2393 struct drm_output *output, *next;
2394 int x = 0, y = 0;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002395 uint32_t connected = 0, disconnects = 0;
2396 int i;
2397
Giulio Camuffo954f1832014-10-11 18:27:30 +03002398 resources = drmModeGetResources(b->drm.fd);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002399 if (!resources) {
Martin Minarik6d118362012-06-07 18:01:59 +02002400 weston_log("drmModeGetResources failed\n");
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002401 return;
2402 }
2403
2404 /* collect new connects */
2405 for (i = 0; i < resources->count_connectors; i++) {
Benjamin Franzke117483d2011-08-30 11:38:26 +02002406 int connector_id = resources->connectors[i];
2407
Giulio Camuffo954f1832014-10-11 18:27:30 +03002408 connector = drmModeGetConnector(b->drm.fd, connector_id);
David Herrmann7551cff2011-12-08 17:05:43 +01002409 if (connector == NULL)
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002410 continue;
2411
David Herrmann7551cff2011-12-08 17:05:43 +01002412 if (connector->connection != DRM_MODE_CONNECTED) {
2413 drmModeFreeConnector(connector);
2414 continue;
2415 }
2416
Benjamin Franzke117483d2011-08-30 11:38:26 +02002417 connected |= (1 << connector_id);
2418
Giulio Camuffo954f1832014-10-11 18:27:30 +03002419 if (!(b->connector_allocator & (1 << connector_id))) {
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002420 struct weston_output *last =
Giulio Camuffo954f1832014-10-11 18:27:30 +03002421 container_of(b->compositor->output_list.prev,
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002422 struct weston_output, link);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002423
2424 /* XXX: not yet needed, we die with 0 outputs */
Giulio Camuffo954f1832014-10-11 18:27:30 +03002425 if (!wl_list_empty(&b->compositor->output_list))
Scott Moreau1bad5db2012-08-18 01:04:05 -06002426 x = last->x + last->width;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002427 else
2428 x = 0;
2429 y = 0;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002430 create_output_for_connector(b, resources,
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002431 connector, x, y,
2432 drm_device);
Martin Minarik6d118362012-06-07 18:01:59 +02002433 weston_log("connector %d connected\n", connector_id);
Benjamin Franzke117483d2011-08-30 11:38:26 +02002434
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002435 }
2436 drmModeFreeConnector(connector);
2437 }
2438 drmModeFreeResources(resources);
2439
Giulio Camuffo954f1832014-10-11 18:27:30 +03002440 disconnects = b->connector_allocator & ~connected;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002441 if (disconnects) {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002442 wl_list_for_each_safe(output, next, &b->compositor->output_list,
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002443 base.link) {
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002444 if (disconnects & (1 << output->connector_id)) {
2445 disconnects &= ~(1 << output->connector_id);
Martin Minarik6d118362012-06-07 18:01:59 +02002446 weston_log("connector %d disconnected\n",
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002447 output->connector_id);
Benjamin Franzke48c4ea22011-08-30 11:44:56 +02002448 drm_output_destroy(&output->base);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002449 }
2450 }
2451 }
2452
Daniel Stonef556ebe2015-05-21 08:28:58 +01002453 /* FIXME: handle zero outputs, without terminating */
Giulio Camuffo954f1832014-10-11 18:27:30 +03002454 if (b->connector_allocator == 0)
Giulio Camuffo459137b2014-10-11 23:56:24 +03002455 weston_compositor_exit(b->compositor);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002456}
2457
2458static int
Giulio Camuffo954f1832014-10-11 18:27:30 +03002459udev_event_is_hotplug(struct drm_backend *b, struct udev_device *device)
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002460{
David Herrmannd7488c22012-03-11 20:05:21 +01002461 const char *sysnum;
David Herrmann6ac52db2012-03-11 20:05:22 +01002462 const char *val;
David Herrmannd7488c22012-03-11 20:05:21 +01002463
2464 sysnum = udev_device_get_sysnum(device);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002465 if (!sysnum || atoi(sysnum) != b->drm.id)
David Herrmannd7488c22012-03-11 20:05:21 +01002466 return 0;
Benjamin Franzke117483d2011-08-30 11:38:26 +02002467
David Herrmann6ac52db2012-03-11 20:05:22 +01002468 val = udev_device_get_property_value(device, "HOTPLUG");
2469 if (!val)
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002470 return 0;
2471
David Herrmann6ac52db2012-03-11 20:05:22 +01002472 return strcmp(val, "1") == 0;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002473}
2474
Kristian Høgsbergb1868472011-04-22 12:27:57 -04002475static int
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002476udev_drm_event(int fd, uint32_t mask, void *data)
2477{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002478 struct drm_backend *b = data;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002479 struct udev_device *event;
2480
Giulio Camuffo954f1832014-10-11 18:27:30 +03002481 event = udev_monitor_receive_device(b->udev_monitor);
Benjamin Franzke117483d2011-08-30 11:38:26 +02002482
Giulio Camuffo954f1832014-10-11 18:27:30 +03002483 if (udev_event_is_hotplug(b, event))
2484 update_outputs(b, event);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002485
2486 udev_device_unref(event);
Kristian Høgsbergb1868472011-04-22 12:27:57 -04002487
2488 return 1;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002489}
2490
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002491static void
Kristian Høgsberg7b884bc2012-07-31 14:32:01 -04002492drm_restore(struct weston_compositor *ec)
2493{
Kristian Høgsberg3f495872013-09-18 23:00:17 -07002494 weston_launcher_restore(ec->launcher);
Kristian Høgsberg7b884bc2012-07-31 14:32:01 -04002495}
2496
2497static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002498drm_destroy(struct weston_compositor *ec)
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002499{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002500 struct drm_backend *b = (struct drm_backend *) ec->backend;
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002501
Giulio Camuffo954f1832014-10-11 18:27:30 +03002502 udev_input_destroy(&b->input);
Jonas Ådahlc97af922012-03-28 22:36:09 +02002503
Giulio Camuffo954f1832014-10-11 18:27:30 +03002504 wl_event_source_remove(b->udev_drm_source);
2505 wl_event_source_remove(b->drm_source);
Jonas Ådahlc97af922012-03-28 22:36:09 +02002506
Giulio Camuffo954f1832014-10-11 18:27:30 +03002507 destroy_sprites(b);
Kristian Høgsberg3d64a3e2013-05-10 12:36:04 -04002508
Ander Conselvan de Oliveira6b162142013-10-25 16:26:32 +03002509 weston_compositor_shutdown(ec);
2510
Giulio Camuffo954f1832014-10-11 18:27:30 +03002511 if (b->gbm)
2512 gbm_device_destroy(b->gbm);
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02002513
Giulio Camuffo954f1832014-10-11 18:27:30 +03002514 weston_launcher_destroy(ec->launcher);
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002515
Giulio Camuffo954f1832014-10-11 18:27:30 +03002516 close(b->drm.fd);
Rob Bradford45c15b82013-07-26 16:29:35 +01002517
Giulio Camuffo954f1832014-10-11 18:27:30 +03002518 free(b);
Kristian Høgsbergcaa64422010-12-01 16:52:15 -05002519}
2520
Kristian Høgsberg9396fc52011-05-06 15:15:37 -04002521static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002522drm_backend_set_modes(struct drm_backend *backend)
Kristian Høgsberg835cd492012-01-18 11:48:46 -05002523{
2524 struct drm_output *output;
2525 struct drm_mode *drm_mode;
2526 int ret;
2527
Giulio Camuffo954f1832014-10-11 18:27:30 +03002528 wl_list_for_each(output, &backend->compositor->output_list, base.link) {
Ander Conselvan de Oliveira2002f882013-02-26 13:44:58 +02002529 if (!output->current) {
2530 /* If something that would cause the output to
2531 * switch mode happened while in another vt, we
2532 * might not have a current drm_fb. In that case,
2533 * schedule a repaint and let drm_output_repaint
2534 * handle setting the mode. */
2535 weston_output_schedule_repaint(&output->base);
2536 continue;
2537 }
2538
Hardeningff39efa2013-09-18 23:56:35 +02002539 drm_mode = (struct drm_mode *) output->base.current_mode;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002540 ret = drmModeSetCrtc(backend->drm.fd, output->crtc_id,
Ander Conselvan de Oliveira555c17d2012-05-02 16:42:21 +03002541 output->current->fb_id, 0, 0,
Kristian Høgsberg835cd492012-01-18 11:48:46 -05002542 &output->connector_id, 1,
2543 &drm_mode->mode_info);
2544 if (ret < 0) {
Martin Minarik6d118362012-06-07 18:01:59 +02002545 weston_log(
Kristian Høgsbergcbcd0472012-03-11 18:27:41 -04002546 "failed to set mode %dx%d for output at %d,%d: %m\n",
Daniel Stonef556ebe2015-05-21 08:28:58 +01002547 drm_mode->base.width, drm_mode->base.height,
Kristian Høgsberg835cd492012-01-18 11:48:46 -05002548 output->base.x, output->base.y);
2549 }
2550 }
2551}
2552
2553static void
Kristian Høgsberg61741a22013-09-17 16:02:57 -07002554session_notify(struct wl_listener *listener, void *data)
Kristian Høgsberg9396fc52011-05-06 15:15:37 -04002555{
Kristian Høgsberg61741a22013-09-17 16:02:57 -07002556 struct weston_compositor *compositor = data;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002557 struct drm_backend *b = (struct drm_backend *)compositor->backend;
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002558 struct drm_sprite *sprite;
Kristian Høgsberga6edab32012-07-14 01:06:28 -04002559 struct drm_output *output;
Kristian Høgsberg9396fc52011-05-06 15:15:37 -04002560
Giulio Camuffo954f1832014-10-11 18:27:30 +03002561 if (compositor->session_active) {
Kristian Høgsberg61741a22013-09-17 16:02:57 -07002562 weston_log("activating session\n");
Giulio Camuffo954f1832014-10-11 18:27:30 +03002563 compositor->state = b->prev_state;
2564 drm_backend_set_modes(b);
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002565 weston_compositor_damage_all(compositor);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002566 udev_input_enable(&b->input);
Kristian Høgsberg61741a22013-09-17 16:02:57 -07002567 } else {
2568 weston_log("deactivating session\n");
Giulio Camuffo954f1832014-10-11 18:27:30 +03002569 udev_input_disable(&b->input);
Kristian Høgsberg4014a6b2012-04-10 00:08:45 -04002570
Giulio Camuffo954f1832014-10-11 18:27:30 +03002571 b->prev_state = compositor->state;
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01002572 weston_compositor_offscreen(compositor);
Kristian Høgsbergd8e181b2011-05-06 15:38:28 -04002573
Kristian Høgsberg34f80ff2012-01-18 11:50:31 -05002574 /* If we have a repaint scheduled (either from a
2575 * pending pageflip or the idle handler), make sure we
2576 * cancel that so we don't try to pageflip when we're
Philipp Brüschweiler57edf7f2013-03-29 13:01:56 +01002577 * vt switched away. The OFFSCREEN state will prevent
Kristian Høgsberg34f80ff2012-01-18 11:50:31 -05002578 * further attemps at repainting. When we switch
2579 * back, we schedule a repaint, which will process
2580 * pending frame callbacks. */
2581
Giulio Camuffo954f1832014-10-11 18:27:30 +03002582 wl_list_for_each(output, &compositor->output_list, base.link) {
Kristian Høgsberga6edab32012-07-14 01:06:28 -04002583 output->base.repaint_needed = 0;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002584 drmModeSetCursor(b->drm.fd, output->crtc_id, 0, 0, 0);
Kristian Høgsberg34f80ff2012-01-18 11:50:31 -05002585 }
2586
Giulio Camuffo954f1832014-10-11 18:27:30 +03002587 output = container_of(compositor->output_list.next,
Kristian Høgsberga6edab32012-07-14 01:06:28 -04002588 struct drm_output, base.link);
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002589
Giulio Camuffo954f1832014-10-11 18:27:30 +03002590 wl_list_for_each(sprite, &b->sprite_list, link)
2591 drmModeSetPlane(b->drm.fd,
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002592 sprite->plane_id,
Kristian Høgsberga6edab32012-07-14 01:06:28 -04002593 output->crtc_id, 0, 0,
Kristian Høgsberg85fd3272012-02-23 21:45:32 -05002594 0, 0, 0, 0, 0, 0, 0, 0);
Kristian Høgsberg9396fc52011-05-06 15:15:37 -04002595 };
2596}
2597
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -04002598static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04002599switch_vt_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -04002600{
Kristian Høgsberg3f495872013-09-18 23:00:17 -07002601 struct weston_compositor *compositor = data;
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -04002602
Kristian Høgsberg3f495872013-09-18 23:00:17 -07002603 weston_launcher_activate_vt(compositor->launcher, key - KEY_F1 + 1);
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -04002604}
2605
David Herrmann0af066f2012-10-29 19:21:16 +01002606/*
2607 * Find primary GPU
2608 * Some systems may have multiple DRM devices attached to a single seat. This
2609 * function loops over all devices and tries to find a PCI device with the
2610 * boot_vga sysfs attribute set to 1.
2611 * If no such device is found, the first DRM device reported by udev is used.
2612 */
2613static struct udev_device*
Giulio Camuffo954f1832014-10-11 18:27:30 +03002614find_primary_gpu(struct drm_backend *b, const char *seat)
David Herrmann0af066f2012-10-29 19:21:16 +01002615{
2616 struct udev_enumerate *e;
2617 struct udev_list_entry *entry;
2618 const char *path, *device_seat, *id;
2619 struct udev_device *device, *drm_device, *pci;
2620
Giulio Camuffo954f1832014-10-11 18:27:30 +03002621 e = udev_enumerate_new(b->udev);
David Herrmann0af066f2012-10-29 19:21:16 +01002622 udev_enumerate_add_match_subsystem(e, "drm");
2623 udev_enumerate_add_match_sysname(e, "card[0-9]*");
2624
2625 udev_enumerate_scan_devices(e);
2626 drm_device = NULL;
2627 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
2628 path = udev_list_entry_get_name(entry);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002629 device = udev_device_new_from_syspath(b->udev, path);
David Herrmann0af066f2012-10-29 19:21:16 +01002630 if (!device)
2631 continue;
2632 device_seat = udev_device_get_property_value(device, "ID_SEAT");
2633 if (!device_seat)
2634 device_seat = default_seat;
2635 if (strcmp(device_seat, seat)) {
2636 udev_device_unref(device);
2637 continue;
2638 }
2639
2640 pci = udev_device_get_parent_with_subsystem_devtype(device,
2641 "pci", NULL);
2642 if (pci) {
2643 id = udev_device_get_sysattr_value(pci, "boot_vga");
2644 if (id && !strcmp(id, "1")) {
2645 if (drm_device)
2646 udev_device_unref(drm_device);
2647 drm_device = device;
2648 break;
2649 }
2650 }
2651
2652 if (!drm_device)
2653 drm_device = device;
2654 else
2655 udev_device_unref(device);
2656 }
2657
2658 udev_enumerate_unref(e);
2659 return drm_device;
2660}
2661
Ander Conselvan de Oliveirada1c9082012-10-31 17:55:46 +02002662static void
Kristian Høgsberge3148752013-05-06 23:19:49 -04002663planes_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
Ander Conselvan de Oliveirada1c9082012-10-31 17:55:46 +02002664{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002665 struct drm_backend *b = data;
Ander Conselvan de Oliveirada1c9082012-10-31 17:55:46 +02002666
Ander Conselvan de Oliveira7e918da2012-11-22 15:56:59 +02002667 switch (key) {
2668 case KEY_C:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002669 b->cursors_are_broken ^= 1;
Ander Conselvan de Oliveira7e918da2012-11-22 15:56:59 +02002670 break;
2671 case KEY_V:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002672 b->sprites_are_broken ^= 1;
Ander Conselvan de Oliveira7e918da2012-11-22 15:56:59 +02002673 break;
2674 case KEY_O:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002675 b->sprites_hidden ^= 1;
Ander Conselvan de Oliveira7e918da2012-11-22 15:56:59 +02002676 break;
2677 default:
2678 break;
2679 }
Ander Conselvan de Oliveira180f42a2012-11-21 15:11:37 +02002680}
2681
Kristian Høgsberg0eac34a2013-08-30 14:28:22 -07002682#ifdef BUILD_VAAPI_RECORDER
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002683static void
Ander Conselvan de Oliveira2d13fde2014-05-09 15:57:38 +03002684recorder_destroy(struct drm_output *output)
2685{
2686 vaapi_recorder_destroy(output->recorder);
2687 output->recorder = NULL;
2688
2689 output->base.disable_planes--;
2690
2691 wl_list_remove(&output->recorder_frame_listener.link);
2692 weston_log("[libva recorder] done\n");
2693}
2694
2695static void
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002696recorder_frame_notify(struct wl_listener *listener, void *data)
2697{
2698 struct drm_output *output;
Giulio Camuffo954f1832014-10-11 18:27:30 +03002699 struct drm_backend *b;
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002700 int fd, ret;
2701
2702 output = container_of(listener, struct drm_output,
2703 recorder_frame_listener);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002704 b = (struct drm_backend *)output->base.compositor->backend;
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002705
2706 if (!output->recorder)
2707 return;
2708
Giulio Camuffo954f1832014-10-11 18:27:30 +03002709 ret = drmPrimeHandleToFD(b->drm.fd, output->current->handle,
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002710 DRM_CLOEXEC, &fd);
2711 if (ret) {
2712 weston_log("[libva recorder] "
2713 "failed to create prime fd for front buffer\n");
2714 return;
2715 }
2716
Ander Conselvan de Oliveira2d13fde2014-05-09 15:57:38 +03002717 ret = vaapi_recorder_frame(output->recorder, fd,
2718 output->current->stride);
2719 if (ret < 0) {
2720 weston_log("[libva recorder] aborted: %m\n");
2721 recorder_destroy(output);
2722 }
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002723}
2724
2725static void *
Giulio Camuffo954f1832014-10-11 18:27:30 +03002726create_recorder(struct drm_backend *b, int width, int height,
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002727 const char *filename)
2728{
2729 int fd;
2730 drm_magic_t magic;
2731
Giulio Camuffo954f1832014-10-11 18:27:30 +03002732 fd = open(b->drm.filename, O_RDWR | O_CLOEXEC);
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002733 if (fd < 0)
2734 return NULL;
2735
2736 drmGetMagic(fd, &magic);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002737 drmAuthMagic(b->drm.fd, magic);
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002738
2739 return vaapi_recorder_create(fd, width, height, filename);
2740}
2741
2742static void
2743recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2744 void *data)
2745{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002746 struct drm_backend *b = data;
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002747 struct drm_output *output;
2748 int width, height;
2749
Giulio Camuffo954f1832014-10-11 18:27:30 +03002750 output = container_of(b->compositor->output_list.next,
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002751 struct drm_output, base.link);
2752
2753 if (!output->recorder) {
Ander Conselvan de Oliveira2ef1cd12014-05-06 16:49:06 +03002754 if (output->format != GBM_FORMAT_XRGB8888) {
2755 weston_log("failed to start vaapi recorder: "
2756 "output format not supported\n");
2757 return;
2758 }
2759
Hardeningff39efa2013-09-18 23:56:35 +02002760 width = output->base.current_mode->width;
2761 height = output->base.current_mode->height;
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002762
2763 output->recorder =
Giulio Camuffo954f1832014-10-11 18:27:30 +03002764 create_recorder(b, width, height, "capture.h264");
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002765 if (!output->recorder) {
2766 weston_log("failed to create vaapi recorder\n");
2767 return;
2768 }
2769
2770 output->base.disable_planes++;
2771
2772 output->recorder_frame_listener.notify = recorder_frame_notify;
2773 wl_signal_add(&output->base.frame_signal,
2774 &output->recorder_frame_listener);
2775
2776 weston_output_schedule_repaint(&output->base);
2777
2778 weston_log("[libva recorder] initialized\n");
2779 } else {
Ander Conselvan de Oliveira2d13fde2014-05-09 15:57:38 +03002780 recorder_destroy(output);
Ander Conselvan de Oliveira6aae4d32013-08-23 17:15:48 +03002781 }
2782}
2783#else
2784static void
2785recorder_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2786 void *data)
2787{
2788 weston_log("Compiled without libva support\n");
2789}
2790#endif
2791
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002792static void
Giulio Camuffo954f1832014-10-11 18:27:30 +03002793switch_to_gl_renderer(struct drm_backend *b)
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002794{
2795 struct drm_output *output;
2796
Giulio Camuffo954f1832014-10-11 18:27:30 +03002797 if (!b->use_pixman)
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002798 return;
2799
2800 weston_log("Switching to GL renderer\n");
2801
Giulio Camuffo954f1832014-10-11 18:27:30 +03002802 b->gbm = create_gbm_device(b->drm.fd);
2803 if (!b->gbm) {
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002804 weston_log("Failed to create gbm device. "
2805 "Aborting renderer switch\n");
2806 return;
2807 }
2808
Giulio Camuffo954f1832014-10-11 18:27:30 +03002809 wl_list_for_each(output, &b->compositor->output_list, base.link)
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002810 pixman_renderer_output_destroy(&output->base);
2811
Giulio Camuffo954f1832014-10-11 18:27:30 +03002812 b->compositor->renderer->destroy(b->compositor);
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002813
Giulio Camuffo954f1832014-10-11 18:27:30 +03002814 if (drm_backend_create_gl_renderer(b) < 0) {
2815 gbm_device_destroy(b->gbm);
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002816 weston_log("Failed to create GL renderer. Quitting.\n");
2817 /* FIXME: we need a function to shutdown cleanly */
2818 assert(0);
2819 }
2820
Giulio Camuffo954f1832014-10-11 18:27:30 +03002821 wl_list_for_each(output, &b->compositor->output_list, base.link)
2822 drm_output_init_egl(output, b);
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002823
Giulio Camuffo954f1832014-10-11 18:27:30 +03002824 b->use_pixman = 0;
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002825}
2826
2827static void
2828renderer_switch_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2829 void *data)
2830{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002831 struct drm_backend *b = (struct drm_backend *)seat->compositor->backend;
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002832
Giulio Camuffo954f1832014-10-11 18:27:30 +03002833 switch_to_gl_renderer(b);
Ander Conselvan de Oliveira65796812013-11-19 15:22:04 +02002834}
2835
Giulio Camuffo954f1832014-10-11 18:27:30 +03002836static struct drm_backend *
2837drm_backend_create(struct weston_compositor *compositor,
Kristian Høgsbergd8e98332013-10-16 16:15:11 -07002838 struct drm_parameters *param,
Kristian Høgsberg14e438c2013-05-26 21:48:14 -04002839 int *argc, char *argv[],
2840 struct weston_config *config)
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002841{
Giulio Camuffo954f1832014-10-11 18:27:30 +03002842 struct drm_backend *b;
Kristian Høgsberg8e6f3762013-10-16 16:31:42 -07002843 struct weston_config_section *section;
David Herrmann0af066f2012-10-29 19:21:16 +01002844 struct udev_device *drm_device;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002845 struct wl_event_loop *loop;
David Herrmann0af066f2012-10-29 19:21:16 +01002846 const char *path;
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -04002847 uint32_t key;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002848
Kristian Høgsbergfc9c5e02012-06-08 16:45:33 -04002849 weston_log("initializing drm backend\n");
2850
Giulio Camuffo954f1832014-10-11 18:27:30 +03002851 b = zalloc(sizeof *b);
2852 if (b == NULL)
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04002853 return NULL;
Daniel Stone725c2c32012-06-22 14:04:36 +01002854
Pekka Paalanen68583832015-05-19 09:53:16 +03002855 /*
2856 * KMS support for hardware planes cannot properly synchronize
2857 * without nuclear page flip. Without nuclear/atomic, hw plane
2858 * and cursor plane updates would either tear or cause extra
2859 * waits for vblanks which means dropping the compositor framerate
2860 * to a fraction.
2861 *
2862 * These can be enabled again when nuclear/atomic support lands.
2863 */
Giulio Camuffo954f1832014-10-11 18:27:30 +03002864 b->sprites_are_broken = 1;
2865 b->cursors_are_broken = 1;
2866 b->compositor = compositor;
Kristian Høgsberg8e6f3762013-10-16 16:31:42 -07002867
2868 section = weston_config_get_section(config, "core", NULL, NULL);
Neil Roberts77c1a5b2014-03-07 18:05:50 +00002869 if (get_gbm_format_from_section(section,
2870 GBM_FORMAT_XRGB8888,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002871 &b->format) == -1)
Kristian Høgsberg8e6f3762013-10-16 16:31:42 -07002872 goto err_base;
Kristian Høgsberg8e6f3762013-10-16 16:31:42 -07002873
Giulio Camuffo954f1832014-10-11 18:27:30 +03002874 b->use_pixman = param->use_pixman;
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02002875
Rafal Mielniczuk32069c02013-03-27 18:39:28 +01002876 /* Check if we run drm-backend using weston-launch */
Giulio Camuffo954f1832014-10-11 18:27:30 +03002877 compositor->launcher = weston_launcher_connect(compositor, param->tty,
2878 param->seat_id, true);
2879 if (compositor->launcher == NULL) {
Rafal Mielniczuk32069c02013-03-27 18:39:28 +01002880 weston_log("fatal: drm backend should be run "
Kristian Høgsbergb76237e2013-04-04 21:36:20 -04002881 "using weston-launch binary or as root\n");
Rafal Mielniczuk32069c02013-03-27 18:39:28 +01002882 goto err_compositor;
2883 }
2884
Giulio Camuffo954f1832014-10-11 18:27:30 +03002885 b->udev = udev_new();
2886 if (b->udev == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02002887 weston_log("failed to initialize udev context\n");
Kristian Høgsberg3f495872013-09-18 23:00:17 -07002888 goto err_launcher;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002889 }
2890
Giulio Camuffo954f1832014-10-11 18:27:30 +03002891 b->session_listener.notify = session_notify;
2892 wl_signal_add(&compositor->session_signal, &b->session_listener);
Kristian Høgsbergc5b9ddb2012-01-15 14:29:09 -05002893
Giulio Camuffo954f1832014-10-11 18:27:30 +03002894 drm_device = find_primary_gpu(b, param->seat_id);
Kristian Høgsberg8d51f142011-07-15 21:28:38 -04002895 if (drm_device == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02002896 weston_log("no drm device found\n");
Kristian Høgsberg3f495872013-09-18 23:00:17 -07002897 goto err_udev;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04002898 }
David Herrmann0af066f2012-10-29 19:21:16 +01002899 path = udev_device_get_syspath(drm_device);
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04002900
Giulio Camuffo954f1832014-10-11 18:27:30 +03002901 if (init_drm(b, drm_device) < 0) {
Ander Conselvan de Oliveira22929172013-01-25 15:13:02 +02002902 weston_log("failed to initialize kms\n");
2903 goto err_udev_dev;
2904 }
2905
Giulio Camuffo954f1832014-10-11 18:27:30 +03002906 if (b->use_pixman) {
2907 if (init_pixman(b) < 0) {
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02002908 weston_log("failed to initialize pixman renderer\n");
2909 goto err_udev_dev;
2910 }
2911 } else {
Giulio Camuffo954f1832014-10-11 18:27:30 +03002912 if (init_egl(b) < 0) {
Ander Conselvan de Oliveira5fb44142013-01-25 15:13:05 +02002913 weston_log("failed to initialize egl\n");
2914 goto err_udev_dev;
2915 }
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04002916 }
Kristian Høgsberg8525a502011-01-14 16:20:21 -05002917
Giulio Camuffo954f1832014-10-11 18:27:30 +03002918 b->base.destroy = drm_destroy;
2919 b->base.restore = drm_restore;
Benjamin Franzke431da9a2011-04-20 11:02:58 +02002920
Giulio Camuffo954f1832014-10-11 18:27:30 +03002921 b->prev_state = WESTON_COMPOSITOR_ACTIVE;
Pekka Paalanenbce2d3f2011-12-02 13:07:27 +02002922
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -04002923 for (key = KEY_F1; key < KEY_F9; key++)
Giulio Camuffo954f1832014-10-11 18:27:30 +03002924 weston_compositor_add_key_binding(compositor, key,
Daniel Stone325fc2d2012-05-30 16:31:58 +01002925 MODIFIER_CTRL | MODIFIER_ALT,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002926 switch_vt_binding, compositor);
Kristian Høgsberg5d1c0c52012-04-10 00:11:50 -04002927
Giulio Camuffo954f1832014-10-11 18:27:30 +03002928 wl_list_init(&b->sprite_list);
2929 create_sprites(b);
Jesse Barnes58ef3792012-02-23 09:45:49 -05002930
Giulio Camuffo954f1832014-10-11 18:27:30 +03002931 if (udev_input_init(&b->input,
2932 compositor, b->udev, param->seat_id) < 0) {
Ander Conselvan de Oliveira4ade0e42014-04-17 13:08:45 +03002933 weston_log("failed to create input devices\n");
2934 goto err_sprite;
2935 }
2936
Giulio Camuffo954f1832014-10-11 18:27:30 +03002937 if (create_outputs(b, param->connector, drm_device) < 0) {
Martin Minarik6d118362012-06-07 18:01:59 +02002938 weston_log("failed to create output for %s\n", path);
Ander Conselvan de Oliveira4ade0e42014-04-17 13:08:45 +03002939 goto err_udev_input;
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04002940 }
2941
Jason Ekstrand9fc71512014-04-02 19:53:46 -05002942 /* A this point we have some idea of whether or not we have a working
2943 * cursor plane. */
Giulio Camuffo954f1832014-10-11 18:27:30 +03002944 if (!b->cursors_are_broken)
2945 compositor->capabilities |= WESTON_CAP_CURSOR_PLANE;
Jason Ekstrand9fc71512014-04-02 19:53:46 -05002946
Benjamin Franzke02dee2c2011-10-07 08:27:26 +02002947 path = NULL;
2948
Giulio Camuffo954f1832014-10-11 18:27:30 +03002949 loop = wl_display_get_event_loop(compositor->wl_display);
2950 b->drm_source =
2951 wl_event_loop_add_fd(loop, b->drm.fd,
2952 WL_EVENT_READABLE, on_drm_input, b);
Kristian Høgsbergce5325d2010-06-14 11:54:00 -04002953
Giulio Camuffo954f1832014-10-11 18:27:30 +03002954 b->udev_monitor = udev_monitor_new_from_netlink(b->udev, "udev");
2955 if (b->udev_monitor == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02002956 weston_log("failed to intialize udev monitor\n");
Daniel Stonea96b93c2012-06-22 14:04:37 +01002957 goto err_drm_source;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002958 }
Giulio Camuffo954f1832014-10-11 18:27:30 +03002959 udev_monitor_filter_add_match_subsystem_devtype(b->udev_monitor,
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002960 "drm", NULL);
Giulio Camuffo954f1832014-10-11 18:27:30 +03002961 b->udev_drm_source =
Benjamin Franzke117483d2011-08-30 11:38:26 +02002962 wl_event_loop_add_fd(loop,
Giulio Camuffo954f1832014-10-11 18:27:30 +03002963 udev_monitor_get_fd(b->udev_monitor),
2964 WL_EVENT_READABLE, udev_drm_event, b);
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002965
Giulio Camuffo954f1832014-10-11 18:27:30 +03002966 if (udev_monitor_enable_receiving(b->udev_monitor) < 0) {
Martin Minarik6d118362012-06-07 18:01:59 +02002967 weston_log("failed to enable udev-monitor receiving\n");
Daniel Stonea96b93c2012-06-22 14:04:37 +01002968 goto err_udev_monitor;
Benjamin Franzke9c26ff32011-03-15 15:08:41 +01002969 }
2970
Daniel Stonea96b93c2012-06-22 14:04:37 +01002971 udev_device_unref(drm_device);
Daniel Stonea96b93c2012-06-22 14:04:37 +01002972
Giulio Camuffo954f1832014-10-11 18:27:30 +03002973 weston_compositor_add_debug_binding(compositor, KEY_O,
2974 planes_binding, b);
2975 weston_compositor_add_debug_binding(compositor, KEY_C,
2976 planes_binding, b);
2977 weston_compositor_add_debug_binding(compositor, KEY_V,
2978 planes_binding, b);
2979 weston_compositor_add_debug_binding(compositor, KEY_Q,
2980 recorder_binding, b);
2981 weston_compositor_add_debug_binding(compositor, KEY_W,
2982 renderer_switch_binding, b);
Ander Conselvan de Oliveirada1c9082012-10-31 17:55:46 +02002983
Giulio Camuffo954f1832014-10-11 18:27:30 +03002984 compositor->backend = &b->base;
2985 return b;
Daniel Stonea96b93c2012-06-22 14:04:37 +01002986
2987err_udev_monitor:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002988 wl_event_source_remove(b->udev_drm_source);
2989 udev_monitor_unref(b->udev_monitor);
Daniel Stonea96b93c2012-06-22 14:04:37 +01002990err_drm_source:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002991 wl_event_source_remove(b->drm_source);
Ander Conselvan de Oliveira4ade0e42014-04-17 13:08:45 +03002992err_udev_input:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002993 udev_input_destroy(&b->input);
Kristian Høgsberg2bc5e8e2012-09-06 20:51:00 -04002994err_sprite:
Giulio Camuffo954f1832014-10-11 18:27:30 +03002995 compositor->renderer->destroy(compositor);
2996 gbm_device_destroy(b->gbm);
2997 destroy_sprites(b);
Daniel Stonea96b93c2012-06-22 14:04:37 +01002998err_udev_dev:
2999 udev_device_unref(drm_device);
Kristian Høgsberg3f495872013-09-18 23:00:17 -07003000err_launcher:
Giulio Camuffo954f1832014-10-11 18:27:30 +03003001 weston_launcher_destroy(compositor->launcher);
Daniel Stonea96b93c2012-06-22 14:04:37 +01003002err_udev:
Giulio Camuffo954f1832014-10-11 18:27:30 +03003003 udev_unref(b->udev);
Daniel Stonea96b93c2012-06-22 14:04:37 +01003004err_compositor:
Giulio Camuffo954f1832014-10-11 18:27:30 +03003005 weston_compositor_shutdown(compositor);
Daniel Stonea96b93c2012-06-22 14:04:37 +01003006err_base:
Giulio Camuffo954f1832014-10-11 18:27:30 +03003007 free(b);
Daniel Stonea96b93c2012-06-22 14:04:37 +01003008 return NULL;
Kristian Høgsbergfc783d42010-06-11 12:56:24 -04003009}
Kristian Høgsberg1c562182011-05-02 22:09:20 -04003010
Giulio Camuffo954f1832014-10-11 18:27:30 +03003011WL_EXPORT int
3012backend_init(struct weston_compositor *compositor, int *argc, char *argv[],
Kristian Høgsberg14e438c2013-05-26 21:48:14 -04003013 struct weston_config *config)
Kristian Høgsberg1c562182011-05-02 22:09:20 -04003014{
Giulio Camuffo954f1832014-10-11 18:27:30 +03003015 struct drm_backend *b;
Kristian Høgsbergd8e98332013-10-16 16:15:11 -07003016 struct drm_parameters param = { 0, };
Kristian Høgsberg1c562182011-05-02 22:09:20 -04003017
Kristian Høgsbergbcacef12012-03-11 21:05:57 -04003018 const struct weston_option drm_options[] = {
Kristian Høgsbergd8e98332013-10-16 16:15:11 -07003019 { WESTON_OPTION_INTEGER, "connector", 0, &param.connector },
3020 { WESTON_OPTION_STRING, "seat", 0, &param.seat_id },
3021 { WESTON_OPTION_INTEGER, "tty", 0, &param.tty },
Kristian Høgsberg061c4252012-06-28 11:28:15 -04003022 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &option_current_mode },
Kristian Høgsbergd8e98332013-10-16 16:15:11 -07003023 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &param.use_pixman },
Kristian Høgsbergbcacef12012-03-11 21:05:57 -04003024 };
Benjamin Franzke117483d2011-08-30 11:38:26 +02003025
Kristian Høgsbergd8e98332013-10-16 16:15:11 -07003026 param.seat_id = default_seat;
3027
Kristian Høgsbergbcacef12012-03-11 21:05:57 -04003028 parse_options(drm_options, ARRAY_LENGTH(drm_options), argc, argv);
Kristian Høgsberg1c562182011-05-02 22:09:20 -04003029
Giulio Camuffo954f1832014-10-11 18:27:30 +03003030 b = drm_backend_create(compositor, &param, argc, argv, config);
3031 if (b == NULL)
3032 return -1;
3033 return 0;
Kristian Høgsberg1c562182011-05-02 22:09:20 -04003034}