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