Remove useless checks for NULL before freeing
[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 const struct native_present_control *ctrl)
198 {
199 boolean ret;
200
201 if (ctrl->swap_interval)
202 return FALSE;
203
204 switch (ctrl->natt) {
205 case NATIVE_ATTACHMENT_FRONT_LEFT:
206 ret = drm_surface_flush_frontbuffer(nsurf);
207 break;
208 case NATIVE_ATTACHMENT_BACK_LEFT:
209 if (ctrl->preserve)
210 ret = drm_surface_copy_swap(nsurf);
211 else
212 ret = drm_surface_swap_buffers(nsurf);
213 break;
214 default:
215 ret = FALSE;
216 break;
217 }
218
219 return ret;
220 }
221
222 static void
223 drm_surface_wait(struct native_surface *nsurf)
224 {
225 struct drm_surface *drmsurf = drm_surface(nsurf);
226
227 resource_surface_wait(drmsurf->rsurf);
228 }
229
230 static void
231 drm_surface_destroy(struct native_surface *nsurf)
232 {
233 struct drm_surface *drmsurf = drm_surface(nsurf);
234
235 resource_surface_wait(drmsurf->rsurf);
236 if (drmsurf->current_crtc.crtc)
237 drmModeFreeCrtc(drmsurf->current_crtc.crtc);
238
239 if (drmsurf->front_fb.buffer_id)
240 drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->front_fb.buffer_id);
241 pipe_resource_reference(&drmsurf->front_fb.texture, NULL);
242
243 if (drmsurf->back_fb.buffer_id)
244 drmModeRmFB(drmsurf->drmdpy->fd, drmsurf->back_fb.buffer_id);
245 pipe_resource_reference(&drmsurf->back_fb.texture, NULL);
246
247 resource_surface_destroy(drmsurf->rsurf);
248 FREE(drmsurf);
249 }
250
251 static struct drm_surface *
252 drm_display_create_surface(struct native_display *ndpy,
253 const struct native_config *nconf,
254 uint width, uint height)
255 {
256 struct drm_display *drmdpy = drm_display(ndpy);
257 struct drm_config *drmconf = drm_config(nconf);
258 struct drm_surface *drmsurf;
259
260 drmsurf = CALLOC_STRUCT(drm_surface);
261 if (!drmsurf)
262 return NULL;
263
264 drmsurf->drmdpy = drmdpy;
265 drmsurf->color_format = drmconf->base.color_format;
266 drmsurf->width = width;
267 drmsurf->height = height;
268 drmsurf->have_pageflip = TRUE;
269
270 drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
271 drmsurf->color_format,
272 PIPE_BIND_RENDER_TARGET |
273 PIPE_BIND_SAMPLER_VIEW |
274 PIPE_BIND_DISPLAY_TARGET |
275 PIPE_BIND_SCANOUT);
276 if (!drmsurf->rsurf) {
277 FREE(drmsurf);
278 return NULL;
279 }
280
281 resource_surface_set_size(drmsurf->rsurf, drmsurf->width, drmsurf->height);
282
283 drmsurf->base.destroy = drm_surface_destroy;
284 drmsurf->base.present = drm_surface_present;
285 drmsurf->base.validate = drm_surface_validate;
286 drmsurf->base.wait = drm_surface_wait;
287
288 return drmsurf;
289 }
290
291 struct native_surface *
292 drm_display_create_surface_from_resource(struct native_display *ndpy,
293 struct pipe_resource *resource)
294 {
295 struct drm_display *drmdpy = drm_display(ndpy);
296 struct drm_surface *drmsurf;
297 enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
298
299 drmsurf = CALLOC_STRUCT(drm_surface);
300 if (!drmsurf)
301 return NULL;
302
303 drmsurf->drmdpy = drmdpy;
304 drmsurf->color_format = resource->format;
305 drmsurf->width = resource->width0;
306 drmsurf->height = resource->height0;
307 drmsurf->have_pageflip = FALSE;
308
309 drmsurf->rsurf = resource_surface_create(drmdpy->base.screen,
310 drmsurf->color_format,
311 PIPE_BIND_RENDER_TARGET |
312 PIPE_BIND_SAMPLER_VIEW |
313 PIPE_BIND_DISPLAY_TARGET |
314 PIPE_BIND_SCANOUT);
315
316 resource_surface_import_resource(drmsurf->rsurf, natt, resource);
317
318 drmsurf->base.destroy = drm_surface_destroy;
319 drmsurf->base.present = drm_surface_present;
320 drmsurf->base.validate = drm_surface_validate;
321 drmsurf->base.wait = drm_surface_wait;
322
323 return &drmsurf->base;
324 }
325
326
327 /**
328 * Choose a CRTC that supports all given connectors.
329 */
330 static uint32_t
331 drm_display_choose_crtc(struct native_display *ndpy,
332 uint32_t *connectors, int num_connectors)
333 {
334 struct drm_display *drmdpy = drm_display(ndpy);
335 int idx;
336
337 for (idx = 0; idx < drmdpy->resources->count_crtcs; idx++) {
338 boolean found_crtc = TRUE;
339 int i, j;
340
341 for (i = 0; i < num_connectors; i++) {
342 drmModeConnectorPtr connector;
343 int encoder_idx = -1;
344
345 connector = drmModeGetConnector(drmdpy->fd, connectors[i]);
346 if (!connector) {
347 found_crtc = FALSE;
348 break;
349 }
350
351 /* find an encoder the CRTC supports */
352 for (j = 0; j < connector->count_encoders; j++) {
353 drmModeEncoderPtr encoder =
354 drmModeGetEncoder(drmdpy->fd, connector->encoders[j]);
355 if (encoder->possible_crtcs & (1 << idx)) {
356 encoder_idx = j;
357 break;
358 }
359 drmModeFreeEncoder(encoder);
360 }
361
362 drmModeFreeConnector(connector);
363 if (encoder_idx < 0) {
364 found_crtc = FALSE;
365 break;
366 }
367 }
368
369 if (found_crtc)
370 break;
371 }
372
373 if (idx >= drmdpy->resources->count_crtcs) {
374 _eglLog(_EGL_WARNING,
375 "failed to find a CRTC that supports the given %d connectors",
376 num_connectors);
377 return 0;
378 }
379
380 return drmdpy->resources->crtcs[idx];
381 }
382
383 /**
384 * Remember the original CRTC status and set the CRTC
385 */
386 static boolean
387 drm_display_set_crtc(struct native_display *ndpy, int crtc_idx,
388 uint32_t buffer_id, uint32_t x, uint32_t y,
389 uint32_t *connectors, int num_connectors,
390 drmModeModeInfoPtr mode)
391 {
392 struct drm_display *drmdpy = drm_display(ndpy);
393 struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[crtc_idx];
394 uint32_t crtc_id;
395 int err;
396
397 if (drmcrtc->crtc) {
398 crtc_id = drmcrtc->crtc->crtc_id;
399 }
400 else {
401 int count = 0, i;
402
403 /*
404 * Choose the CRTC once. It could be more dynamic, but let's keep it
405 * simple for now.
406 */
407 crtc_id = drm_display_choose_crtc(&drmdpy->base,
408 connectors, num_connectors);
409
410 /* save the original CRTC status */
411 drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
412 if (!drmcrtc->crtc)
413 return FALSE;
414
415 for (i = 0; i < drmdpy->num_connectors; i++) {
416 struct drm_connector *drmconn = &drmdpy->connectors[i];
417 drmModeConnectorPtr connector = drmconn->connector;
418 drmModeEncoderPtr encoder;
419
420 encoder = drmModeGetEncoder(drmdpy->fd, connector->encoder_id);
421 if (encoder) {
422 if (encoder->crtc_id == crtc_id) {
423 drmcrtc->connectors[count++] = connector->connector_id;
424 if (count >= Elements(drmcrtc->connectors))
425 break;
426 }
427 drmModeFreeEncoder(encoder);
428 }
429 }
430
431 drmcrtc->num_connectors = count;
432 }
433
434 err = drmModeSetCrtc(drmdpy->fd, crtc_id, buffer_id, x, y,
435 connectors, num_connectors, mode);
436 if (err) {
437 drmModeFreeCrtc(drmcrtc->crtc);
438 drmcrtc->crtc = NULL;
439 drmcrtc->num_connectors = 0;
440
441 return FALSE;
442 }
443
444 return TRUE;
445 }
446
447 static boolean
448 drm_display_program(struct native_display *ndpy, int crtc_idx,
449 struct native_surface *nsurf, uint x, uint y,
450 const struct native_connector **nconns, int num_nconns,
451 const struct native_mode *nmode)
452 {
453 struct drm_display *drmdpy = drm_display(ndpy);
454 struct drm_surface *drmsurf = drm_surface(nsurf);
455 const struct drm_mode *drmmode = drm_mode(nmode);
456 uint32_t connector_ids[32];
457 uint32_t buffer_id;
458 drmModeModeInfo mode_tmp, *mode;
459 int i;
460
461 if (num_nconns > Elements(connector_ids)) {
462 _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
463 num_nconns = Elements(connector_ids);
464 }
465
466 if (drmsurf) {
467 if (!drm_surface_init_framebuffers(&drmsurf->base, FALSE))
468 return FALSE;
469
470 buffer_id = drmsurf->front_fb.buffer_id;
471 /* the mode argument of drmModeSetCrtc is not constified */
472 mode_tmp = drmmode->mode;
473 mode = &mode_tmp;
474 }
475 else {
476 /* disable the CRTC */
477 buffer_id = 0;
478 mode = NULL;
479 num_nconns = 0;
480 }
481
482 for (i = 0; i < num_nconns; i++) {
483 struct drm_connector *drmconn = drm_connector(nconns[i]);
484 connector_ids[i] = drmconn->connector->connector_id;
485 }
486
487 if (!drm_display_set_crtc(&drmdpy->base, crtc_idx, buffer_id, x, y,
488 connector_ids, num_nconns, mode)) {
489 _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
490
491 return FALSE;
492 }
493
494 if (drmdpy->shown_surfaces[crtc_idx])
495 drmdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
496 drmdpy->shown_surfaces[crtc_idx] = drmsurf;
497
498 /* remember the settings for buffer swapping */
499 if (drmsurf) {
500 uint32_t crtc_id = drmdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
501 struct drm_crtc *drmcrtc = &drmsurf->current_crtc;
502
503 if (drmcrtc->crtc)
504 drmModeFreeCrtc(drmcrtc->crtc);
505 drmcrtc->crtc = drmModeGetCrtc(drmdpy->fd, crtc_id);
506
507 assert(num_nconns < Elements(drmcrtc->connectors));
508 memcpy(drmcrtc->connectors, connector_ids,
509 sizeof(*connector_ids) * num_nconns);
510 drmcrtc->num_connectors = num_nconns;
511
512 drmsurf->is_shown = TRUE;
513 }
514
515 return TRUE;
516 }
517
518 static const struct native_mode **
519 drm_display_get_modes(struct native_display *ndpy,
520 const struct native_connector *nconn,
521 int *num_modes)
522 {
523 struct drm_display *drmdpy = drm_display(ndpy);
524 struct drm_connector *drmconn = drm_connector(nconn);
525 const struct native_mode **nmodes_return;
526 int count, i;
527
528 /* delete old data */
529 if (drmconn->connector) {
530 drmModeFreeConnector(drmconn->connector);
531 FREE(drmconn->drm_modes);
532
533 drmconn->connector = NULL;
534 drmconn->drm_modes = NULL;
535 drmconn->num_modes = 0;
536 }
537
538 /* detect again */
539 drmconn->connector = drmModeGetConnector(drmdpy->fd, drmconn->connector_id);
540 if (!drmconn->connector)
541 return NULL;
542
543 count = drmconn->connector->count_modes;
544 drmconn->drm_modes = CALLOC(count, sizeof(*drmconn->drm_modes));
545 if (!drmconn->drm_modes) {
546 drmModeFreeConnector(drmconn->connector);
547 drmconn->connector = NULL;
548
549 return NULL;
550 }
551
552 for (i = 0; i < count; i++) {
553 struct drm_mode *drmmode = &drmconn->drm_modes[i];
554 drmModeModeInfoPtr mode = &drmconn->connector->modes[i];
555
556 drmmode->mode = *mode;
557
558 drmmode->base.desc = drmmode->mode.name;
559 drmmode->base.width = drmmode->mode.hdisplay;
560 drmmode->base.height = drmmode->mode.vdisplay;
561 drmmode->base.refresh_rate = drmmode->mode.vrefresh;
562 /* not all kernels have vrefresh = refresh_rate * 1000 */
563 if (drmmode->base.refresh_rate < 1000)
564 drmmode->base.refresh_rate *= 1000;
565 }
566
567 nmodes_return = MALLOC(count * sizeof(*nmodes_return));
568 if (nmodes_return) {
569 for (i = 0; i < count; i++)
570 nmodes_return[i] = &drmconn->drm_modes[i].base;
571 if (num_modes)
572 *num_modes = count;
573 }
574
575 return nmodes_return;
576 }
577
578 static const struct native_connector **
579 drm_display_get_connectors(struct native_display *ndpy, int *num_connectors,
580 int *num_crtc)
581 {
582 struct drm_display *drmdpy = drm_display(ndpy);
583 const struct native_connector **connectors;
584 int i;
585
586 if (!drmdpy->connectors) {
587 drmdpy->connectors =
588 CALLOC(drmdpy->resources->count_connectors, sizeof(*drmdpy->connectors));
589 if (!drmdpy->connectors)
590 return NULL;
591
592 for (i = 0; i < drmdpy->resources->count_connectors; i++) {
593 struct drm_connector *drmconn = &drmdpy->connectors[i];
594
595 drmconn->connector_id = drmdpy->resources->connectors[i];
596 /* drmconn->connector is allocated when the modes are asked */
597 }
598
599 drmdpy->num_connectors = drmdpy->resources->count_connectors;
600 }
601
602 connectors = MALLOC(drmdpy->num_connectors * sizeof(*connectors));
603 if (connectors) {
604 for (i = 0; i < drmdpy->num_connectors; i++)
605 connectors[i] = &drmdpy->connectors[i].base;
606 if (num_connectors)
607 *num_connectors = drmdpy->num_connectors;
608 }
609
610 if (num_crtc)
611 *num_crtc = drmdpy->resources->count_crtcs;
612
613 return connectors;
614 }
615
616 static struct native_surface *
617 drm_display_create_scanout_surface(struct native_display *ndpy,
618 const struct native_config *nconf,
619 uint width, uint height)
620 {
621 struct drm_surface *drmsurf;
622
623 drmsurf = drm_display_create_surface(ndpy, nconf, width, height);
624 return &drmsurf->base;
625 }
626
627 static struct native_display_modeset drm_display_modeset = {
628 .get_connectors = drm_display_get_connectors,
629 .get_modes = drm_display_get_modes,
630 .create_scanout_surface = drm_display_create_scanout_surface,
631 .program = drm_display_program
632 };
633
634 void
635 drm_display_fini_modeset(struct native_display *ndpy)
636 {
637 struct drm_display *drmdpy = drm_display(ndpy);
638 int i;
639
640 if (drmdpy->connectors) {
641 for (i = 0; i < drmdpy->num_connectors; i++) {
642 struct drm_connector *drmconn = &drmdpy->connectors[i];
643 if (drmconn->connector) {
644 drmModeFreeConnector(drmconn->connector);
645 FREE(drmconn->drm_modes);
646 }
647 }
648 FREE(drmdpy->connectors);
649 }
650
651 FREE(drmdpy->shown_surfaces);
652 drmdpy->shown_surfaces = NULL;
653
654 if (drmdpy->saved_crtcs) {
655 for (i = 0; i < drmdpy->resources->count_crtcs; i++) {
656 struct drm_crtc *drmcrtc = &drmdpy->saved_crtcs[i];
657
658 if (drmcrtc->crtc) {
659 /* restore crtc */
660 drmModeSetCrtc(drmdpy->fd, drmcrtc->crtc->crtc_id,
661 drmcrtc->crtc->buffer_id, drmcrtc->crtc->x, drmcrtc->crtc->y,
662 drmcrtc->connectors, drmcrtc->num_connectors,
663 &drmcrtc->crtc->mode);
664
665 drmModeFreeCrtc(drmcrtc->crtc);
666 }
667 }
668 FREE(drmdpy->saved_crtcs);
669 }
670
671 if (drmdpy->resources) {
672 drmModeFreeResources(drmdpy->resources);
673 drmdpy->resources = NULL;
674 }
675
676 drmdpy->base.modeset = NULL;
677 }
678
679 boolean
680 drm_display_init_modeset(struct native_display *ndpy)
681 {
682 struct drm_display *drmdpy = drm_display(ndpy);
683
684 /* resources are fixed, unlike crtc, connector, or encoder */
685 drmdpy->resources = drmModeGetResources(drmdpy->fd);
686 if (!drmdpy->resources) {
687 _eglLog(_EGL_DEBUG, "Failed to get KMS resources. Disable modeset.");
688 return FALSE;
689 }
690
691 drmdpy->saved_crtcs =
692 CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->saved_crtcs));
693 if (!drmdpy->saved_crtcs) {
694 drm_display_fini_modeset(&drmdpy->base);
695 return FALSE;
696 }
697
698 drmdpy->shown_surfaces =
699 CALLOC(drmdpy->resources->count_crtcs, sizeof(*drmdpy->shown_surfaces));
700 if (!drmdpy->shown_surfaces) {
701 drm_display_fini_modeset(&drmdpy->base);
702 return FALSE;
703 }
704
705 drmdpy->base.modeset = &drm_display_modeset;
706
707 return TRUE;
708 }