st/egl: adapt to interface changes
[profile/ivi/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, NULL);
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 }