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