Merge branch 'mesa_7_7_branch'
[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 <string.h>
26
27 #include "pipe/p_screen.h"
28 #include "pipe/p_context.h"
29 #include "util/u_debug.h"
30 #include "util/u_memory.h"
31 #include "egllog.h"
32
33 #include "native_kms.h"
34
35 static boolean
36 kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
37 unsigned int *seq_num, struct pipe_texture **textures,
38 int *width, int *height)
39 {
40 struct kms_surface *ksurf = kms_surface(nsurf);
41 struct kms_display *kdpy = ksurf->kdpy;
42 struct pipe_screen *screen = kdpy->base.screen;
43 struct pipe_texture templ, *ptex;
44 int att;
45
46 if (attachment_mask) {
47 memset(&templ, 0, sizeof(templ));
48 templ.target = PIPE_TEXTURE_2D;
49 templ.last_level = 0;
50 templ.width0 = ksurf->width;
51 templ.height0 = ksurf->height;
52 templ.depth0 = 1;
53 templ.format = ksurf->color_format;
54 templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET;
55 if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT)
56 templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY;
57 }
58
59 /* create textures */
60 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
61 /* delay the allocation */
62 if (!native_attachment_mask_test(attachment_mask, att))
63 continue;
64
65 ptex = ksurf->textures[att];
66 if (!ptex) {
67 ptex = screen->texture_create(screen, &templ);
68 ksurf->textures[att] = ptex;
69 }
70
71 if (textures) {
72 textures[att] = NULL;
73 pipe_texture_reference(&textures[att], ptex);
74 }
75 }
76
77 if (seq_num)
78 *seq_num = ksurf->sequence_number;
79 if (width)
80 *width = ksurf->width;
81 if (height)
82 *height = ksurf->height;
83
84 return TRUE;
85 }
86
87 /**
88 * Add textures as DRM framebuffers.
89 */
90 static boolean
91 kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
92 {
93 struct kms_surface *ksurf = kms_surface(nsurf);
94 struct kms_display *kdpy = ksurf->kdpy;
95 int num_framebuffers = (need_back) ? 2 : 1;
96 int i, err;
97
98 for (i = 0; i < num_framebuffers; i++) {
99 struct kms_framebuffer *fb;
100 enum native_attachment natt;
101 unsigned int handle, stride;
102 uint block_bits;
103
104 if (i == 0) {
105 fb = &ksurf->front_fb;
106 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
107 }
108 else {
109 fb = &ksurf->back_fb;
110 natt = NATIVE_ATTACHMENT_BACK_LEFT;
111 }
112
113 if (!fb->texture) {
114 /* make sure the texture has been allocated */
115 kms_surface_validate(&ksurf->base, 1 << natt, NULL, NULL, NULL, NULL);
116 if (!ksurf->textures[natt])
117 return FALSE;
118
119 pipe_texture_reference(&fb->texture, ksurf->textures[natt]);
120 }
121
122 /* already initialized */
123 if (fb->buffer_id)
124 continue;
125
126 /* TODO detect the real value */
127 fb->is_passive = TRUE;
128
129 if (!kdpy->api->local_handle_from_texture(kdpy->api,
130 kdpy->base.screen, fb->texture, &stride, &handle))
131 return FALSE;
132
133 block_bits = util_format_get_blocksizebits(ksurf->color_format);
134 err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height,
135 block_bits, block_bits, stride, handle, &fb->buffer_id);
136 if (err) {
137 fb->buffer_id = 0;
138 return FALSE;
139 }
140 }
141
142 return TRUE;
143 }
144
145 static boolean
146 kms_surface_flush_frontbuffer(struct native_surface *nsurf)
147 {
148 #ifdef DRM_MODE_FEATURE_DIRTYFB
149 struct kms_surface *ksurf = kms_surface(nsurf);
150 struct kms_display *kdpy = ksurf->kdpy;
151
152 /* pbuffer is private */
153 if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
154 return TRUE;
155
156 if (ksurf->front_fb.is_passive)
157 drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
158 #endif
159
160 return TRUE;
161 }
162
163 static boolean
164 kms_surface_swap_buffers(struct native_surface *nsurf)
165 {
166 struct kms_surface *ksurf = kms_surface(nsurf);
167 struct kms_crtc *kcrtc = &ksurf->current_crtc;
168 struct kms_display *kdpy = ksurf->kdpy;
169 struct kms_framebuffer tmp_fb;
170 struct pipe_texture *tmp_texture;
171 int err;
172
173 /* pbuffer is private */
174 if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER)
175 return TRUE;
176
177 if (!ksurf->back_fb.buffer_id) {
178 if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
179 return FALSE;
180 }
181
182 if (ksurf->is_shown && kcrtc->crtc) {
183 err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
184 ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
185 kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
186 if (err)
187 return FALSE;
188 }
189
190 /* swap the buffers */
191 tmp_fb = ksurf->front_fb;
192 ksurf->front_fb = ksurf->back_fb;
193 ksurf->back_fb = tmp_fb;
194
195 tmp_texture = ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT];
196 ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT] =
197 ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT];
198 ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture;
199
200 /* the front/back textures are swapped */
201 ksurf->sequence_number++;
202
203 return TRUE;
204 }
205
206 static void
207 kms_surface_wait(struct native_surface *nsurf)
208 {
209 /* no-op */
210 }
211
212 static void
213 kms_surface_destroy(struct native_surface *nsurf)
214 {
215 struct kms_surface *ksurf = kms_surface(nsurf);
216 int i;
217
218 if (ksurf->current_crtc.crtc)
219 drmModeFreeCrtc(ksurf->current_crtc.crtc);
220
221 if (ksurf->front_fb.buffer_id)
222 drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id);
223 pipe_texture_reference(&ksurf->front_fb.texture, NULL);
224
225 if (ksurf->back_fb.buffer_id)
226 drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id);
227 pipe_texture_reference(&ksurf->back_fb.texture, NULL);
228
229 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
230 struct pipe_texture *ptex = ksurf->textures[i];
231 pipe_texture_reference(&ptex, NULL);
232 }
233
234 free(ksurf);
235 }
236
237 static struct kms_surface *
238 kms_display_create_surface(struct native_display *ndpy,
239 enum kms_surface_type type,
240 const struct native_config *nconf,
241 uint width, uint height)
242 {
243 struct kms_display *kdpy = kms_display(ndpy);
244 struct kms_config *kconf = kms_config(nconf);
245 struct kms_surface *ksurf;
246
247 ksurf = CALLOC_STRUCT(kms_surface);
248 if (!ksurf)
249 return NULL;
250
251 ksurf->kdpy = kdpy;
252 ksurf->type = type;
253 ksurf->color_format = kconf->base.color_format;
254 ksurf->width = width;
255 ksurf->height = height;
256
257 ksurf->base.destroy = kms_surface_destroy;
258 ksurf->base.swap_buffers = kms_surface_swap_buffers;
259 ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
260 ksurf->base.validate = kms_surface_validate;
261 ksurf->base.wait = kms_surface_wait;
262
263 return ksurf;
264 }
265
266 /**
267 * Choose a CRTC that supports all given connectors.
268 */
269 static uint32_t
270 kms_display_choose_crtc(struct native_display *ndpy,
271 uint32_t *connectors, int num_connectors)
272 {
273 struct kms_display *kdpy = kms_display(ndpy);
274 int idx;
275
276 for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
277 boolean found_crtc = TRUE;
278 int i, j;
279
280 for (i = 0; i < num_connectors; i++) {
281 drmModeConnectorPtr connector;
282 int encoder_idx = -1;
283
284 connector = drmModeGetConnector(kdpy->fd, connectors[i]);
285 if (!connector) {
286 found_crtc = FALSE;
287 break;
288 }
289
290 /* find an encoder the CRTC supports */
291 for (j = 0; j < connector->count_encoders; j++) {
292 drmModeEncoderPtr encoder =
293 drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
294 if (encoder->possible_crtcs & (1 << idx)) {
295 encoder_idx = j;
296 break;
297 }
298 drmModeFreeEncoder(encoder);
299 }
300
301 drmModeFreeConnector(connector);
302 if (encoder_idx < 0) {
303 found_crtc = FALSE;
304 break;
305 }
306 }
307
308 if (found_crtc)
309 break;
310 }
311
312 if (idx >= kdpy->resources->count_crtcs) {
313 _eglLog(_EGL_WARNING,
314 "failed to find a CRTC that supports the given %d connectors",
315 num_connectors);
316 return 0;
317 }
318
319 return kdpy->resources->crtcs[idx];
320 }
321
322 /**
323 * Remember the original CRTC status and set the CRTC
324 */
325 static boolean
326 kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
327 uint32_t buffer_id, uint32_t x, uint32_t y,
328 uint32_t *connectors, int num_connectors,
329 drmModeModeInfoPtr mode)
330 {
331 struct kms_display *kdpy = kms_display(ndpy);
332 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
333 uint32_t crtc_id;
334 int err;
335
336 if (kcrtc->crtc) {
337 crtc_id = kcrtc->crtc->crtc_id;
338 }
339 else {
340 int count = 0, i;
341
342 /*
343 * Choose the CRTC once. It could be more dynamic, but let's keep it
344 * simple for now.
345 */
346 crtc_id = kms_display_choose_crtc(&kdpy->base,
347 connectors, num_connectors);
348
349 /* save the original CRTC status */
350 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
351 if (!kcrtc->crtc)
352 return FALSE;
353
354 for (i = 0; i < kdpy->num_connectors; i++) {
355 struct kms_connector *kconn = &kdpy->connectors[i];
356 drmModeConnectorPtr connector = kconn->connector;
357 drmModeEncoderPtr encoder;
358
359 encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
360 if (encoder) {
361 if (encoder->crtc_id == crtc_id) {
362 kcrtc->connectors[count++] = connector->connector_id;
363 if (count >= Elements(kcrtc->connectors))
364 break;
365 }
366 drmModeFreeEncoder(encoder);
367 }
368 }
369
370 kcrtc->num_connectors = count;
371 }
372
373 err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
374 connectors, num_connectors, mode);
375 if (err) {
376 drmModeFreeCrtc(kcrtc->crtc);
377 kcrtc->crtc = NULL;
378 kcrtc->num_connectors = 0;
379
380 return FALSE;
381 }
382
383 return TRUE;
384 }
385
386 static boolean
387 kms_display_program(struct native_display *ndpy, int crtc_idx,
388 struct native_surface *nsurf, uint x, uint y,
389 const struct native_connector **nconns, int num_nconns,
390 const struct native_mode *nmode)
391 {
392 struct kms_display *kdpy = kms_display(ndpy);
393 struct kms_surface *ksurf = kms_surface(nsurf);
394 const struct kms_mode *kmode = kms_mode(nmode);
395 uint32_t connector_ids[32];
396 uint32_t buffer_id;
397 drmModeModeInfo mode_tmp, *mode;
398 int i;
399
400 if (num_nconns > Elements(connector_ids)) {
401 _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
402 num_nconns = Elements(connector_ids);
403 }
404
405 if (ksurf) {
406 if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
407 return FALSE;
408
409 buffer_id = ksurf->front_fb.buffer_id;
410 /* the mode argument of drmModeSetCrtc is not constified */
411 mode_tmp = kmode->mode;
412 mode = &mode_tmp;
413 }
414 else {
415 /* disable the CRTC */
416 buffer_id = 0;
417 mode = NULL;
418 num_nconns = 0;
419 }
420
421 for (i = 0; i < num_nconns; i++) {
422 struct kms_connector *kconn = kms_connector(nconns[i]);
423 connector_ids[i] = kconn->connector->connector_id;
424 }
425
426 if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
427 connector_ids, num_nconns, mode)) {
428 _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
429
430 return FALSE;
431 }
432
433 if (kdpy->shown_surfaces[crtc_idx])
434 kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
435 kdpy->shown_surfaces[crtc_idx] = ksurf;
436
437 /* remember the settings for buffer swapping */
438 if (ksurf) {
439 uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
440 struct kms_crtc *kcrtc = &ksurf->current_crtc;
441
442 if (kcrtc->crtc)
443 drmModeFreeCrtc(kcrtc->crtc);
444 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
445
446 assert(num_nconns < Elements(kcrtc->connectors));
447 memcpy(kcrtc->connectors, connector_ids,
448 sizeof(*connector_ids) * num_nconns);
449 kcrtc->num_connectors = num_nconns;
450
451 ksurf->is_shown = TRUE;
452 }
453
454 return TRUE;
455 }
456
457 static const struct native_mode **
458 kms_display_get_modes(struct native_display *ndpy,
459 const struct native_connector *nconn,
460 int *num_modes)
461 {
462 struct kms_display *kdpy = kms_display(ndpy);
463 struct kms_connector *kconn = kms_connector(nconn);
464 const struct native_mode **nmodes_return;
465 int count, i;
466
467 /* delete old data */
468 if (kconn->connector) {
469 drmModeFreeConnector(kconn->connector);
470 free(kconn->kms_modes);
471
472 kconn->connector = NULL;
473 kconn->kms_modes = NULL;
474 kconn->num_modes = 0;
475 }
476
477 /* detect again */
478 kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
479 if (!kconn->connector)
480 return NULL;
481
482 count = kconn->connector->count_modes;
483 kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes));
484 if (!kconn->kms_modes) {
485 drmModeFreeConnector(kconn->connector);
486 kconn->connector = NULL;
487
488 return NULL;
489 }
490
491 for (i = 0; i < count; i++) {
492 struct kms_mode *kmode = &kconn->kms_modes[i];
493 drmModeModeInfoPtr mode = &kconn->connector->modes[i];
494
495 kmode->mode = *mode;
496
497 kmode->base.desc = kmode->mode.name;
498 kmode->base.width = kmode->mode.hdisplay;
499 kmode->base.height = kmode->mode.vdisplay;
500 kmode->base.refresh_rate = kmode->mode.vrefresh / 1000;
501 }
502
503 nmodes_return = malloc(count * sizeof(*nmodes_return));
504 if (nmodes_return) {
505 for (i = 0; i < count; i++)
506 nmodes_return[i] = &kconn->kms_modes[i].base;
507 if (num_modes)
508 *num_modes = count;
509 }
510
511 return nmodes_return;
512 }
513
514 static const struct native_connector **
515 kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
516 int *num_crtc)
517 {
518 struct kms_display *kdpy = kms_display(ndpy);
519 const struct native_connector **connectors;
520 int i;
521
522 if (!kdpy->connectors) {
523 kdpy->connectors =
524 calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
525 if (!kdpy->connectors)
526 return NULL;
527
528 for (i = 0; i < kdpy->resources->count_connectors; i++) {
529 struct kms_connector *kconn = &kdpy->connectors[i];
530
531 kconn->connector_id = kdpy->resources->connectors[i];
532 /* kconn->connector is allocated when the modes are asked */
533 }
534
535 kdpy->num_connectors = kdpy->resources->count_connectors;
536 }
537
538 connectors = malloc(kdpy->num_connectors * sizeof(*connectors));
539 if (connectors) {
540 for (i = 0; i < kdpy->num_connectors; i++)
541 connectors[i] = &kdpy->connectors[i].base;
542 if (num_connectors)
543 *num_connectors = kdpy->num_connectors;
544 }
545
546 if (num_crtc)
547 *num_crtc = kdpy->resources->count_crtcs;
548
549 return connectors;
550 }
551
552 static struct native_surface *
553 kms_display_create_scanout_surface(struct native_display *ndpy,
554 const struct native_config *nconf,
555 uint width, uint height)
556 {
557 struct kms_surface *ksurf;
558
559 ksurf = kms_display_create_surface(ndpy,
560 KMS_SURFACE_TYPE_SCANOUT, nconf, width, height);
561 return &ksurf->base;
562 }
563
564 static struct native_surface *
565 kms_display_create_pbuffer_surface(struct native_display *ndpy,
566 const struct native_config *nconf,
567 uint width, uint height)
568 {
569 struct kms_surface *ksurf;
570
571 ksurf = kms_display_create_surface(ndpy,
572 KMS_SURFACE_TYPE_PBUFFER, nconf, width, height);
573 return &ksurf->base;
574 }
575
576 static struct pipe_context *
577 kms_display_create_context(struct native_display *ndpy, void *context_private)
578 {
579 struct kms_display *kdpy = kms_display(ndpy);
580 struct pipe_context *pctx;
581
582 pctx = kdpy->api->create_context(kdpy->api, kdpy->base.screen);
583 if (pctx)
584 pctx->priv = context_private;
585 return pctx;
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_A8R8G8B8_UNORM;
619 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
620 format = PIPE_FORMAT_B8G8R8A8_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_S8Z24_UNORM;
635 if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) {
636 format = PIPE_FORMAT_Z24S8_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 void
673 kms_display_destroy(struct native_display *ndpy)
674 {
675 struct kms_display *kdpy = kms_display(ndpy);
676 int i;
677
678 if (kdpy->config)
679 free(kdpy->config);
680
681 if (kdpy->connectors) {
682 for (i = 0; i < kdpy->num_connectors; i++) {
683 struct kms_connector *kconn = &kdpy->connectors[i];
684 if (kconn->connector) {
685 drmModeFreeConnector(kconn->connector);
686 free(kconn->kms_modes);
687 }
688 }
689 free(kdpy->connectors);
690 }
691
692 if (kdpy->shown_surfaces)
693 free(kdpy->shown_surfaces);
694
695 if (kdpy->saved_crtcs) {
696 for (i = 0; i < kdpy->resources->count_crtcs; i++) {
697 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
698
699 if (kcrtc->crtc) {
700 /* restore crtc */
701 drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
702 kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
703 kcrtc->connectors, kcrtc->num_connectors,
704 &kcrtc->crtc->mode);
705
706 drmModeFreeCrtc(kcrtc->crtc);
707 }
708 }
709 free(kdpy->saved_crtcs);
710 }
711
712 if (kdpy->resources)
713 drmModeFreeResources(kdpy->resources);
714
715 if (kdpy->base.screen)
716 kdpy->base.screen->destroy(kdpy->base.screen);
717
718 if (kdpy->fd >= 0)
719 drmClose(kdpy->fd);
720
721 if (kdpy->api)
722 kdpy->api->destroy(kdpy->api);
723 free(kdpy);
724 }
725
726 /**
727 * Initialize KMS and pipe screen.
728 */
729 static boolean
730 kms_display_init_screen(struct native_display *ndpy)
731 {
732 struct kms_display *kdpy = kms_display(ndpy);
733 struct drm_create_screen_arg arg;
734 int fd;
735
736 fd = drmOpen(kdpy->api->name, NULL);
737 if (fd < 0) {
738 _eglLog(_EGL_WARNING, "failed to open DRM device");
739 return FALSE;
740 }
741
742 #if 0
743 if (drmSetMaster(fd)) {
744 _eglLog(_EGL_WARNING, "failed to become DRM master");
745 return FALSE;
746 }
747 #endif
748
749 memset(&arg, 0, sizeof(arg));
750 arg.mode = DRM_CREATE_NORMAL;
751 kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg);
752 if (!kdpy->base.screen) {
753 _eglLog(_EGL_WARNING, "failed to create DRM screen");
754 drmClose(fd);
755 return FALSE;
756 }
757
758 kdpy->fd = fd;
759
760 return TRUE;
761 }
762
763 static struct native_display_modeset kms_display_modeset = {
764 .get_connectors = kms_display_get_connectors,
765 .get_modes = kms_display_get_modes,
766 .create_scanout_surface = kms_display_create_scanout_surface,
767 .program = kms_display_program
768 };
769
770 static struct native_display *
771 kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api)
772 {
773 struct kms_display *kdpy;
774
775 kdpy = CALLOC_STRUCT(kms_display);
776 if (!kdpy)
777 return NULL;
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_context = kms_display_create_context;
816 kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface;
817
818 kdpy->base.modeset = &kms_display_modeset;
819
820 return &kdpy->base;
821 }
822
823 struct native_probe *
824 native_create_probe(EGLNativeDisplayType dpy)
825 {
826 return NULL;
827 }
828
829 enum native_probe_result
830 native_get_probe_result(struct native_probe *nprobe)
831 {
832 return NATIVE_PROBE_UNKNOWN;
833 }
834
835 /* the api is destroyed with the native display */
836 static struct drm_api *drm_api;
837
838 const char *
839 native_get_name(void)
840 {
841 static char kms_name[32];
842
843 if (!drm_api)
844 drm_api = drm_api_create();
845
846 if (drm_api)
847 snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name);
848 else
849 snprintf(kms_name, sizeof(kms_name), "KMS");
850
851 return kms_name;
852 }
853
854 struct native_display *
855 native_create_display(EGLNativeDisplayType dpy)
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, drm_api);
864
865 return ndpy;
866 }