st/egl: make native_buffer interface typed
[mesa.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 }