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