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