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