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