8ee80996a4ff051247ec7aaab48b3f2290775fca
[mesa.git] / src / gallium / state_trackers / egl / kms / native_kms.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.8
4 *
5 * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25
26 #include "pipe/p_screen.h"
27 #include "pipe/p_context.h"
28 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/u_pointer.h"
32 #include "util/u_string.h"
33 #include "egllog.h"
34
35 #include "native_kms.h"
36 #include "state_tracker/drm_driver.h"
37
38 static boolean
39 kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
40 unsigned int *seq_num, struct pipe_resource **textures,
41 int *width, int *height)
42 {
43 struct kms_surface *ksurf = kms_surface(nsurf);
44
45 if (!resource_surface_add_resources(ksurf->rsurf, attachment_mask))
46 return FALSE;
47 if (textures)
48 resource_surface_get_resources(ksurf->rsurf, textures, attachment_mask);
49
50 if (seq_num)
51 *seq_num = ksurf->sequence_number;
52 if (width)
53 *width = ksurf->width;
54 if (height)
55 *height = ksurf->height;
56
57 return TRUE;
58 }
59
60 /**
61 * Add textures as DRM framebuffers.
62 */
63 static boolean
64 kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
65 {
66 struct kms_surface *ksurf = kms_surface(nsurf);
67 struct kms_display *kdpy = ksurf->kdpy;
68 int num_framebuffers = (need_back) ? 2 : 1;
69 int i, err;
70
71 for (i = 0; i < num_framebuffers; i++) {
72 struct kms_framebuffer *fb;
73 enum native_attachment natt;
74 struct winsys_handle whandle;
75 uint block_bits;
76
77 if (i == 0) {
78 fb = &ksurf->front_fb;
79 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
80 }
81 else {
82 fb = &ksurf->back_fb;
83 natt = NATIVE_ATTACHMENT_BACK_LEFT;
84 }
85
86 if (!fb->texture) {
87 /* make sure the texture has been allocated */
88 resource_surface_add_resources(ksurf->rsurf, 1 << natt);
89 fb->texture =
90 resource_surface_get_single_resource(ksurf->rsurf, natt);
91 if (!fb->texture)
92 return FALSE;
93 }
94
95 /* already initialized */
96 if (fb->buffer_id)
97 continue;
98
99 /* TODO detect the real value */
100 fb->is_passive = TRUE;
101
102 memset(&whandle, 0, sizeof(whandle));
103 whandle.type = DRM_API_HANDLE_TYPE_KMS;
104
105 if (!kdpy->base.screen->resource_get_handle(kdpy->base.screen,
106 fb->texture, &whandle))
107 return FALSE;
108
109 block_bits = util_format_get_blocksizebits(ksurf->color_format);
110 err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height,
111 block_bits, block_bits, whandle.stride, whandle.handle,
112 &fb->buffer_id);
113 if (err) {
114 fb->buffer_id = 0;
115 return FALSE;
116 }
117 }
118
119 return TRUE;
120 }
121
122 static boolean
123 kms_surface_flush_frontbuffer(struct native_surface *nsurf)
124 {
125 #ifdef DRM_MODE_FEATURE_DIRTYFB
126 struct kms_surface *ksurf = kms_surface(nsurf);
127 struct kms_display *kdpy = ksurf->kdpy;
128
129 if (ksurf->front_fb.is_passive)
130 drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
131 #endif
132
133 return TRUE;
134 }
135
136 static boolean
137 kms_surface_swap_buffers(struct native_surface *nsurf)
138 {
139 struct kms_surface *ksurf = kms_surface(nsurf);
140 struct kms_crtc *kcrtc = &ksurf->current_crtc;
141 struct kms_display *kdpy = ksurf->kdpy;
142 struct kms_framebuffer tmp_fb;
143 int err;
144
145 if (!ksurf->back_fb.buffer_id) {
146 if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
147 return FALSE;
148 }
149
150 if (ksurf->is_shown && kcrtc->crtc) {
151 err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
152 ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
153 kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
154 if (err)
155 return FALSE;
156 }
157
158 /* swap the buffers */
159 tmp_fb = ksurf->front_fb;
160 ksurf->front_fb = ksurf->back_fb;
161 ksurf->back_fb = tmp_fb;
162
163 resource_surface_swap_buffers(ksurf->rsurf,
164 NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
165 /* the front/back textures are swapped */
166 ksurf->sequence_number++;
167 kdpy->event_handler->invalid_surface(&kdpy->base,
168 &ksurf->base, ksurf->sequence_number);
169
170 return TRUE;
171 }
172
173 static void
174 kms_surface_wait(struct native_surface *nsurf)
175 {
176 /* no-op */
177 }
178
179 static void
180 kms_surface_destroy(struct native_surface *nsurf)
181 {
182 struct kms_surface *ksurf = kms_surface(nsurf);
183
184 if (ksurf->current_crtc.crtc)
185 drmModeFreeCrtc(ksurf->current_crtc.crtc);
186
187 if (ksurf->front_fb.buffer_id)
188 drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id);
189 pipe_resource_reference(&ksurf->front_fb.texture, NULL);
190
191 if (ksurf->back_fb.buffer_id)
192 drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id);
193 pipe_resource_reference(&ksurf->back_fb.texture, NULL);
194
195 resource_surface_destroy(ksurf->rsurf);
196 FREE(ksurf);
197 }
198
199 static struct kms_surface *
200 kms_display_create_surface(struct native_display *ndpy,
201 const struct native_config *nconf,
202 uint width, uint height)
203 {
204 struct kms_display *kdpy = kms_display(ndpy);
205 struct kms_config *kconf = kms_config(nconf);
206 struct kms_surface *ksurf;
207
208 ksurf = CALLOC_STRUCT(kms_surface);
209 if (!ksurf)
210 return NULL;
211
212 ksurf->kdpy = kdpy;
213 ksurf->color_format = kconf->base.color_format;
214 ksurf->width = width;
215 ksurf->height = height;
216
217 ksurf->rsurf = resource_surface_create(kdpy->base.screen,
218 ksurf->color_format,
219 PIPE_BIND_RENDER_TARGET |
220 PIPE_BIND_SAMPLER_VIEW |
221 PIPE_BIND_DISPLAY_TARGET |
222 PIPE_BIND_SCANOUT);
223 if (!ksurf->rsurf) {
224 FREE(ksurf);
225 return NULL;
226 }
227
228 resource_surface_set_size(ksurf->rsurf, ksurf->width, ksurf->height);
229
230 ksurf->base.destroy = kms_surface_destroy;
231 ksurf->base.swap_buffers = kms_surface_swap_buffers;
232 ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
233 ksurf->base.validate = kms_surface_validate;
234 ksurf->base.wait = kms_surface_wait;
235
236 return ksurf;
237 }
238
239 /**
240 * Choose a CRTC that supports all given connectors.
241 */
242 static uint32_t
243 kms_display_choose_crtc(struct native_display *ndpy,
244 uint32_t *connectors, int num_connectors)
245 {
246 struct kms_display *kdpy = kms_display(ndpy);
247 int idx;
248
249 for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
250 boolean found_crtc = TRUE;
251 int i, j;
252
253 for (i = 0; i < num_connectors; i++) {
254 drmModeConnectorPtr connector;
255 int encoder_idx = -1;
256
257 connector = drmModeGetConnector(kdpy->fd, connectors[i]);
258 if (!connector) {
259 found_crtc = FALSE;
260 break;
261 }
262
263 /* find an encoder the CRTC supports */
264 for (j = 0; j < connector->count_encoders; j++) {
265 drmModeEncoderPtr encoder =
266 drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
267 if (encoder->possible_crtcs & (1 << idx)) {
268 encoder_idx = j;
269 break;
270 }
271 drmModeFreeEncoder(encoder);
272 }
273
274 drmModeFreeConnector(connector);
275 if (encoder_idx < 0) {
276 found_crtc = FALSE;
277 break;
278 }
279 }
280
281 if (found_crtc)
282 break;
283 }
284
285 if (idx >= kdpy->resources->count_crtcs) {
286 _eglLog(_EGL_WARNING,
287 "failed to find a CRTC that supports the given %d connectors",
288 num_connectors);
289 return 0;
290 }
291
292 return kdpy->resources->crtcs[idx];
293 }
294
295 /**
296 * Remember the original CRTC status and set the CRTC
297 */
298 static boolean
299 kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
300 uint32_t buffer_id, uint32_t x, uint32_t y,
301 uint32_t *connectors, int num_connectors,
302 drmModeModeInfoPtr mode)
303 {
304 struct kms_display *kdpy = kms_display(ndpy);
305 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
306 uint32_t crtc_id;
307 int err;
308
309 if (kcrtc->crtc) {
310 crtc_id = kcrtc->crtc->crtc_id;
311 }
312 else {
313 int count = 0, i;
314
315 /*
316 * Choose the CRTC once. It could be more dynamic, but let's keep it
317 * simple for now.
318 */
319 crtc_id = kms_display_choose_crtc(&kdpy->base,
320 connectors, num_connectors);
321
322 /* save the original CRTC status */
323 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
324 if (!kcrtc->crtc)
325 return FALSE;
326
327 for (i = 0; i < kdpy->num_connectors; i++) {
328 struct kms_connector *kconn = &kdpy->connectors[i];
329 drmModeConnectorPtr connector = kconn->connector;
330 drmModeEncoderPtr encoder;
331
332 encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
333 if (encoder) {
334 if (encoder->crtc_id == crtc_id) {
335 kcrtc->connectors[count++] = connector->connector_id;
336 if (count >= Elements(kcrtc->connectors))
337 break;
338 }
339 drmModeFreeEncoder(encoder);
340 }
341 }
342
343 kcrtc->num_connectors = count;
344 }
345
346 err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
347 connectors, num_connectors, mode);
348 if (err) {
349 drmModeFreeCrtc(kcrtc->crtc);
350 kcrtc->crtc = NULL;
351 kcrtc->num_connectors = 0;
352
353 return FALSE;
354 }
355
356 return TRUE;
357 }
358
359 static boolean
360 kms_display_program(struct native_display *ndpy, int crtc_idx,
361 struct native_surface *nsurf, uint x, uint y,
362 const struct native_connector **nconns, int num_nconns,
363 const struct native_mode *nmode)
364 {
365 struct kms_display *kdpy = kms_display(ndpy);
366 struct kms_surface *ksurf = kms_surface(nsurf);
367 const struct kms_mode *kmode = kms_mode(nmode);
368 uint32_t connector_ids[32];
369 uint32_t buffer_id;
370 drmModeModeInfo mode_tmp, *mode;
371 int i;
372
373 if (num_nconns > Elements(connector_ids)) {
374 _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
375 num_nconns = Elements(connector_ids);
376 }
377
378 if (ksurf) {
379 if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
380 return FALSE;
381
382 buffer_id = ksurf->front_fb.buffer_id;
383 /* the mode argument of drmModeSetCrtc is not constified */
384 mode_tmp = kmode->mode;
385 mode = &mode_tmp;
386 }
387 else {
388 /* disable the CRTC */
389 buffer_id = 0;
390 mode = NULL;
391 num_nconns = 0;
392 }
393
394 for (i = 0; i < num_nconns; i++) {
395 struct kms_connector *kconn = kms_connector(nconns[i]);
396 connector_ids[i] = kconn->connector->connector_id;
397 }
398
399 if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
400 connector_ids, num_nconns, mode)) {
401 _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
402
403 return FALSE;
404 }
405
406 if (kdpy->shown_surfaces[crtc_idx])
407 kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
408 kdpy->shown_surfaces[crtc_idx] = ksurf;
409
410 /* remember the settings for buffer swapping */
411 if (ksurf) {
412 uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
413 struct kms_crtc *kcrtc = &ksurf->current_crtc;
414
415 if (kcrtc->crtc)
416 drmModeFreeCrtc(kcrtc->crtc);
417 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
418
419 assert(num_nconns < Elements(kcrtc->connectors));
420 memcpy(kcrtc->connectors, connector_ids,
421 sizeof(*connector_ids) * num_nconns);
422 kcrtc->num_connectors = num_nconns;
423
424 ksurf->is_shown = TRUE;
425 }
426
427 return TRUE;
428 }
429
430 static const struct native_mode **
431 kms_display_get_modes(struct native_display *ndpy,
432 const struct native_connector *nconn,
433 int *num_modes)
434 {
435 struct kms_display *kdpy = kms_display(ndpy);
436 struct kms_connector *kconn = kms_connector(nconn);
437 const struct native_mode **nmodes_return;
438 int count, i;
439
440 /* delete old data */
441 if (kconn->connector) {
442 drmModeFreeConnector(kconn->connector);
443 FREE(kconn->kms_modes);
444
445 kconn->connector = NULL;
446 kconn->kms_modes = NULL;
447 kconn->num_modes = 0;
448 }
449
450 /* detect again */
451 kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
452 if (!kconn->connector)
453 return NULL;
454
455 count = kconn->connector->count_modes;
456 kconn->kms_modes = CALLOC(count, sizeof(*kconn->kms_modes));
457 if (!kconn->kms_modes) {
458 drmModeFreeConnector(kconn->connector);
459 kconn->connector = NULL;
460
461 return NULL;
462 }
463
464 for (i = 0; i < count; i++) {
465 struct kms_mode *kmode = &kconn->kms_modes[i];
466 drmModeModeInfoPtr mode = &kconn->connector->modes[i];
467
468 kmode->mode = *mode;
469
470 kmode->base.desc = kmode->mode.name;
471 kmode->base.width = kmode->mode.hdisplay;
472 kmode->base.height = kmode->mode.vdisplay;
473 kmode->base.refresh_rate = kmode->mode.vrefresh;
474 /* not all kernels have vrefresh = refresh_rate * 1000 */
475 if (kmode->base.refresh_rate > 1000)
476 kmode->base.refresh_rate = (kmode->base.refresh_rate + 500) / 1000;
477 }
478
479 nmodes_return = MALLOC(count * sizeof(*nmodes_return));
480 if (nmodes_return) {
481 for (i = 0; i < count; i++)
482 nmodes_return[i] = &kconn->kms_modes[i].base;
483 if (num_modes)
484 *num_modes = count;
485 }
486
487 return nmodes_return;
488 }
489
490 static const struct native_connector **
491 kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
492 int *num_crtc)
493 {
494 struct kms_display *kdpy = kms_display(ndpy);
495 const struct native_connector **connectors;
496 int i;
497
498 if (!kdpy->connectors) {
499 kdpy->connectors =
500 CALLOC(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
501 if (!kdpy->connectors)
502 return NULL;
503
504 for (i = 0; i < kdpy->resources->count_connectors; i++) {
505 struct kms_connector *kconn = &kdpy->connectors[i];
506
507 kconn->connector_id = kdpy->resources->connectors[i];
508 /* kconn->connector is allocated when the modes are asked */
509 }
510
511 kdpy->num_connectors = kdpy->resources->count_connectors;
512 }
513
514 connectors = MALLOC(kdpy->num_connectors * sizeof(*connectors));
515 if (connectors) {
516 for (i = 0; i < kdpy->num_connectors; i++)
517 connectors[i] = &kdpy->connectors[i].base;
518 if (num_connectors)
519 *num_connectors = kdpy->num_connectors;
520 }
521
522 if (num_crtc)
523 *num_crtc = kdpy->resources->count_crtcs;
524
525 return connectors;
526 }
527
528 static struct native_surface *
529 kms_display_create_scanout_surface(struct native_display *ndpy,
530 const struct native_config *nconf,
531 uint width, uint height)
532 {
533 struct kms_surface *ksurf;
534
535 ksurf = kms_display_create_surface(ndpy, nconf, width, height);
536 return &ksurf->base;
537 }
538
539 static boolean
540 kms_display_is_format_supported(struct native_display *ndpy,
541 enum pipe_format fmt, boolean is_color)
542 {
543 return ndpy->screen->is_format_supported(ndpy->screen,
544 fmt, PIPE_TEXTURE_2D, 0,
545 (is_color) ? PIPE_BIND_RENDER_TARGET :
546 PIPE_BIND_DEPTH_STENCIL, 0);
547 }
548
549 static const struct native_config **
550 kms_display_get_configs(struct native_display *ndpy, int *num_configs)
551 {
552 struct kms_display *kdpy = kms_display(ndpy);
553 const struct native_config **configs;
554
555 /* first time */
556 if (!kdpy->config) {
557 struct native_config *nconf;
558 enum pipe_format format;
559
560 kdpy->config = CALLOC(1, sizeof(*kdpy->config));
561 if (!kdpy->config)
562 return NULL;
563
564 nconf = &kdpy->config->base;
565
566 nconf->buffer_mask =
567 (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
568 (1 << NATIVE_ATTACHMENT_BACK_LEFT);
569
570 format = PIPE_FORMAT_B8G8R8A8_UNORM;
571 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
572 format = PIPE_FORMAT_A8R8G8B8_UNORM;
573 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
574 format = PIPE_FORMAT_NONE;
575 }
576 if (format == PIPE_FORMAT_NONE) {
577 FREE(kdpy->config);
578 kdpy->config = NULL;
579 return NULL;
580 }
581
582 nconf->color_format = format;
583
584 nconf->scanout_bit = TRUE;
585 }
586
587 configs = MALLOC(sizeof(*configs));
588 if (configs) {
589 configs[0] = &kdpy->config->base;
590 if (num_configs)
591 *num_configs = 1;
592 }
593
594 return configs;
595 }
596
597 static int
598 kms_display_get_param(struct native_display *ndpy,
599 enum native_param_type param)
600 {
601 int val;
602
603 switch (param) {
604 default:
605 val = 0;
606 break;
607 }
608
609 return val;
610 }
611
612 static void
613 kms_display_destroy(struct native_display *ndpy)
614 {
615 struct kms_display *kdpy = kms_display(ndpy);
616 int i;
617
618 if (kdpy->config)
619 FREE(kdpy->config);
620
621 if (kdpy->connectors) {
622 for (i = 0; i < kdpy->num_connectors; i++) {
623 struct kms_connector *kconn = &kdpy->connectors[i];
624 if (kconn->connector) {
625 drmModeFreeConnector(kconn->connector);
626 FREE(kconn->kms_modes);
627 }
628 }
629 FREE(kdpy->connectors);
630 }
631
632 if (kdpy->shown_surfaces)
633 FREE(kdpy->shown_surfaces);
634
635 if (kdpy->saved_crtcs) {
636 for (i = 0; i < kdpy->resources->count_crtcs; i++) {
637 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
638
639 if (kcrtc->crtc) {
640 /* restore crtc */
641 drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
642 kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
643 kcrtc->connectors, kcrtc->num_connectors,
644 &kcrtc->crtc->mode);
645
646 drmModeFreeCrtc(kcrtc->crtc);
647 }
648 }
649 FREE(kdpy->saved_crtcs);
650 }
651
652 if (kdpy->resources)
653 drmModeFreeResources(kdpy->resources);
654
655 if (kdpy->base.screen)
656 kdpy->base.screen->destroy(kdpy->base.screen);
657
658 if (kdpy->fd >= 0)
659 drmClose(kdpy->fd);
660
661 FREE(kdpy);
662 }
663
664 /**
665 * Initialize KMS and pipe screen.
666 */
667 static boolean
668 kms_display_init_screen(struct native_display *ndpy)
669 {
670 struct kms_display *kdpy = kms_display(ndpy);
671 int fd;
672
673 fd = kdpy->fd;
674 if (fd >= 0) {
675 drmVersionPtr version = drmGetVersion(fd);
676 if (!version || strcmp(version->name, driver_descriptor.driver_name)) {
677 if (version) {
678 _eglLog(_EGL_WARNING, "unknown driver name %s", version->name);
679 drmFreeVersion(version);
680 }
681 else {
682 _eglLog(_EGL_WARNING, "invalid fd %d", fd);
683 }
684
685 return FALSE;
686 }
687
688 drmFreeVersion(version);
689 }
690 else {
691 fd = drmOpen(driver_descriptor.driver_name, NULL);
692 }
693
694 if (fd < 0) {
695 _eglLog(_EGL_WARNING, "failed to open DRM device");
696 return FALSE;
697 }
698
699 #if 0
700 if (drmSetMaster(fd)) {
701 _eglLog(_EGL_WARNING, "failed to become DRM master");
702 return FALSE;
703 }
704 #endif
705
706 kdpy->base.screen = driver_descriptor.create_screen(fd);
707 if (!kdpy->base.screen) {
708 _eglLog(_EGL_WARNING, "failed to create DRM screen");
709 drmClose(fd);
710 return FALSE;
711 }
712
713 kdpy->fd = fd;
714
715 return TRUE;
716 }
717
718 static struct native_display_modeset kms_display_modeset = {
719 .get_connectors = kms_display_get_connectors,
720 .get_modes = kms_display_get_modes,
721 .create_scanout_surface = kms_display_create_scanout_surface,
722 .program = kms_display_program
723 };
724
725 static struct native_display *
726 kms_create_display(int fd, struct native_event_handler *event_handler)
727 {
728 struct kms_display *kdpy;
729
730 kdpy = CALLOC_STRUCT(kms_display);
731 if (!kdpy)
732 return NULL;
733
734 kdpy->event_handler = event_handler;
735 kdpy->fd = fd;
736 if (!kms_display_init_screen(&kdpy->base)) {
737 kms_display_destroy(&kdpy->base);
738 return NULL;
739 }
740
741 /* resources are fixed, unlike crtc, connector, or encoder */
742 kdpy->resources = drmModeGetResources(kdpy->fd);
743 if (!kdpy->resources) {
744 kms_display_destroy(&kdpy->base);
745 return NULL;
746 }
747
748 kdpy->saved_crtcs =
749 CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
750 if (!kdpy->saved_crtcs) {
751 kms_display_destroy(&kdpy->base);
752 return NULL;
753 }
754
755 kdpy->shown_surfaces =
756 CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
757 if (!kdpy->shown_surfaces) {
758 kms_display_destroy(&kdpy->base);
759 return NULL;
760 }
761
762 kdpy->base.destroy = kms_display_destroy;
763 kdpy->base.get_param = kms_display_get_param;
764 kdpy->base.get_configs = kms_display_get_configs;
765
766 kdpy->base.modeset = &kms_display_modeset;
767
768 return &kdpy->base;
769 }
770
771 static struct native_display *
772 native_create_display(void *dpy, struct native_event_handler *event_handler)
773 {
774 struct native_display *ndpy;
775 int fd;
776
777 /* well, this makes fd 0 being ignored */
778 fd = (dpy) ? (int) pointer_to_intptr(dpy) : -1;
779 ndpy = kms_create_display(fd, event_handler);
780
781 return ndpy;
782 }
783
784 static void
785 kms_init_platform(struct native_platform *nplat)
786 {
787 static char kms_name[32];
788
789 if (nplat->name)
790 return;
791
792 util_snprintf(kms_name, sizeof(kms_name), "KMS/%s", driver_descriptor.name);
793
794 nplat->name = kms_name;
795 nplat->create_probe = NULL;
796 nplat->get_probe_result = NULL;
797 nplat->create_display = native_create_display;
798 }
799
800 static struct native_platform kms_platform;
801
802 const struct native_platform *
803 native_get_platform(void)
804 {
805 kms_init_platform(&kms_platform);
806 return &kms_platform;
807 }