Merge branch 'gallium-nopointsizeminmax'
[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 / 1000;
503 }
504
505 nmodes_return = malloc(count * sizeof(*nmodes_return));
506 if (nmodes_return) {
507 for (i = 0; i < count; i++)
508 nmodes_return[i] = &kconn->kms_modes[i].base;
509 if (num_modes)
510 *num_modes = count;
511 }
512
513 return nmodes_return;
514 }
515
516 static const struct native_connector **
517 kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
518 int *num_crtc)
519 {
520 struct kms_display *kdpy = kms_display(ndpy);
521 const struct native_connector **connectors;
522 int i;
523
524 if (!kdpy->connectors) {
525 kdpy->connectors =
526 calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
527 if (!kdpy->connectors)
528 return NULL;
529
530 for (i = 0; i < kdpy->resources->count_connectors; i++) {
531 struct kms_connector *kconn = &kdpy->connectors[i];
532
533 kconn->connector_id = kdpy->resources->connectors[i];
534 /* kconn->connector is allocated when the modes are asked */
535 }
536
537 kdpy->num_connectors = kdpy->resources->count_connectors;
538 }
539
540 connectors = malloc(kdpy->num_connectors * sizeof(*connectors));
541 if (connectors) {
542 for (i = 0; i < kdpy->num_connectors; i++)
543 connectors[i] = &kdpy->connectors[i].base;
544 if (num_connectors)
545 *num_connectors = kdpy->num_connectors;
546 }
547
548 if (num_crtc)
549 *num_crtc = kdpy->resources->count_crtcs;
550
551 return connectors;
552 }
553
554 static struct native_surface *
555 kms_display_create_scanout_surface(struct native_display *ndpy,
556 const struct native_config *nconf,
557 uint width, uint height)
558 {
559 struct kms_surface *ksurf;
560
561 ksurf = kms_display_create_surface(ndpy,
562 KMS_SURFACE_TYPE_SCANOUT, nconf, width, height);
563 return &ksurf->base;
564 }
565
566 static struct native_surface *
567 kms_display_create_pbuffer_surface(struct native_display *ndpy,
568 const struct native_config *nconf,
569 uint width, uint height)
570 {
571 struct kms_surface *ksurf;
572
573 ksurf = kms_display_create_surface(ndpy,
574 KMS_SURFACE_TYPE_PBUFFER, nconf, width, height);
575 return &ksurf->base;
576 }
577
578
579 static boolean
580 kms_display_is_format_supported(struct native_display *ndpy,
581 enum pipe_format fmt, boolean is_color)
582 {
583 return ndpy->screen->is_format_supported(ndpy->screen,
584 fmt, PIPE_TEXTURE_2D,
585 (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
586 PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
587 }
588
589 static const struct native_config **
590 kms_display_get_configs(struct native_display *ndpy, int *num_configs)
591 {
592 struct kms_display *kdpy = kms_display(ndpy);
593 const struct native_config **configs;
594
595 /* first time */
596 if (!kdpy->config) {
597 struct native_config *nconf;
598 enum pipe_format format;
599
600 kdpy->config = calloc(1, sizeof(*kdpy->config));
601 if (!kdpy->config)
602 return NULL;
603
604 nconf = &kdpy->config->base;
605
606 /* always double-buffered */
607 nconf->mode.doubleBufferMode = TRUE;
608
609 format = PIPE_FORMAT_A8R8G8B8_UNORM;
610 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
611 format = PIPE_FORMAT_B8G8R8A8_UNORM;
612 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
613 format = PIPE_FORMAT_NONE;
614 }
615 if (format == PIPE_FORMAT_NONE)
616 return NULL;
617
618 nconf->color_format = format;
619 nconf->mode.redBits = 8;
620 nconf->mode.greenBits = 8;
621 nconf->mode.blueBits = 8;
622 nconf->mode.alphaBits = 8;
623 nconf->mode.rgbBits = 32;
624
625 format = PIPE_FORMAT_S8Z24_UNORM;
626 if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) {
627 format = PIPE_FORMAT_Z24S8_UNORM;
628 if (!kms_display_is_format_supported(&kdpy->base, format, FALSE))
629 format = PIPE_FORMAT_NONE;
630 }
631 if (format != PIPE_FORMAT_NONE) {
632 nconf->depth_format = format;
633 nconf->stencil_format = format;
634
635 nconf->mode.depthBits = 24;
636 nconf->mode.stencilBits = 8;
637 nconf->mode.haveDepthBuffer = TRUE;
638 nconf->mode.haveStencilBuffer = TRUE;
639 }
640
641 nconf->scanout_bit = TRUE;
642 nconf->mode.drawableType = GLX_PBUFFER_BIT;
643 nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML;
644
645 nconf->mode.visualID = 0;
646 nconf->mode.visualType = EGL_NONE;
647
648 nconf->mode.renderType = GLX_RGBA_BIT;
649 nconf->mode.rgbMode = TRUE;
650 nconf->mode.xRenderable = FALSE;
651 }
652
653 configs = malloc(sizeof(*configs));
654 if (configs) {
655 configs[0] = &kdpy->config->base;
656 if (num_configs)
657 *num_configs = 1;
658 }
659
660 return configs;
661 }
662
663 static void
664 kms_display_destroy(struct native_display *ndpy)
665 {
666 struct kms_display *kdpy = kms_display(ndpy);
667 int i;
668
669 if (kdpy->config)
670 free(kdpy->config);
671
672 if (kdpy->connectors) {
673 for (i = 0; i < kdpy->num_connectors; i++) {
674 struct kms_connector *kconn = &kdpy->connectors[i];
675 if (kconn->connector) {
676 drmModeFreeConnector(kconn->connector);
677 free(kconn->kms_modes);
678 }
679 }
680 free(kdpy->connectors);
681 }
682
683 if (kdpy->shown_surfaces)
684 free(kdpy->shown_surfaces);
685
686 if (kdpy->saved_crtcs) {
687 for (i = 0; i < kdpy->resources->count_crtcs; i++) {
688 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
689
690 if (kcrtc->crtc) {
691 /* restore crtc */
692 drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
693 kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
694 kcrtc->connectors, kcrtc->num_connectors,
695 &kcrtc->crtc->mode);
696
697 drmModeFreeCrtc(kcrtc->crtc);
698 }
699 }
700 free(kdpy->saved_crtcs);
701 }
702
703 if (kdpy->resources)
704 drmModeFreeResources(kdpy->resources);
705
706 if (kdpy->base.screen)
707 kdpy->base.screen->destroy(kdpy->base.screen);
708
709 if (kdpy->fd >= 0)
710 drmClose(kdpy->fd);
711
712 if (kdpy->api)
713 kdpy->api->destroy(kdpy->api);
714 free(kdpy);
715 }
716
717 /**
718 * Initialize KMS and pipe screen.
719 */
720 static boolean
721 kms_display_init_screen(struct native_display *ndpy)
722 {
723 struct kms_display *kdpy = kms_display(ndpy);
724 struct drm_create_screen_arg arg;
725 int fd;
726
727 fd = drmOpen(kdpy->api->name, NULL);
728 if (fd < 0) {
729 _eglLog(_EGL_WARNING, "failed to open DRM device");
730 return FALSE;
731 }
732
733 #if 0
734 if (drmSetMaster(fd)) {
735 _eglLog(_EGL_WARNING, "failed to become DRM master");
736 return FALSE;
737 }
738 #endif
739
740 memset(&arg, 0, sizeof(arg));
741 arg.mode = DRM_CREATE_NORMAL;
742 kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg);
743 if (!kdpy->base.screen) {
744 _eglLog(_EGL_WARNING, "failed to create DRM screen");
745 drmClose(fd);
746 return FALSE;
747 }
748
749 kdpy->fd = fd;
750
751 return TRUE;
752 }
753
754 static struct native_display_modeset kms_display_modeset = {
755 .get_connectors = kms_display_get_connectors,
756 .get_modes = kms_display_get_modes,
757 .create_scanout_surface = kms_display_create_scanout_surface,
758 .program = kms_display_program
759 };
760
761 static struct native_display *
762 kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
763 {
764 struct kms_display *kdpy;
765
766 kdpy = CALLOC_STRUCT(kms_display);
767 if (!kdpy)
768 return NULL;
769
770 kdpy->api = api;
771 if (!kdpy->api) {
772 _eglLog(_EGL_WARNING, "failed to create DRM API");
773 free(kdpy);
774 return NULL;
775 }
776
777 kdpy->fd = -1;
778 if (!kms_display_init_screen(&kdpy->base)) {
779 kms_display_destroy(&kdpy->base);
780 return NULL;
781 }
782
783 /* resources are fixed, unlike crtc, connector, or encoder */
784 kdpy->resources = drmModeGetResources(kdpy->fd);
785 if (!kdpy->resources) {
786 kms_display_destroy(&kdpy->base);
787 return NULL;
788 }
789
790 kdpy->saved_crtcs =
791 calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
792 if (!kdpy->saved_crtcs) {
793 kms_display_destroy(&kdpy->base);
794 return NULL;
795 }
796
797 kdpy->shown_surfaces =
798 calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
799 if (!kdpy->shown_surfaces) {
800 kms_display_destroy(&kdpy->base);
801 return NULL;
802 }
803
804 kdpy->base.destroy = kms_display_destroy;
805 kdpy->base.get_configs = kms_display_get_configs;
806 kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface;
807
808 kdpy->base.modeset = &kms_display_modeset;
809
810 return &kdpy->base;
811 }
812
813 struct native_probe *
814 native_create_probe(EGLNativeDisplayType dpy)
815 {
816 return NULL;
817 }
818
819 enum native_probe_result
820 native_get_probe_result(struct native_probe *nprobe)
821 {
822 return NATIVE_PROBE_UNKNOWN;
823 }
824
825 /* the api is destroyed with the native display */
826 static struct drm_api *drm_api;
827
828 const char *
829 native_get_name(void)
830 {
831 static char kms_name[32];
832
833 if (!drm_api)
834 drm_api = drm_api_create();
835
836 if (drm_api)
837 snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name);
838 else
839 snprintf(kms_name, sizeof(kms_name), "KMS");
840
841 return kms_name;
842 }
843
844 struct native_display *
845 native_create_display(EGLNativeDisplayType dpy)
846 {
847 struct native_display *ndpy = NULL;
848
849 if (!drm_api)
850 drm_api = drm_api_create();
851
852 if (drm_api)
853 ndpy = kms_create_display(dpy, drm_api);
854
855 return ndpy;
856 }