2 * Mesa 3-D graphics library
5 * Copyright (C) 2010 Chia-I Wu <olv@0xlab.org>
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
26 #include "pipe/p_screen.h"
27 #include "pipe/p_context.h"
28 #include "util/u_debug.h"
29 #include "util/u_memory.h"
30 #include "util/u_inlines.h"
31 #include "util/u_pointer.h"
32 #include "util/u_string.h"
35 #include "native_kms.h"
36 #include "state_tracker/drm_driver.h"
39 kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
40 unsigned int *seq_num, struct pipe_resource **textures,
41 int *width, int *height)
43 struct kms_surface *ksurf = kms_surface(nsurf);
45 if (!resource_surface_add_resources(ksurf->rsurf, attachment_mask))
48 resource_surface_get_resources(ksurf->rsurf, textures, attachment_mask);
51 *seq_num = ksurf->sequence_number;
53 *width = ksurf->width;
55 *height = ksurf->height;
61 * Add textures as DRM framebuffers.
64 kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
66 struct kms_surface *ksurf = kms_surface(nsurf);
67 struct kms_display *kdpy = ksurf->kdpy;
68 int num_framebuffers = (need_back) ? 2 : 1;
71 for (i = 0; i < num_framebuffers; i++) {
72 struct kms_framebuffer *fb;
73 enum native_attachment natt;
74 struct winsys_handle whandle;
78 fb = &ksurf->front_fb;
79 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
83 natt = NATIVE_ATTACHMENT_BACK_LEFT;
87 /* make sure the texture has been allocated */
88 resource_surface_add_resources(ksurf->rsurf, 1 << natt);
90 resource_surface_get_single_resource(ksurf->rsurf, natt);
95 /* already initialized */
99 /* TODO detect the real value */
100 fb->is_passive = TRUE;
102 memset(&whandle, 0, sizeof(whandle));
103 whandle.type = DRM_API_HANDLE_TYPE_KMS;
105 if (!kdpy->base.screen->resource_get_handle(kdpy->base.screen,
106 fb->texture, &whandle))
109 block_bits = util_format_get_blocksizebits(ksurf->color_format);
110 err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height,
111 block_bits, block_bits, whandle.stride, whandle.handle,
123 kms_surface_flush_frontbuffer(struct native_surface *nsurf)
125 #ifdef DRM_MODE_FEATURE_DIRTYFB
126 struct kms_surface *ksurf = kms_surface(nsurf);
127 struct kms_display *kdpy = ksurf->kdpy;
129 if (ksurf->front_fb.is_passive)
130 drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
137 kms_surface_swap_buffers(struct native_surface *nsurf)
139 struct kms_surface *ksurf = kms_surface(nsurf);
140 struct kms_crtc *kcrtc = &ksurf->current_crtc;
141 struct kms_display *kdpy = ksurf->kdpy;
142 struct kms_framebuffer tmp_fb;
145 if (!ksurf->back_fb.buffer_id) {
146 if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
150 if (ksurf->is_shown && kcrtc->crtc) {
151 err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
152 ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
153 kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
158 /* swap the buffers */
159 tmp_fb = ksurf->front_fb;
160 ksurf->front_fb = ksurf->back_fb;
161 ksurf->back_fb = tmp_fb;
163 resource_surface_swap_buffers(ksurf->rsurf,
164 NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, FALSE);
165 /* the front/back textures are swapped */
166 ksurf->sequence_number++;
167 kdpy->event_handler->invalid_surface(&kdpy->base,
168 &ksurf->base, ksurf->sequence_number);
174 kms_surface_wait(struct native_surface *nsurf)
180 kms_surface_destroy(struct native_surface *nsurf)
182 struct kms_surface *ksurf = kms_surface(nsurf);
184 if (ksurf->current_crtc.crtc)
185 drmModeFreeCrtc(ksurf->current_crtc.crtc);
187 if (ksurf->front_fb.buffer_id)
188 drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id);
189 pipe_resource_reference(&ksurf->front_fb.texture, NULL);
191 if (ksurf->back_fb.buffer_id)
192 drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id);
193 pipe_resource_reference(&ksurf->back_fb.texture, NULL);
195 resource_surface_destroy(ksurf->rsurf);
199 static struct kms_surface *
200 kms_display_create_surface(struct native_display *ndpy,
201 const struct native_config *nconf,
202 uint width, uint height)
204 struct kms_display *kdpy = kms_display(ndpy);
205 struct kms_config *kconf = kms_config(nconf);
206 struct kms_surface *ksurf;
208 ksurf = CALLOC_STRUCT(kms_surface);
213 ksurf->color_format = kconf->base.color_format;
214 ksurf->width = width;
215 ksurf->height = height;
217 ksurf->rsurf = resource_surface_create(kdpy->base.screen,
219 PIPE_BIND_RENDER_TARGET |
220 PIPE_BIND_SAMPLER_VIEW |
221 PIPE_BIND_DISPLAY_TARGET |
228 resource_surface_set_size(ksurf->rsurf, ksurf->width, ksurf->height);
230 ksurf->base.destroy = kms_surface_destroy;
231 ksurf->base.swap_buffers = kms_surface_swap_buffers;
232 ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
233 ksurf->base.validate = kms_surface_validate;
234 ksurf->base.wait = kms_surface_wait;
240 * Choose a CRTC that supports all given connectors.
243 kms_display_choose_crtc(struct native_display *ndpy,
244 uint32_t *connectors, int num_connectors)
246 struct kms_display *kdpy = kms_display(ndpy);
249 for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
250 boolean found_crtc = TRUE;
253 for (i = 0; i < num_connectors; i++) {
254 drmModeConnectorPtr connector;
255 int encoder_idx = -1;
257 connector = drmModeGetConnector(kdpy->fd, connectors[i]);
263 /* find an encoder the CRTC supports */
264 for (j = 0; j < connector->count_encoders; j++) {
265 drmModeEncoderPtr encoder =
266 drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
267 if (encoder->possible_crtcs & (1 << idx)) {
271 drmModeFreeEncoder(encoder);
274 drmModeFreeConnector(connector);
275 if (encoder_idx < 0) {
285 if (idx >= kdpy->resources->count_crtcs) {
286 _eglLog(_EGL_WARNING,
287 "failed to find a CRTC that supports the given %d connectors",
292 return kdpy->resources->crtcs[idx];
296 * Remember the original CRTC status and set the CRTC
299 kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
300 uint32_t buffer_id, uint32_t x, uint32_t y,
301 uint32_t *connectors, int num_connectors,
302 drmModeModeInfoPtr mode)
304 struct kms_display *kdpy = kms_display(ndpy);
305 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
310 crtc_id = kcrtc->crtc->crtc_id;
316 * Choose the CRTC once. It could be more dynamic, but let's keep it
319 crtc_id = kms_display_choose_crtc(&kdpy->base,
320 connectors, num_connectors);
322 /* save the original CRTC status */
323 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
327 for (i = 0; i < kdpy->num_connectors; i++) {
328 struct kms_connector *kconn = &kdpy->connectors[i];
329 drmModeConnectorPtr connector = kconn->connector;
330 drmModeEncoderPtr encoder;
332 encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
334 if (encoder->crtc_id == crtc_id) {
335 kcrtc->connectors[count++] = connector->connector_id;
336 if (count >= Elements(kcrtc->connectors))
339 drmModeFreeEncoder(encoder);
343 kcrtc->num_connectors = count;
346 err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
347 connectors, num_connectors, mode);
349 drmModeFreeCrtc(kcrtc->crtc);
351 kcrtc->num_connectors = 0;
360 kms_display_program(struct native_display *ndpy, int crtc_idx,
361 struct native_surface *nsurf, uint x, uint y,
362 const struct native_connector **nconns, int num_nconns,
363 const struct native_mode *nmode)
365 struct kms_display *kdpy = kms_display(ndpy);
366 struct kms_surface *ksurf = kms_surface(nsurf);
367 const struct kms_mode *kmode = kms_mode(nmode);
368 uint32_t connector_ids[32];
370 drmModeModeInfo mode_tmp, *mode;
373 if (num_nconns > Elements(connector_ids)) {
374 _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
375 num_nconns = Elements(connector_ids);
379 if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
382 buffer_id = ksurf->front_fb.buffer_id;
383 /* the mode argument of drmModeSetCrtc is not constified */
384 mode_tmp = kmode->mode;
388 /* disable the CRTC */
394 for (i = 0; i < num_nconns; i++) {
395 struct kms_connector *kconn = kms_connector(nconns[i]);
396 connector_ids[i] = kconn->connector->connector_id;
399 if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
400 connector_ids, num_nconns, mode)) {
401 _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
406 if (kdpy->shown_surfaces[crtc_idx])
407 kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
408 kdpy->shown_surfaces[crtc_idx] = ksurf;
410 /* remember the settings for buffer swapping */
412 uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
413 struct kms_crtc *kcrtc = &ksurf->current_crtc;
416 drmModeFreeCrtc(kcrtc->crtc);
417 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
419 assert(num_nconns < Elements(kcrtc->connectors));
420 memcpy(kcrtc->connectors, connector_ids,
421 sizeof(*connector_ids) * num_nconns);
422 kcrtc->num_connectors = num_nconns;
424 ksurf->is_shown = TRUE;
430 static const struct native_mode **
431 kms_display_get_modes(struct native_display *ndpy,
432 const struct native_connector *nconn,
435 struct kms_display *kdpy = kms_display(ndpy);
436 struct kms_connector *kconn = kms_connector(nconn);
437 const struct native_mode **nmodes_return;
440 /* delete old data */
441 if (kconn->connector) {
442 drmModeFreeConnector(kconn->connector);
443 FREE(kconn->kms_modes);
445 kconn->connector = NULL;
446 kconn->kms_modes = NULL;
447 kconn->num_modes = 0;
451 kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
452 if (!kconn->connector)
455 count = kconn->connector->count_modes;
456 kconn->kms_modes = CALLOC(count, sizeof(*kconn->kms_modes));
457 if (!kconn->kms_modes) {
458 drmModeFreeConnector(kconn->connector);
459 kconn->connector = NULL;
464 for (i = 0; i < count; i++) {
465 struct kms_mode *kmode = &kconn->kms_modes[i];
466 drmModeModeInfoPtr mode = &kconn->connector->modes[i];
470 kmode->base.desc = kmode->mode.name;
471 kmode->base.width = kmode->mode.hdisplay;
472 kmode->base.height = kmode->mode.vdisplay;
473 kmode->base.refresh_rate = kmode->mode.vrefresh;
474 /* not all kernels have vrefresh = refresh_rate * 1000 */
475 if (kmode->base.refresh_rate > 1000)
476 kmode->base.refresh_rate = (kmode->base.refresh_rate + 500) / 1000;
479 nmodes_return = MALLOC(count * sizeof(*nmodes_return));
481 for (i = 0; i < count; i++)
482 nmodes_return[i] = &kconn->kms_modes[i].base;
487 return nmodes_return;
490 static const struct native_connector **
491 kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
494 struct kms_display *kdpy = kms_display(ndpy);
495 const struct native_connector **connectors;
498 if (!kdpy->connectors) {
500 CALLOC(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
501 if (!kdpy->connectors)
504 for (i = 0; i < kdpy->resources->count_connectors; i++) {
505 struct kms_connector *kconn = &kdpy->connectors[i];
507 kconn->connector_id = kdpy->resources->connectors[i];
508 /* kconn->connector is allocated when the modes are asked */
511 kdpy->num_connectors = kdpy->resources->count_connectors;
514 connectors = MALLOC(kdpy->num_connectors * sizeof(*connectors));
516 for (i = 0; i < kdpy->num_connectors; i++)
517 connectors[i] = &kdpy->connectors[i].base;
519 *num_connectors = kdpy->num_connectors;
523 *num_crtc = kdpy->resources->count_crtcs;
528 static struct native_surface *
529 kms_display_create_scanout_surface(struct native_display *ndpy,
530 const struct native_config *nconf,
531 uint width, uint height)
533 struct kms_surface *ksurf;
535 ksurf = kms_display_create_surface(ndpy, nconf, width, height);
540 kms_display_is_format_supported(struct native_display *ndpy,
541 enum pipe_format fmt, boolean is_color)
543 return ndpy->screen->is_format_supported(ndpy->screen,
544 fmt, PIPE_TEXTURE_2D, 0,
545 (is_color) ? PIPE_BIND_RENDER_TARGET :
546 PIPE_BIND_DEPTH_STENCIL, 0);
549 static const struct native_config **
550 kms_display_get_configs(struct native_display *ndpy, int *num_configs)
552 struct kms_display *kdpy = kms_display(ndpy);
553 const struct native_config **configs;
557 struct native_config *nconf;
558 enum pipe_format format;
560 kdpy->config = CALLOC(1, sizeof(*kdpy->config));
564 nconf = &kdpy->config->base;
567 (1 << NATIVE_ATTACHMENT_FRONT_LEFT) |
568 (1 << NATIVE_ATTACHMENT_BACK_LEFT);
570 format = PIPE_FORMAT_B8G8R8A8_UNORM;
571 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
572 format = PIPE_FORMAT_A8R8G8B8_UNORM;
573 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
574 format = PIPE_FORMAT_NONE;
576 if (format == PIPE_FORMAT_NONE) {
582 nconf->color_format = format;
584 nconf->scanout_bit = TRUE;
587 configs = MALLOC(sizeof(*configs));
589 configs[0] = &kdpy->config->base;
598 kms_display_get_param(struct native_display *ndpy,
599 enum native_param_type param)
613 kms_display_destroy(struct native_display *ndpy)
615 struct kms_display *kdpy = kms_display(ndpy);
621 if (kdpy->connectors) {
622 for (i = 0; i < kdpy->num_connectors; i++) {
623 struct kms_connector *kconn = &kdpy->connectors[i];
624 if (kconn->connector) {
625 drmModeFreeConnector(kconn->connector);
626 FREE(kconn->kms_modes);
629 FREE(kdpy->connectors);
632 if (kdpy->shown_surfaces)
633 FREE(kdpy->shown_surfaces);
635 if (kdpy->saved_crtcs) {
636 for (i = 0; i < kdpy->resources->count_crtcs; i++) {
637 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
641 drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
642 kcrtc->crtc->buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
643 kcrtc->connectors, kcrtc->num_connectors,
646 drmModeFreeCrtc(kcrtc->crtc);
649 FREE(kdpy->saved_crtcs);
653 drmModeFreeResources(kdpy->resources);
655 if (kdpy->base.screen)
656 kdpy->base.screen->destroy(kdpy->base.screen);
665 * Initialize KMS and pipe screen.
668 kms_display_init_screen(struct native_display *ndpy)
670 struct kms_display *kdpy = kms_display(ndpy);
675 drmVersionPtr version = drmGetVersion(fd);
676 if (!version || strcmp(version->name, driver_descriptor.driver_name)) {
678 _eglLog(_EGL_WARNING, "unknown driver name %s", version->name);
679 drmFreeVersion(version);
682 _eglLog(_EGL_WARNING, "invalid fd %d", fd);
688 drmFreeVersion(version);
691 fd = drmOpen(driver_descriptor.driver_name, NULL);
695 _eglLog(_EGL_WARNING, "failed to open DRM device");
700 if (drmSetMaster(fd)) {
701 _eglLog(_EGL_WARNING, "failed to become DRM master");
706 kdpy->base.screen = driver_descriptor.create_screen(fd);
707 if (!kdpy->base.screen) {
708 _eglLog(_EGL_WARNING, "failed to create DRM screen");
718 static struct native_display_modeset kms_display_modeset = {
719 .get_connectors = kms_display_get_connectors,
720 .get_modes = kms_display_get_modes,
721 .create_scanout_surface = kms_display_create_scanout_surface,
722 .program = kms_display_program
725 static struct native_display *
726 kms_create_display(int fd, struct native_event_handler *event_handler)
728 struct kms_display *kdpy;
730 kdpy = CALLOC_STRUCT(kms_display);
734 kdpy->event_handler = event_handler;
736 if (!kms_display_init_screen(&kdpy->base)) {
737 kms_display_destroy(&kdpy->base);
741 /* resources are fixed, unlike crtc, connector, or encoder */
742 kdpy->resources = drmModeGetResources(kdpy->fd);
743 if (!kdpy->resources) {
744 kms_display_destroy(&kdpy->base);
749 CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
750 if (!kdpy->saved_crtcs) {
751 kms_display_destroy(&kdpy->base);
755 kdpy->shown_surfaces =
756 CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
757 if (!kdpy->shown_surfaces) {
758 kms_display_destroy(&kdpy->base);
762 kdpy->base.destroy = kms_display_destroy;
763 kdpy->base.get_param = kms_display_get_param;
764 kdpy->base.get_configs = kms_display_get_configs;
766 kdpy->base.modeset = &kms_display_modeset;
771 struct native_probe *
772 native_create_probe(EGLNativeDisplayType dpy)
777 enum native_probe_result
778 native_get_probe_result(struct native_probe *nprobe)
780 return NATIVE_PROBE_UNKNOWN;
784 native_get_name(void)
786 static char kms_name[32];
789 util_snprintf(kms_name, sizeof(kms_name), "KMS/%s", driver_descriptor.name);
794 struct native_display *
795 native_create_display(EGLNativeDisplayType dpy,
796 struct native_event_handler *event_handler)
798 struct native_display *ndpy = NULL;
801 fd = (dpy != EGL_DEFAULT_DISPLAY) ? (int) pointer_to_intptr((void *) dpy) : -1;
802 ndpy = kms_create_display(fd, event_handler);