Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / state_trackers / egl / drm / modeset.c
1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.9
4  *
5  * Copyright (C) 2010 LunarG Inc.
6  * Copyright (C) 2011 VMware Inc. All rights reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  * Authors:
27  *    Chia-I Wu <olv@lunarg.com>
28  *    Thomas Hellstrom <thellstrom@vmware.com>
29  */
30
31 #include "util/u_memory.h"
32 #include "util/u_inlines.h"
33 #include "egllog.h"
34
35 #include "native_drm.h"
36
37 static boolean
38 drm_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 drm_surface *drmsurf = drm_surface(nsurf);
43
44    if (!resource_surface_add_resources(drmsurf->rsurf, attachment_mask))
45       return FALSE;
46    if (textures)
47       resource_surface_get_resources(drmsurf->rsurf, textures, attachment_mask);
48
49    if (seq_num)
50       *seq_num = drmsurf->sequence_number;
51    if (width)
52       *width = drmsurf->width;
53    if (height)
54       *height = drmsurf->height;
55
56    return TRUE;
57 }
58
59 /**
60  * Add textures as DRM framebuffers.
61  */
62 static boolean
63 drm_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
64 {
65    struct drm_surface *drmsurf = drm_surface(nsurf);
66    struct drm_display *drmdpy = drmsurf->drmdpy;
67    int num_framebuffers = (need_back) ? 2 : 1;
68    int i, err;
69
70    for (i = 0; i < num_framebuffers; i++) {
71       struct drm_framebuffer *fb;
72       enum native_attachment natt;
73       struct winsys_handle whandle;
74       uint block_bits;
75
76       if (i == 0) {
77          fb = &drmsurf->front_fb;
78          natt = NATIVE_ATTACHMENT_FRONT_LEFT;
79       }
80       else {
81          fb = &drmsurf->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(drmsurf->rsurf, 1 << natt);
88          fb->texture =
89             resource_surface_get_single_resource(drmsurf->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 (!drmdpy->base.screen->resource_get_handle(drmdpy->base.screen,
105                fb->texture, &whandle))
106          return FALSE;
107
108       block_bits = util_format_get_blocksizebits(drmsurf->color_format);
109       err = drmModeAddFB(drmdpy->fd, drmsurf->width, drmsurf->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 drm_surface_flush_frontbuffer(struct native_surface *nsurf)
123 {
124 #ifdef DRM_MODE_FEATURE_DIRTYFB
125    struct drm_surface *drmsurf = drm_surface(nsurf);
126    struct drm_display *drmdpy = drmsurf->drmdpy;
127
128    if (drmsurf->front_fb.is_passive)
129       drmModeDirtyFB(drmdpy->fd, drmsurf->front_fb.buffer_id, NULL, 0);
130 #endif
131
132    return TRUE;
133 }
134
135 static boolean
136 drm_surface_copy_swap(struct native_surface *nsurf)
137 {
138    struct drm_surface *drmsurf = drm_surface(nsurf);
139    struct drm_display *drmdpy = drmsurf->drmdpy;
140
141    (void) resource_surface_throttle(drmsurf->rsurf);
142    if (!resource_surface_copy_swap(drmsurf->rsurf, &drmdpy->base))
143       return FALSE;
144
145    (void) resource_surface_flush(drmsurf->rsurf, &drmdpy->base);
146    if (!drm_surface_flush_frontbuffer(nsurf))
147       return FALSE;
148
149    drmsurf->sequence_number++;
150
151    return TRUE;
152 }
153
154 static boolean
155 drm_surface_swap_buffers(struct native_surface *nsurf)
156 {
157    struct drm_surface *drmsurf = drm_surface(nsurf);
158    struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
159    struct drm_display *drmdpy = drmsurf->drmdpy;
160    struct drm_framebuffer tmp_fb;
161    int err;
162
163    if (!drmsurf->have_pageflip)
164       return drm_surface_copy_swap(nsurf);
165
166    if (!drmsurf->back_fb.buffer_id) {
167       if (!drm_surface_init_framebuffers(&drmsurf->base, TRUE))
168          return FALSE;
169    }
170
171    if (drmsurf->is_shown && drmcrtc->crtc) {
172       err = drmModePageFlip(drmdpy->fd, drmcrtc->crtc->crtc_id,
173                             drmsurf->back_fb.buffer_id, 0, NULL);
174       if (err) {
175          drmsurf->have_pageflip = FALSE;
176          return drm_surface_copy_swap(nsurf);
177       }
178    }
179
180    /* swap the buffers */
181    tmp_fb = drmsurf->front_fb;
182    drmsurf->front_fb = drmsurf->back_fb;
183    drmsurf->back_fb = tmp_fb;
184
185    resource_surface_swap_buffers(drmsurf->rsurf,
186          NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
187    /* the front/back textures are swapped */
188    drmsurf->sequence_number++;
189    drmdpy->event_handler->invalid_surface(&drmdpy->base,
190          &drmsurf->base, drmsurf->sequence_number);
191
192    return TRUE;
193 }
194
195 static boolean
196 drm_surface_present(struct native_surface *nsurf,
197                     enum native_attachment natt,
198                     boolean preserve,
199                     uint swap_interval)
200 {
201    boolean ret;
202
203    if (swap_interval)
204       return FALSE;
205
206    switch (natt) {
207    case NATIVE_ATTACHMENT_FRONT_LEFT:
208       ret = drm_surface_flush_frontbuffer(nsurf);
209       break;
210    case NATIVE_ATTACHMENT_BACK_LEFT:
211       if (preserve)
212          ret = drm_surface_copy_swap(nsurf);
213       else
214          ret = drm_surface_swap_buffers(nsurf);
215       break;
216    default:
217       ret = FALSE;
218       break;
219    }
220
221    return ret;
222 }
223
224 static void
225 drm_surface_wait(struct native_surface *nsurf)
226 {
227    struct drm_surface *drmsurf = drm_surface(nsurf);
228
229    resource_surface_wait(drmsurf->rsurf);
230 }
231
232 static void
233 drm_surface_destroy(struct native_surface *nsurf)
234 {
235    struct drm_surface *drmsurf = drm_surface(nsurf);
236
237    resource_surface_wait(drmsurf->rsurf);
238    if (drmsurf->current_crtc.crtc)
239          drmModeFreeCrtc(drmsurf->current_crtc.crtc);
240
241    if (drmsurf->front_fb.buffer_id)
242       drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->front_fb.buffer_id);
243    pipe_resource_reference(&drmsurf->front_fb.texture, NULL);
244
245    if (drmsurf->back_fb.buffer_id)
246       drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->back_fb.buffer_id);
247    pipe_resource_reference(&drmsurf->back_fb.texture, NULL);
248
249    resource_surface_destroy(drmsurf->rsurf);
250    FREE(drmsurf);
251 }
252
253 static struct drm_surface *
254 drm_display_create_surface(struct native_display *ndpy,
255                            const struct native_config *nconf,
256                            uint width, uint height)
257 {
258    struct drm_display *drmdpy = drm_display(ndpy);
259    struct drm_config *drmconf = drm_config(nconf);
260    struct drm_surface *drmsurf;
261
262    drmsurf = CALLOC_STRUCT(drm_surface);
263    if (!drmsurf)
264       return NULL;
265
266    drmsurf->drmdpy = drmdpy;
267    drmsurf->color_format = drmconf->base.color_format;
268    drmsurf->width = width;
269    drmsurf->height = height;
270    drmsurf->have_pageflip = TRUE;
271
272    drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
273          drmsurf->color_format,
274          PIPE_BIND_RENDER_TARGET |
275          PIPE_BIND_SAMPLER_VIEW |
276          PIPE_BIND_DISPLAY_TARGET |
277          PIPE_BIND_SCANOUT);
278    if (!drmsurf->rsurf) {
279       FREE(drmsurf);
280       return NULL;
281    }
282
283    resource_surface_set_size(drmsurf->rsurf, drmsurf->width, drmsurf->height);
284
285    drmsurf->base.destroy = drm_surface_destroy;
286    drmsurf->base.present = drm_surface_present;
287    drmsurf->base.validate = drm_surface_validate;
288    drmsurf->base.wait = drm_surface_wait;
289
290    return drmsurf;
291 }
292
293 struct native_surface *
294 drm_display_create_surface_from_resource(struct native_display *ndpy,
295                                          struct pipe_resource *resource)
296 {
297    struct drm_display *drmdpy = drm_display(ndpy);
298    struct drm_surface *drmsurf;
299    enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
300
301    drmsurf = CALLOC_STRUCT(drm_surface);
302    if (!drmsurf)
303       return NULL;
304
305    drmsurf->drmdpy = drmdpy;
306    drmsurf->color_format = resource->format;
307    drmsurf->width = resource->width0;
308    drmsurf->height = resource->height0;
309    drmsurf->have_pageflip = FALSE;
310
311    drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
312          drmsurf->color_format,
313          PIPE_BIND_RENDER_TARGET |
314          PIPE_BIND_SAMPLER_VIEW |
315          PIPE_BIND_DISPLAY_TARGET |
316          PIPE_BIND_SCANOUT);
317    
318    resource_surface_import_resource(drmsurf->rsurf, natt, resource);
319
320    drmsurf->base.destroy = drm_surface_destroy;
321    drmsurf->base.present = drm_surface_present;
322    drmsurf->base.validate = drm_surface_validate;
323    drmsurf->base.wait = drm_surface_wait;
324
325    return &drmsurf->base;
326 }
327         
328
329 /**
330  * Choose a CRTC that supports all given connectors.
331  */
332 static uint32_t
333 drm_display_choose_crtc(struct native_display *ndpy,
334                         uint32_t *connectors, int num_connectors)
335 {
336    struct drm_display *drmdpy = drm_display(ndpy);
337    int idx;
338
339    for (idx = 0; idx < drmdpy->resources->count_crtcs; idx++) {
340       boolean found_crtc = TRUE;
341       int i, j;
342
343       for (i = 0; i < num_connectors; i++) {
344          drmModeConnectorPtr connector;
345          int encoder_idx = -1;
346
347          connector = drmModeGetConnector(drmdpy->fd, connectors[i]);
348          if (!connector) {
349             found_crtc = FALSE;
350             break;
351          }
352
353          /* find an encoder the CRTC supports */
354          for (j = 0; j < connector->count_encoders; j++) {
355             drmModeEncoderPtr encoder =
356                drmModeGetEncoder(drmdpy->fd, connector->encoders[j]);
357             if (encoder->possible_crtcs & (1 << idx)) {
358                encoder_idx = j;
359                break;
360             }
361             drmModeFreeEncoder(encoder);
362          }
363
364          drmModeFreeConnector(connector);
365          if (encoder_idx < 0) {
366             found_crtc = FALSE;
367             break;
368          }
369       }
370
371       if (found_crtc)
372          break;
373    }
374
375    if (idx >= drmdpy->resources->count_crtcs) {
376       _eglLog(_EGL_WARNING,
377             "failed to find a CRTC that supports the given %d connectors",
378             num_connectors);
379       return 0;
380    }
381
382    return drmdpy->resources->crtcs[idx];
383 }
384
385 /**
386  * Remember the original CRTC status and set the CRTC
387  */
388 static boolean
389 drm_display_set_crtc(struct native_display *ndpy, int crtc_idx,
390                      uint32_t buffer_id, uint32_t x, uint32_t y,
391                      uint32_t *connectors, int num_connectors,
392                      drmModeModeInfoPtr mode)
393 {
394    struct drm_display *drmdpy = drm_display(ndpy);
395    struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[crtc_idx];
396    uint32_t crtc_id;
397    int err;
398
399    if (drmcrtc->crtc) {
400       crtc_id = drmcrtc->crtc->crtc_id;
401    }
402    else {
403       int count = 0, i;
404
405       /*
406        * Choose the CRTC once.  It could be more dynamic, but let's keep it
407        * simple for now.
408        */
409       crtc_id = drm_display_choose_crtc(&drmdpy->base,
410             connectors, num_connectors);
411
412       /* save the original CRTC status */
413       drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
414       if (!drmcrtc->crtc)
415          return FALSE;
416
417       for (i = 0; i < drmdpy->num_connectors; i++) {
418          struct drm_connector *drmconn = &drmdpy->connectors[i];
419          drmModeConnectorPtr connector = drmconn->connector;
420          drmModeEncoderPtr encoder;
421
422          encoder = drmModeGetEncoder(drmdpy->fd, connector->encoder_id);
423          if (encoder) {
424             if (encoder->crtc_id == crtc_id) {
425                drmcrtc->connectors[count++] = connector->connector_id;
426                if (count >= Elements(drmcrtc->connectors))
427                   break;
428             }
429             drmModeFreeEncoder(encoder);
430          }
431       }
432
433       drmcrtc->num_connectors = count;
434    }
435
436    err = drmModeSetCrtc(drmdpy->fd, crtc_id, buffer_id, x, y,
437          connectors, num_connectors, mode);
438    if (err) {
439       drmModeFreeCrtc(drmcrtc->crtc);
440       drmcrtc->crtc = NULL;
441       drmcrtc->num_connectors = 0;
442
443       return FALSE;
444    }
445
446    return TRUE;
447 }
448
449 static boolean
450 drm_display_program(struct native_display *ndpy, int crtc_idx,
451                     struct native_surface *nsurf, uint x, uint y,
452                     const struct native_connector **nconns, int num_nconns,
453                     const struct native_mode *nmode)
454 {
455    struct drm_display *drmdpy = drm_display(ndpy);
456    struct drm_surface *drmsurf = drm_surface(nsurf);
457    const struct drm_mode *drmmode = drm_mode(nmode);
458    uint32_t connector_ids[32];
459    uint32_t buffer_id;
460    drmModeModeInfo mode_tmp, *mode;
461    int i;
462
463    if (num_nconns > Elements(connector_ids)) {
464       _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
465       num_nconns = Elements(connector_ids);
466    }
467
468    if (drmsurf) {
469       if (!drm_surface_init_framebuffers(&drmsurf->base, FALSE))
470          return FALSE;
471
472       buffer_id = drmsurf->front_fb.buffer_id;
473       /* the mode argument of drmModeSetCrtc is not constified */
474       mode_tmp = drmmode->mode;
475       mode = &mode_tmp;
476    }
477    else {
478       /* disable the CRTC */
479       buffer_id = 0;
480       mode = NULL;
481       num_nconns = 0;
482    }
483
484    for (i = 0; i < num_nconns; i++) {
485       struct drm_connector *drmconn = drm_connector(nconns[i]);
486       connector_ids[i] = drmconn->connector->connector_id;
487    }
488
489    if (!drm_display_set_crtc(&drmdpy->base, crtc_idx, buffer_id, x, y,
490             connector_ids, num_nconns, mode)) {
491       _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
492
493       return FALSE;
494    }
495
496    if (drmdpy->shown_surfaces[crtc_idx])
497       drmdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
498    drmdpy->shown_surfaces[crtc_idx] = drmsurf;
499
500    /* remember the settings for buffer swapping */
501    if (drmsurf) {
502       uint32_t crtc_id = drmdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
503       struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
504
505       if (drmcrtc->crtc)
506          drmModeFreeCrtc(drmcrtc->crtc);
507       drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
508
509       assert(num_nconns < Elements(drmcrtc->connectors));
510       memcpy(drmcrtc->connectors, connector_ids,
511             sizeof(*connector_ids) * num_nconns);
512       drmcrtc->num_connectors = num_nconns;
513
514       drmsurf->is_shown = TRUE;
515    }
516
517    return TRUE;
518 }
519
520 static const struct native_mode **
521 drm_display_get_modes(struct native_display *ndpy,
522                       const struct native_connector *nconn,
523                       int *num_modes)
524 {
525    struct drm_display *drmdpy = drm_display(ndpy);
526    struct drm_connector *drmconn = drm_connector(nconn);
527    const struct native_mode **nmodes_return;
528    int count, i;
529
530    /* delete old data */
531    if (drmconn->connector) {
532       drmModeFreeConnector(drmconn->connector);
533       FREE(drmconn->drm_modes);
534
535       drmconn->connector = NULL;
536       drmconn->drm_modes = NULL;
537       drmconn->num_modes = 0;
538    }
539
540    /* detect again */
541    drmconn->connector = drmModeGetConnector(drmdpy->fd, drmconn->connector_id);
542    if (!drmconn->connector)
543       return NULL;
544
545    count = drmconn->connector->count_modes;
546    drmconn->drm_modes = CALLOC(count, sizeof(*drmconn->drm_modes));
547    if (!drmconn->drm_modes) {
548       drmModeFreeConnector(drmconn->connector);
549       drmconn->connector = NULL;
550
551       return NULL;
552    }
553
554    for (i = 0; i < count; i++) {
555       struct drm_mode *drmmode = &drmconn->drm_modes[i];
556       drmModeModeInfoPtr mode = &drmconn->connector->modes[i];
557
558       drmmode->mode = *mode;
559
560       drmmode->base.desc = drmmode->mode.name;
561       drmmode->base.width = drmmode->mode.hdisplay;
562       drmmode->base.height = drmmode->mode.vdisplay;
563       drmmode->base.refresh_rate = drmmode->mode.vrefresh;
564       /* not all kernels have vrefresh = refresh_rate * 1000 */
565       if (drmmode->base.refresh_rate < 1000)
566          drmmode->base.refresh_rate *= 1000;
567    }
568
569    nmodes_return = MALLOC(count * sizeof(*nmodes_return));
570    if (nmodes_return) {
571       for (i = 0; i < count; i++)
572          nmodes_return[i] = &drmconn->drm_modes[i].base;
573       if (num_modes)
574          *num_modes = count;
575    }
576
577    return nmodes_return;
578 }
579
580 static const struct native_connector **
581 drm_display_get_connectors(struct native_display *ndpy, int *num_connectors,
582                            int *num_crtc)
583 {
584    struct drm_display *drmdpy = drm_display(ndpy);
585    const struct native_connector **connectors;
586    int i;
587
588    if (!drmdpy->connectors) {
589       drmdpy->connectors =
590          CALLOC(drmdpy->resources->count_connectors, sizeof(*drmdpy->connectors));
591       if (!drmdpy->connectors)
592          return NULL;
593
594       for (i = 0; i < drmdpy->resources->count_connectors; i++) {
595          struct drm_connector *drmconn = &drmdpy->connectors[i];
596
597          drmconn->connector_id = drmdpy->resources->connectors[i];
598          /* drmconn->connector is allocated when the modes are asked */
599       }
600
601       drmdpy->num_connectors = drmdpy->resources->count_connectors;
602    }
603
604    connectors = MALLOC(drmdpy->num_connectors * sizeof(*connectors));
605    if (connectors) {
606       for (i = 0; i < drmdpy->num_connectors; i++)
607          connectors[i] = &drmdpy->connectors[i].base;
608       if (num_connectors)
609          *num_connectors = drmdpy->num_connectors;
610    }
611
612    if (num_crtc)
613       *num_crtc = drmdpy->resources->count_crtcs;
614
615    return connectors;
616 }
617
618 static struct native_surface *
619 drm_display_create_scanout_surface(struct native_display *ndpy,
620                                    const struct native_config *nconf,
621                                    uint width, uint height)
622 {
623    struct drm_surface *drmsurf;
624
625    drmsurf = drm_display_create_surface(ndpy, nconf, width, height);
626    return &drmsurf->base;
627 }
628
629 static struct native_display_modeset drm_display_modeset = {
630    .get_connectors = drm_display_get_connectors,
631    .get_modes = drm_display_get_modes,
632    .create_scanout_surface = drm_display_create_scanout_surface,
633    .program = drm_display_program
634 };
635
636 void
637 drm_display_fini_modeset(struct native_display *ndpy)
638 {
639    struct drm_display *drmdpy = drm_display(ndpy);
640    int i;
641
642    if (drmdpy->connectors) {
643       for (i = 0; i < drmdpy->num_connectors; i++) {
644          struct drm_connector *drmconn = &drmdpy->connectors[i];
645          if (drmconn->connector) {
646             drmModeFreeConnector(drmconn->connector);
647             FREE(drmconn->drm_modes);
648          }
649       }
650       FREE(drmdpy->connectors);
651    }
652
653    if (drmdpy->shown_surfaces) {
654       FREE(drmdpy->shown_surfaces);
655       drmdpy->shown_surfaces = NULL;
656    }
657
658    if (drmdpy->saved_crtcs) {
659       for (i = 0; i < drmdpy->resources->count_crtcs; i++) {
660          struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[i];
661
662          if (drmcrtc->crtc) {
663             /* restore crtc */
664             drmModeSetCrtc(drmdpy->fd, drmcrtc->crtc->crtc_id,
665                   drmcrtc->crtc->buffer_id, drmcrtc->crtc->x, drmcrtc->crtc->y,
666                   drmcrtc->connectors, drmcrtc->num_connectors,
667                   &drmcrtc->crtc->mode);
668
669             drmModeFreeCrtc(drmcrtc->crtc);
670          }
671       }
672       FREE(drmdpy->saved_crtcs);
673    }
674
675    if (drmdpy->resources) {
676       drmModeFreeResources(drmdpy->resources);
677       drmdpy->resources = NULL;
678    }
679
680    drmdpy->base.modeset = NULL;
681 }
682
683 boolean
684 drm_display_init_modeset(struct native_display *ndpy)
685 {
686    struct drm_display *drmdpy = drm_display(ndpy);
687
688    /* resources are fixed, unlike crtc, connector, or encoder */
689    drmdpy->resources = drmModeGetResources(drmdpy->fd);
690    if (!drmdpy->resources) {
691       _eglLog(_EGL_DEBUG, "Failed to get KMS resources.  Disable modeset.");
692       return FALSE;
693    }
694
695    drmdpy->saved_crtcs =
696       CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->saved_crtcs));
697    if (!drmdpy->saved_crtcs) {
698       drm_display_fini_modeset(&drmdpy->base);
699       return FALSE;
700    }
701
702    drmdpy->shown_surfaces =
703       CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->shown_surfaces));
704    if (!drmdpy->shown_surfaces) {
705       drm_display_fini_modeset(&drmdpy->base);
706       return FALSE;
707    }
708
709    drmdpy->base.modeset = &drm_display_modeset;
710
711    return TRUE;
712 }