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.
29 #include "pipe/p_screen.h"
30 #include "pipe/p_context.h"
31 #include "util/u_debug.h"
32 #include "util/u_memory.h"
33 #include "util/u_inlines.h"
36 #include "native_kms.h"
39 kms_surface_validate(struct native_surface *nsurf, uint attachment_mask,
40 unsigned int *seq_num, struct pipe_texture **textures,
41 int *width, int *height)
43 struct kms_surface *ksurf = kms_surface(nsurf);
44 struct kms_display *kdpy = ksurf->kdpy;
45 struct pipe_screen *screen = kdpy->base.screen;
46 struct pipe_texture templ, *ptex;
49 if (attachment_mask) {
50 memset(&templ, 0, sizeof(templ));
51 templ.target = PIPE_TEXTURE_2D;
53 templ.width0 = ksurf->width;
54 templ.height0 = ksurf->height;
56 templ.format = ksurf->color_format;
58 PIPE_TEXTURE_USAGE_RENDER_TARGET | PIPE_TEXTURE_USAGE_SCANOUT;
62 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
63 /* delay the allocation */
64 if (!native_attachment_mask_test(attachment_mask, att))
67 ptex = ksurf->textures[att];
69 ptex = screen->texture_create(screen, &templ);
70 ksurf->textures[att] = ptex;
75 pipe_texture_reference(&textures[att], ptex);
80 *seq_num = ksurf->sequence_number;
82 *width = ksurf->width;
84 *height = ksurf->height;
90 * Add textures as DRM framebuffers.
93 kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back)
95 struct kms_surface *ksurf = kms_surface(nsurf);
96 struct kms_display *kdpy = ksurf->kdpy;
97 int num_framebuffers = (need_back) ? 2 : 1;
100 for (i = 0; i < num_framebuffers; i++) {
101 struct kms_framebuffer *fb;
102 enum native_attachment natt;
103 struct winsys_handle whandle;
107 fb = &ksurf->front_fb;
108 natt = NATIVE_ATTACHMENT_FRONT_LEFT;
111 fb = &ksurf->back_fb;
112 natt = NATIVE_ATTACHMENT_BACK_LEFT;
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])
121 pipe_texture_reference(&fb->texture, ksurf->textures[natt]);
124 /* already initialized */
128 /* TODO detect the real value */
129 fb->is_passive = TRUE;
131 memset(&whandle, 0, sizeof(whandle));
132 whandle.type = DRM_API_HANDLE_TYPE_KMS;
134 if (!kdpy->base.screen->texture_get_handle(kdpy->base.screen,
135 fb->texture, &whandle))
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,
152 kms_surface_flush_frontbuffer(struct native_surface *nsurf)
154 #ifdef DRM_MODE_FEATURE_DIRTYFB
155 struct kms_surface *ksurf = kms_surface(nsurf);
156 struct kms_display *kdpy = ksurf->kdpy;
158 if (ksurf->front_fb.is_passive)
159 drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0);
166 kms_surface_swap_buffers(struct native_surface *nsurf)
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;
175 if (!ksurf->back_fb.buffer_id) {
176 if (!kms_surface_init_framebuffers(&ksurf->base, TRUE))
180 if (ksurf->is_shown && kcrtc->crtc) {
181 err = drmModeSetCrtc(kdpy->fd, kcrtc->crtc->crtc_id,
182 ksurf->back_fb.buffer_id, kcrtc->crtc->x, kcrtc->crtc->y,
183 kcrtc->connectors, kcrtc->num_connectors, &kcrtc->crtc->mode);
188 /* swap the buffers */
189 tmp_fb = ksurf->front_fb;
190 ksurf->front_fb = ksurf->back_fb;
191 ksurf->back_fb = tmp_fb;
193 tmp_texture = ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT];
194 ksurf->textures[NATIVE_ATTACHMENT_FRONT_LEFT] =
195 ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT];
196 ksurf->textures[NATIVE_ATTACHMENT_BACK_LEFT] = tmp_texture;
198 /* the front/back textures are swapped */
199 ksurf->sequence_number++;
200 kdpy->event_handler->invalid_surface(&kdpy->base,
201 &ksurf->base, ksurf->sequence_number);
207 kms_surface_wait(struct native_surface *nsurf)
213 kms_surface_destroy(struct native_surface *nsurf)
215 struct kms_surface *ksurf = kms_surface(nsurf);
218 if (ksurf->current_crtc.crtc)
219 drmModeFreeCrtc(ksurf->current_crtc.crtc);
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);
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);
229 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
230 struct pipe_texture *ptex = ksurf->textures[i];
231 pipe_texture_reference(&ptex, NULL);
237 static struct kms_surface *
238 kms_display_create_surface(struct native_display *ndpy,
239 const struct native_config *nconf,
240 uint width, uint height)
242 struct kms_display *kdpy = kms_display(ndpy);
243 struct kms_config *kconf = kms_config(nconf);
244 struct kms_surface *ksurf;
246 ksurf = CALLOC_STRUCT(kms_surface);
251 ksurf->color_format = kconf->base.color_format;
252 ksurf->width = width;
253 ksurf->height = height;
255 ksurf->base.destroy = kms_surface_destroy;
256 ksurf->base.swap_buffers = kms_surface_swap_buffers;
257 ksurf->base.flush_frontbuffer = kms_surface_flush_frontbuffer;
258 ksurf->base.validate = kms_surface_validate;
259 ksurf->base.wait = kms_surface_wait;
265 * Choose a CRTC that supports all given connectors.
268 kms_display_choose_crtc(struct native_display *ndpy,
269 uint32_t *connectors, int num_connectors)
271 struct kms_display *kdpy = kms_display(ndpy);
274 for (idx = 0; idx < kdpy->resources->count_crtcs; idx++) {
275 boolean found_crtc = TRUE;
278 for (i = 0; i < num_connectors; i++) {
279 drmModeConnectorPtr connector;
280 int encoder_idx = -1;
282 connector = drmModeGetConnector(kdpy->fd, connectors[i]);
288 /* find an encoder the CRTC supports */
289 for (j = 0; j < connector->count_encoders; j++) {
290 drmModeEncoderPtr encoder =
291 drmModeGetEncoder(kdpy->fd, connector->encoders[j]);
292 if (encoder->possible_crtcs & (1 << idx)) {
296 drmModeFreeEncoder(encoder);
299 drmModeFreeConnector(connector);
300 if (encoder_idx < 0) {
310 if (idx >= kdpy->resources->count_crtcs) {
311 _eglLog(_EGL_WARNING,
312 "failed to find a CRTC that supports the given %d connectors",
317 return kdpy->resources->crtcs[idx];
321 * Remember the original CRTC status and set the CRTC
324 kms_display_set_crtc(struct native_display *ndpy, int crtc_idx,
325 uint32_t buffer_id, uint32_t x, uint32_t y,
326 uint32_t *connectors, int num_connectors,
327 drmModeModeInfoPtr mode)
329 struct kms_display *kdpy = kms_display(ndpy);
330 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[crtc_idx];
335 crtc_id = kcrtc->crtc->crtc_id;
341 * Choose the CRTC once. It could be more dynamic, but let's keep it
344 crtc_id = kms_display_choose_crtc(&kdpy->base,
345 connectors, num_connectors);
347 /* save the original CRTC status */
348 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
352 for (i = 0; i < kdpy->num_connectors; i++) {
353 struct kms_connector *kconn = &kdpy->connectors[i];
354 drmModeConnectorPtr connector = kconn->connector;
355 drmModeEncoderPtr encoder;
357 encoder = drmModeGetEncoder(kdpy->fd, connector->encoder_id);
359 if (encoder->crtc_id == crtc_id) {
360 kcrtc->connectors[count++] = connector->connector_id;
361 if (count >= Elements(kcrtc->connectors))
364 drmModeFreeEncoder(encoder);
368 kcrtc->num_connectors = count;
371 err = drmModeSetCrtc(kdpy->fd, crtc_id, buffer_id, x, y,
372 connectors, num_connectors, mode);
374 drmModeFreeCrtc(kcrtc->crtc);
376 kcrtc->num_connectors = 0;
385 kms_display_program(struct native_display *ndpy, int crtc_idx,
386 struct native_surface *nsurf, uint x, uint y,
387 const struct native_connector **nconns, int num_nconns,
388 const struct native_mode *nmode)
390 struct kms_display *kdpy = kms_display(ndpy);
391 struct kms_surface *ksurf = kms_surface(nsurf);
392 const struct kms_mode *kmode = kms_mode(nmode);
393 uint32_t connector_ids[32];
395 drmModeModeInfo mode_tmp, *mode;
398 if (num_nconns > Elements(connector_ids)) {
399 _eglLog(_EGL_WARNING, "too many connectors (%d)", num_nconns);
400 num_nconns = Elements(connector_ids);
404 if (!kms_surface_init_framebuffers(&ksurf->base, FALSE))
407 buffer_id = ksurf->front_fb.buffer_id;
408 /* the mode argument of drmModeSetCrtc is not constified */
409 mode_tmp = kmode->mode;
413 /* disable the CRTC */
419 for (i = 0; i < num_nconns; i++) {
420 struct kms_connector *kconn = kms_connector(nconns[i]);
421 connector_ids[i] = kconn->connector->connector_id;
424 if (!kms_display_set_crtc(&kdpy->base, crtc_idx, buffer_id, x, y,
425 connector_ids, num_nconns, mode)) {
426 _eglLog(_EGL_WARNING, "failed to set CRTC %d", crtc_idx);
431 if (kdpy->shown_surfaces[crtc_idx])
432 kdpy->shown_surfaces[crtc_idx]->is_shown = FALSE;
433 kdpy->shown_surfaces[crtc_idx] = ksurf;
435 /* remember the settings for buffer swapping */
437 uint32_t crtc_id = kdpy->saved_crtcs[crtc_idx].crtc->crtc_id;
438 struct kms_crtc *kcrtc = &ksurf->current_crtc;
441 drmModeFreeCrtc(kcrtc->crtc);
442 kcrtc->crtc = drmModeGetCrtc(kdpy->fd, crtc_id);
444 assert(num_nconns < Elements(kcrtc->connectors));
445 memcpy(kcrtc->connectors, connector_ids,
446 sizeof(*connector_ids) * num_nconns);
447 kcrtc->num_connectors = num_nconns;
449 ksurf->is_shown = TRUE;
455 static const struct native_mode **
456 kms_display_get_modes(struct native_display *ndpy,
457 const struct native_connector *nconn,
460 struct kms_display *kdpy = kms_display(ndpy);
461 struct kms_connector *kconn = kms_connector(nconn);
462 const struct native_mode **nmodes_return;
465 /* delete old data */
466 if (kconn->connector) {
467 drmModeFreeConnector(kconn->connector);
468 free(kconn->kms_modes);
470 kconn->connector = NULL;
471 kconn->kms_modes = NULL;
472 kconn->num_modes = 0;
476 kconn->connector = drmModeGetConnector(kdpy->fd, kconn->connector_id);
477 if (!kconn->connector)
480 count = kconn->connector->count_modes;
481 kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes));
482 if (!kconn->kms_modes) {
483 drmModeFreeConnector(kconn->connector);
484 kconn->connector = NULL;
489 for (i = 0; i < count; i++) {
490 struct kms_mode *kmode = &kconn->kms_modes[i];
491 drmModeModeInfoPtr mode = &kconn->connector->modes[i];
495 kmode->base.desc = kmode->mode.name;
496 kmode->base.width = kmode->mode.hdisplay;
497 kmode->base.height = kmode->mode.vdisplay;
498 kmode->base.refresh_rate = kmode->mode.vrefresh;
499 /* not all kernels have vrefresh = refresh_rate * 1000 */
500 if (kmode->base.refresh_rate > 1000)
501 kmode->base.refresh_rate = (kmode->base.refresh_rate + 500) / 1000;
504 nmodes_return = malloc(count * sizeof(*nmodes_return));
506 for (i = 0; i < count; i++)
507 nmodes_return[i] = &kconn->kms_modes[i].base;
512 return nmodes_return;
515 static const struct native_connector **
516 kms_display_get_connectors(struct native_display *ndpy, int *num_connectors,
519 struct kms_display *kdpy = kms_display(ndpy);
520 const struct native_connector **connectors;
523 if (!kdpy->connectors) {
525 calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors));
526 if (!kdpy->connectors)
529 for (i = 0; i < kdpy->resources->count_connectors; i++) {
530 struct kms_connector *kconn = &kdpy->connectors[i];
532 kconn->connector_id = kdpy->resources->connectors[i];
533 /* kconn->connector is allocated when the modes are asked */
536 kdpy->num_connectors = kdpy->resources->count_connectors;
539 connectors = malloc(kdpy->num_connectors * sizeof(*connectors));
541 for (i = 0; i < kdpy->num_connectors; i++)
542 connectors[i] = &kdpy->connectors[i].base;
544 *num_connectors = kdpy->num_connectors;
548 *num_crtc = kdpy->resources->count_crtcs;
553 static struct native_surface *
554 kms_display_create_scanout_surface(struct native_display *ndpy,
555 const struct native_config *nconf,
556 uint width, uint height)
558 struct kms_surface *ksurf;
560 ksurf = kms_display_create_surface(ndpy, nconf, width, height);
565 kms_display_is_format_supported(struct native_display *ndpy,
566 enum pipe_format fmt, boolean is_color)
568 return ndpy->screen->is_format_supported(ndpy->screen,
569 fmt, PIPE_TEXTURE_2D,
570 (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET :
571 PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0);
574 static const struct native_config **
575 kms_display_get_configs(struct native_display *ndpy, int *num_configs)
577 struct kms_display *kdpy = kms_display(ndpy);
578 const struct native_config **configs;
582 struct native_config *nconf;
583 enum pipe_format format;
585 kdpy->config = calloc(1, sizeof(*kdpy->config));
589 nconf = &kdpy->config->base;
591 /* always double-buffered */
592 nconf->mode.doubleBufferMode = TRUE;
594 format = PIPE_FORMAT_B8G8R8A8_UNORM;
595 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) {
596 format = PIPE_FORMAT_A8R8G8B8_UNORM;
597 if (!kms_display_is_format_supported(&kdpy->base, format, TRUE))
598 format = PIPE_FORMAT_NONE;
600 if (format == PIPE_FORMAT_NONE)
603 nconf->color_format = format;
604 nconf->mode.redBits = 8;
605 nconf->mode.greenBits = 8;
606 nconf->mode.blueBits = 8;
607 nconf->mode.alphaBits = 8;
608 nconf->mode.rgbBits = 32;
610 format = PIPE_FORMAT_Z24_UNORM_S8_USCALED;
611 if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) {
612 format = PIPE_FORMAT_S8_USCALED_Z24_UNORM;
613 if (!kms_display_is_format_supported(&kdpy->base, format, FALSE))
614 format = PIPE_FORMAT_NONE;
616 if (format != PIPE_FORMAT_NONE) {
617 nconf->depth_format = format;
618 nconf->stencil_format = format;
620 nconf->mode.depthBits = 24;
621 nconf->mode.stencilBits = 8;
622 nconf->mode.haveDepthBuffer = TRUE;
623 nconf->mode.haveStencilBuffer = TRUE;
626 nconf->scanout_bit = TRUE;
627 nconf->mode.drawableType = GLX_PBUFFER_BIT;
628 nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML;
630 nconf->mode.visualID = 0;
631 nconf->mode.visualType = EGL_NONE;
633 nconf->mode.renderType = GLX_RGBA_BIT;
634 nconf->mode.rgbMode = TRUE;
635 nconf->mode.xRenderable = FALSE;
638 configs = malloc(sizeof(*configs));
640 configs[0] = &kdpy->config->base;
649 kms_display_get_param(struct native_display *ndpy,
650 enum native_param_type param)
664 kms_display_destroy(struct native_display *ndpy)
666 struct kms_display *kdpy = kms_display(ndpy);
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);
680 free(kdpy->connectors);
683 if (kdpy->shown_surfaces)
684 free(kdpy->shown_surfaces);
686 if (kdpy->saved_crtcs) {
687 for (i = 0; i < kdpy->resources->count_crtcs; i++) {
688 struct kms_crtc *kcrtc = &kdpy->saved_crtcs[i];
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,
697 drmModeFreeCrtc(kcrtc->crtc);
700 free(kdpy->saved_crtcs);
704 drmModeFreeResources(kdpy->resources);
706 if (kdpy->base.screen)
707 kdpy->base.screen->destroy(kdpy->base.screen);
713 kdpy->api->destroy(kdpy->api);
718 * Initialize KMS and pipe screen.
721 kms_display_init_screen(struct native_display *ndpy)
723 struct kms_display *kdpy = kms_display(ndpy);
724 struct drm_create_screen_arg arg;
727 fd = drmOpen(kdpy->api->name, NULL);
729 _eglLog(_EGL_WARNING, "failed to open DRM device");
734 if (drmSetMaster(fd)) {
735 _eglLog(_EGL_WARNING, "failed to become DRM master");
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");
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
761 static struct native_display *
762 kms_create_display(EGLNativeDisplayType dpy,
763 struct native_event_handler *event_handler,
766 struct kms_display *kdpy;
768 kdpy = CALLOC_STRUCT(kms_display);
772 kdpy->event_handler = event_handler;
776 _eglLog(_EGL_WARNING, "failed to create DRM API");
782 if (!kms_display_init_screen(&kdpy->base)) {
783 kms_display_destroy(&kdpy->base);
787 /* resources are fixed, unlike crtc, connector, or encoder */
788 kdpy->resources = drmModeGetResources(kdpy->fd);
789 if (!kdpy->resources) {
790 kms_display_destroy(&kdpy->base);
795 calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs));
796 if (!kdpy->saved_crtcs) {
797 kms_display_destroy(&kdpy->base);
801 kdpy->shown_surfaces =
802 calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces));
803 if (!kdpy->shown_surfaces) {
804 kms_display_destroy(&kdpy->base);
808 kdpy->base.destroy = kms_display_destroy;
809 kdpy->base.get_param = kms_display_get_param;
810 kdpy->base.get_configs = kms_display_get_configs;
812 kdpy->base.modeset = &kms_display_modeset;
817 struct native_probe *
818 native_create_probe(EGLNativeDisplayType dpy)
823 enum native_probe_result
824 native_get_probe_result(struct native_probe *nprobe)
826 return NATIVE_PROBE_UNKNOWN;
829 /* the api is destroyed with the native display */
830 static struct drm_api *drm_api;
833 native_get_name(void)
835 static char kms_name[32];
838 drm_api = drm_api_create();
841 snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name);
843 snprintf(kms_name, sizeof(kms_name), "KMS");
848 struct native_display *
849 native_create_display(EGLNativeDisplayType dpy,
850 struct native_event_handler *event_handler)
852 struct native_display *ndpy = NULL;
855 drm_api = drm_api_create();
858 ndpy = kms_create_display(dpy, event_handler, drm_api);