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_string.h"
34 #include "native_kms.h"
37 kms_surface_validate(struct native_surface
*nsurf
, uint attachment_mask
,
38 unsigned int *seq_num
, struct pipe_resource
**textures
,
39 int *width
, int *height
)
41 struct kms_surface
*ksurf
= kms_surface(nsurf
);
42 struct kms_display
*kdpy
= ksurf
->kdpy
;
43 struct pipe_screen
*screen
= kdpy
->base
.screen
;
44 struct pipe_resource templ
, *ptex
;
47 if (attachment_mask
) {
48 memset(&templ
, 0, sizeof(templ
));
49 templ
.target
= PIPE_TEXTURE_2D
;
51 templ
.width0
= ksurf
->width
;
52 templ
.height0
= ksurf
->height
;
54 templ
.format
= ksurf
->color_format
;
55 templ
.bind
= PIPE_BIND_RENDER_TARGET
| PIPE_BIND_SCANOUT
;
59 for (att
= 0; att
< NUM_NATIVE_ATTACHMENTS
; att
++) {
60 /* delay the allocation */
61 if (!native_attachment_mask_test(attachment_mask
, att
))
64 ptex
= ksurf
->textures
[att
];
66 ptex
= screen
->resource_create(screen
, &templ
);
67 ksurf
->textures
[att
] = ptex
;
72 pipe_resource_reference(&textures
[att
], ptex
);
77 *seq_num
= ksurf
->sequence_number
;
79 *width
= ksurf
->width
;
81 *height
= ksurf
->height
;
87 * Add textures as DRM framebuffers.
90 kms_surface_init_framebuffers(struct native_surface
*nsurf
, boolean need_back
)
92 struct kms_surface
*ksurf
= kms_surface(nsurf
);
93 struct kms_display
*kdpy
= ksurf
->kdpy
;
94 int num_framebuffers
= (need_back
) ? 2 : 1;
97 for (i
= 0; i
< num_framebuffers
; i
++) {
98 struct kms_framebuffer
*fb
;
99 enum native_attachment natt
;
100 struct winsys_handle whandle
;
104 fb
= &ksurf
->front_fb
;
105 natt
= NATIVE_ATTACHMENT_FRONT_LEFT
;
108 fb
= &ksurf
->back_fb
;
109 natt
= NATIVE_ATTACHMENT_BACK_LEFT
;
113 /* make sure the texture has been allocated */
114 kms_surface_validate(&ksurf
->base
, 1 << natt
, NULL
, NULL
, NULL
, NULL
);
115 if (!ksurf
->textures
[natt
])
118 pipe_resource_reference(&fb
->texture
, ksurf
->textures
[natt
]);
121 /* already initialized */
125 /* TODO detect the real value */
126 fb
->is_passive
= TRUE
;
128 memset(&whandle
, 0, sizeof(whandle
));
129 whandle
.type
= DRM_API_HANDLE_TYPE_KMS
;
131 if (!kdpy
->base
.screen
->resource_get_handle(kdpy
->base
.screen
,
132 fb
->texture
, &whandle
))
135 block_bits
= util_format_get_blocksizebits(ksurf
->color_format
);
136 err
= drmModeAddFB(kdpy
->fd
, ksurf
->width
, ksurf
->height
,
137 block_bits
, block_bits
, whandle
.stride
, whandle
.handle
,
149 kms_surface_flush_frontbuffer(struct native_surface
*nsurf
)
151 #ifdef DRM_MODE_FEATURE_DIRTYFB
152 struct kms_surface
*ksurf
= kms_surface(nsurf
);
153 struct kms_display
*kdpy
= ksurf
->kdpy
;
155 if (ksurf
->front_fb
.is_passive
)
156 drmModeDirtyFB(kdpy
->fd
, ksurf
->front_fb
.buffer_id
, NULL
, 0);
163 kms_surface_swap_buffers(struct native_surface
*nsurf
)
165 struct kms_surface
*ksurf
= kms_surface(nsurf
);
166 struct kms_crtc
*kcrtc
= &ksurf
->current_crtc
;
167 struct kms_display
*kdpy
= ksurf
->kdpy
;
168 struct kms_framebuffer tmp_fb
;
169 struct pipe_resource
*tmp_texture
;
172 if (!ksurf
->back_fb
.buffer_id
) {
173 if (!kms_surface_init_framebuffers(&ksurf
->base
, TRUE
))
177 if (ksurf
->is_shown
&& kcrtc
->crtc
) {
178 err
= drmModeSetCrtc(kdpy
->fd
, kcrtc
->crtc
->crtc_id
,
179 ksurf
->back_fb
.buffer_id
, kcrtc
->crtc
->x
, kcrtc
->crtc
->y
,
180 kcrtc
->connectors
, kcrtc
->num_connectors
, &kcrtc
->crtc
->mode
);
185 /* swap the buffers */
186 tmp_fb
= ksurf
->front_fb
;
187 ksurf
->front_fb
= ksurf
->back_fb
;
188 ksurf
->back_fb
= tmp_fb
;
190 tmp_texture
= ksurf
->textures
[NATIVE_ATTACHMENT_FRONT_LEFT
];
191 ksurf
->textures
[NATIVE_ATTACHMENT_FRONT_LEFT
] =
192 ksurf
->textures
[NATIVE_ATTACHMENT_BACK_LEFT
];
193 ksurf
->textures
[NATIVE_ATTACHMENT_BACK_LEFT
] = tmp_texture
;
195 /* the front/back textures are swapped */
196 ksurf
->sequence_number
++;
197 kdpy
->event_handler
->invalid_surface(&kdpy
->base
,
198 &ksurf
->base
, ksurf
->sequence_number
);
204 kms_surface_wait(struct native_surface
*nsurf
)
210 kms_surface_destroy(struct native_surface
*nsurf
)
212 struct kms_surface
*ksurf
= kms_surface(nsurf
);
215 if (ksurf
->current_crtc
.crtc
)
216 drmModeFreeCrtc(ksurf
->current_crtc
.crtc
);
218 if (ksurf
->front_fb
.buffer_id
)
219 drmModeRmFB(ksurf
->kdpy
->fd
, ksurf
->front_fb
.buffer_id
);
220 pipe_resource_reference(&ksurf
->front_fb
.texture
, NULL
);
222 if (ksurf
->back_fb
.buffer_id
)
223 drmModeRmFB(ksurf
->kdpy
->fd
, ksurf
->back_fb
.buffer_id
);
224 pipe_resource_reference(&ksurf
->back_fb
.texture
, NULL
);
226 for (i
= 0; i
< NUM_NATIVE_ATTACHMENTS
; i
++) {
227 struct pipe_resource
*ptex
= ksurf
->textures
[i
];
228 pipe_resource_reference(&ptex
, NULL
);
234 static struct kms_surface
*
235 kms_display_create_surface(struct native_display
*ndpy
,
236 const struct native_config
*nconf
,
237 uint width
, uint height
)
239 struct kms_display
*kdpy
= kms_display(ndpy
);
240 struct kms_config
*kconf
= kms_config(nconf
);
241 struct kms_surface
*ksurf
;
243 ksurf
= CALLOC_STRUCT(kms_surface
);
248 ksurf
->color_format
= kconf
->base
.color_format
;
249 ksurf
->width
= width
;
250 ksurf
->height
= height
;
252 ksurf
->base
.destroy
= kms_surface_destroy
;
253 ksurf
->base
.swap_buffers
= kms_surface_swap_buffers
;
254 ksurf
->base
.flush_frontbuffer
= kms_surface_flush_frontbuffer
;
255 ksurf
->base
.validate
= kms_surface_validate
;
256 ksurf
->base
.wait
= kms_surface_wait
;
262 * Choose a CRTC that supports all given connectors.
265 kms_display_choose_crtc(struct native_display
*ndpy
,
266 uint32_t *connectors
, int num_connectors
)
268 struct kms_display
*kdpy
= kms_display(ndpy
);
271 for (idx
= 0; idx
< kdpy
->resources
->count_crtcs
; idx
++) {
272 boolean found_crtc
= TRUE
;
275 for (i
= 0; i
< num_connectors
; i
++) {
276 drmModeConnectorPtr connector
;
277 int encoder_idx
= -1;
279 connector
= drmModeGetConnector(kdpy
->fd
, connectors
[i
]);
285 /* find an encoder the CRTC supports */
286 for (j
= 0; j
< connector
->count_encoders
; j
++) {
287 drmModeEncoderPtr encoder
=
288 drmModeGetEncoder(kdpy
->fd
, connector
->encoders
[j
]);
289 if (encoder
->possible_crtcs
& (1 << idx
)) {
293 drmModeFreeEncoder(encoder
);
296 drmModeFreeConnector(connector
);
297 if (encoder_idx
< 0) {
307 if (idx
>= kdpy
->resources
->count_crtcs
) {
308 _eglLog(_EGL_WARNING
,
309 "failed to find a CRTC that supports the given %d connectors",
314 return kdpy
->resources
->crtcs
[idx
];
318 * Remember the original CRTC status and set the CRTC
321 kms_display_set_crtc(struct native_display
*ndpy
, int crtc_idx
,
322 uint32_t buffer_id
, uint32_t x
, uint32_t y
,
323 uint32_t *connectors
, int num_connectors
,
324 drmModeModeInfoPtr mode
)
326 struct kms_display
*kdpy
= kms_display(ndpy
);
327 struct kms_crtc
*kcrtc
= &kdpy
->saved_crtcs
[crtc_idx
];
332 crtc_id
= kcrtc
->crtc
->crtc_id
;
338 * Choose the CRTC once. It could be more dynamic, but let's keep it
341 crtc_id
= kms_display_choose_crtc(&kdpy
->base
,
342 connectors
, num_connectors
);
344 /* save the original CRTC status */
345 kcrtc
->crtc
= drmModeGetCrtc(kdpy
->fd
, crtc_id
);
349 for (i
= 0; i
< kdpy
->num_connectors
; i
++) {
350 struct kms_connector
*kconn
= &kdpy
->connectors
[i
];
351 drmModeConnectorPtr connector
= kconn
->connector
;
352 drmModeEncoderPtr encoder
;
354 encoder
= drmModeGetEncoder(kdpy
->fd
, connector
->encoder_id
);
356 if (encoder
->crtc_id
== crtc_id
) {
357 kcrtc
->connectors
[count
++] = connector
->connector_id
;
358 if (count
>= Elements(kcrtc
->connectors
))
361 drmModeFreeEncoder(encoder
);
365 kcrtc
->num_connectors
= count
;
368 err
= drmModeSetCrtc(kdpy
->fd
, crtc_id
, buffer_id
, x
, y
,
369 connectors
, num_connectors
, mode
);
371 drmModeFreeCrtc(kcrtc
->crtc
);
373 kcrtc
->num_connectors
= 0;
382 kms_display_program(struct native_display
*ndpy
, int crtc_idx
,
383 struct native_surface
*nsurf
, uint x
, uint y
,
384 const struct native_connector
**nconns
, int num_nconns
,
385 const struct native_mode
*nmode
)
387 struct kms_display
*kdpy
= kms_display(ndpy
);
388 struct kms_surface
*ksurf
= kms_surface(nsurf
);
389 const struct kms_mode
*kmode
= kms_mode(nmode
);
390 uint32_t connector_ids
[32];
392 drmModeModeInfo mode_tmp
, *mode
;
395 if (num_nconns
> Elements(connector_ids
)) {
396 _eglLog(_EGL_WARNING
, "too many connectors (%d)", num_nconns
);
397 num_nconns
= Elements(connector_ids
);
401 if (!kms_surface_init_framebuffers(&ksurf
->base
, FALSE
))
404 buffer_id
= ksurf
->front_fb
.buffer_id
;
405 /* the mode argument of drmModeSetCrtc is not constified */
406 mode_tmp
= kmode
->mode
;
410 /* disable the CRTC */
416 for (i
= 0; i
< num_nconns
; i
++) {
417 struct kms_connector
*kconn
= kms_connector(nconns
[i
]);
418 connector_ids
[i
] = kconn
->connector
->connector_id
;
421 if (!kms_display_set_crtc(&kdpy
->base
, crtc_idx
, buffer_id
, x
, y
,
422 connector_ids
, num_nconns
, mode
)) {
423 _eglLog(_EGL_WARNING
, "failed to set CRTC %d", crtc_idx
);
428 if (kdpy
->shown_surfaces
[crtc_idx
])
429 kdpy
->shown_surfaces
[crtc_idx
]->is_shown
= FALSE
;
430 kdpy
->shown_surfaces
[crtc_idx
] = ksurf
;
432 /* remember the settings for buffer swapping */
434 uint32_t crtc_id
= kdpy
->saved_crtcs
[crtc_idx
].crtc
->crtc_id
;
435 struct kms_crtc
*kcrtc
= &ksurf
->current_crtc
;
438 drmModeFreeCrtc(kcrtc
->crtc
);
439 kcrtc
->crtc
= drmModeGetCrtc(kdpy
->fd
, crtc_id
);
441 assert(num_nconns
< Elements(kcrtc
->connectors
));
442 memcpy(kcrtc
->connectors
, connector_ids
,
443 sizeof(*connector_ids
) * num_nconns
);
444 kcrtc
->num_connectors
= num_nconns
;
446 ksurf
->is_shown
= TRUE
;
452 static const struct native_mode
**
453 kms_display_get_modes(struct native_display
*ndpy
,
454 const struct native_connector
*nconn
,
457 struct kms_display
*kdpy
= kms_display(ndpy
);
458 struct kms_connector
*kconn
= kms_connector(nconn
);
459 const struct native_mode
**nmodes_return
;
462 /* delete old data */
463 if (kconn
->connector
) {
464 drmModeFreeConnector(kconn
->connector
);
465 FREE(kconn
->kms_modes
);
467 kconn
->connector
= NULL
;
468 kconn
->kms_modes
= NULL
;
469 kconn
->num_modes
= 0;
473 kconn
->connector
= drmModeGetConnector(kdpy
->fd
, kconn
->connector_id
);
474 if (!kconn
->connector
)
477 count
= kconn
->connector
->count_modes
;
478 kconn
->kms_modes
= CALLOC(count
, sizeof(*kconn
->kms_modes
));
479 if (!kconn
->kms_modes
) {
480 drmModeFreeConnector(kconn
->connector
);
481 kconn
->connector
= NULL
;
486 for (i
= 0; i
< count
; i
++) {
487 struct kms_mode
*kmode
= &kconn
->kms_modes
[i
];
488 drmModeModeInfoPtr mode
= &kconn
->connector
->modes
[i
];
492 kmode
->base
.desc
= kmode
->mode
.name
;
493 kmode
->base
.width
= kmode
->mode
.hdisplay
;
494 kmode
->base
.height
= kmode
->mode
.vdisplay
;
495 kmode
->base
.refresh_rate
= kmode
->mode
.vrefresh
;
496 /* not all kernels have vrefresh = refresh_rate * 1000 */
497 if (kmode
->base
.refresh_rate
> 1000)
498 kmode
->base
.refresh_rate
= (kmode
->base
.refresh_rate
+ 500) / 1000;
501 nmodes_return
= MALLOC(count
* sizeof(*nmodes_return
));
503 for (i
= 0; i
< count
; i
++)
504 nmodes_return
[i
] = &kconn
->kms_modes
[i
].base
;
509 return nmodes_return
;
512 static const struct native_connector
**
513 kms_display_get_connectors(struct native_display
*ndpy
, int *num_connectors
,
516 struct kms_display
*kdpy
= kms_display(ndpy
);
517 const struct native_connector
**connectors
;
520 if (!kdpy
->connectors
) {
522 CALLOC(kdpy
->resources
->count_connectors
, sizeof(*kdpy
->connectors
));
523 if (!kdpy
->connectors
)
526 for (i
= 0; i
< kdpy
->resources
->count_connectors
; i
++) {
527 struct kms_connector
*kconn
= &kdpy
->connectors
[i
];
529 kconn
->connector_id
= kdpy
->resources
->connectors
[i
];
530 /* kconn->connector is allocated when the modes are asked */
533 kdpy
->num_connectors
= kdpy
->resources
->count_connectors
;
536 connectors
= MALLOC(kdpy
->num_connectors
* sizeof(*connectors
));
538 for (i
= 0; i
< kdpy
->num_connectors
; i
++)
539 connectors
[i
] = &kdpy
->connectors
[i
].base
;
541 *num_connectors
= kdpy
->num_connectors
;
545 *num_crtc
= kdpy
->resources
->count_crtcs
;
550 static struct native_surface
*
551 kms_display_create_scanout_surface(struct native_display
*ndpy
,
552 const struct native_config
*nconf
,
553 uint width
, uint height
)
555 struct kms_surface
*ksurf
;
557 ksurf
= kms_display_create_surface(ndpy
, nconf
, width
, height
);
562 kms_display_is_format_supported(struct native_display
*ndpy
,
563 enum pipe_format fmt
, boolean is_color
)
565 return ndpy
->screen
->is_format_supported(ndpy
->screen
,
566 fmt
, PIPE_TEXTURE_2D
, 0,
567 (is_color
) ? PIPE_BIND_RENDER_TARGET
:
568 PIPE_BIND_DEPTH_STENCIL
, 0);
571 static const struct native_config
**
572 kms_display_get_configs(struct native_display
*ndpy
, int *num_configs
)
574 struct kms_display
*kdpy
= kms_display(ndpy
);
575 const struct native_config
**configs
;
579 struct native_config
*nconf
;
580 enum pipe_format format
;
582 kdpy
->config
= CALLOC(1, sizeof(*kdpy
->config
));
586 nconf
= &kdpy
->config
->base
;
589 (1 << NATIVE_ATTACHMENT_FRONT_LEFT
) |
590 (1 << NATIVE_ATTACHMENT_BACK_LEFT
);
592 format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
593 if (!kms_display_is_format_supported(&kdpy
->base
, format
, TRUE
)) {
594 format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
595 if (!kms_display_is_format_supported(&kdpy
->base
, format
, TRUE
))
596 format
= PIPE_FORMAT_NONE
;
598 if (format
== PIPE_FORMAT_NONE
) {
604 nconf
->color_format
= format
;
606 nconf
->scanout_bit
= TRUE
;
609 configs
= MALLOC(sizeof(*configs
));
611 configs
[0] = &kdpy
->config
->base
;
620 kms_display_get_param(struct native_display
*ndpy
,
621 enum native_param_type param
)
635 kms_display_destroy(struct native_display
*ndpy
)
637 struct kms_display
*kdpy
= kms_display(ndpy
);
643 if (kdpy
->connectors
) {
644 for (i
= 0; i
< kdpy
->num_connectors
; i
++) {
645 struct kms_connector
*kconn
= &kdpy
->connectors
[i
];
646 if (kconn
->connector
) {
647 drmModeFreeConnector(kconn
->connector
);
648 FREE(kconn
->kms_modes
);
651 FREE(kdpy
->connectors
);
654 if (kdpy
->shown_surfaces
)
655 FREE(kdpy
->shown_surfaces
);
657 if (kdpy
->saved_crtcs
) {
658 for (i
= 0; i
< kdpy
->resources
->count_crtcs
; i
++) {
659 struct kms_crtc
*kcrtc
= &kdpy
->saved_crtcs
[i
];
663 drmModeSetCrtc(kdpy
->fd
, kcrtc
->crtc
->crtc_id
,
664 kcrtc
->crtc
->buffer_id
, kcrtc
->crtc
->x
, kcrtc
->crtc
->y
,
665 kcrtc
->connectors
, kcrtc
->num_connectors
,
668 drmModeFreeCrtc(kcrtc
->crtc
);
671 FREE(kdpy
->saved_crtcs
);
675 drmModeFreeResources(kdpy
->resources
);
677 if (kdpy
->base
.screen
)
678 kdpy
->base
.screen
->destroy(kdpy
->base
.screen
);
683 if (kdpy
->api
&& kdpy
->api
->destroy
)
684 kdpy
->api
->destroy(kdpy
->api
);
689 * Initialize KMS and pipe screen.
692 kms_display_init_screen(struct native_display
*ndpy
)
694 struct kms_display
*kdpy
= kms_display(ndpy
);
697 fd
= drmOpen(kdpy
->api
->driver_name
, NULL
);
699 _eglLog(_EGL_WARNING
, "failed to open DRM device");
704 if (drmSetMaster(fd
)) {
705 _eglLog(_EGL_WARNING
, "failed to become DRM master");
710 kdpy
->base
.screen
= kdpy
->api
->create_screen(kdpy
->api
, fd
);
711 if (!kdpy
->base
.screen
) {
712 _eglLog(_EGL_WARNING
, "failed to create DRM screen");
722 static struct native_display_modeset kms_display_modeset
= {
723 .get_connectors
= kms_display_get_connectors
,
724 .get_modes
= kms_display_get_modes
,
725 .create_scanout_surface
= kms_display_create_scanout_surface
,
726 .program
= kms_display_program
729 static struct native_display
*
730 kms_create_display(EGLNativeDisplayType dpy
,
731 struct native_event_handler
*event_handler
,
734 struct kms_display
*kdpy
;
736 kdpy
= CALLOC_STRUCT(kms_display
);
740 kdpy
->event_handler
= event_handler
;
744 _eglLog(_EGL_WARNING
, "failed to create DRM API");
750 if (!kms_display_init_screen(&kdpy
->base
)) {
751 kms_display_destroy(&kdpy
->base
);
755 /* resources are fixed, unlike crtc, connector, or encoder */
756 kdpy
->resources
= drmModeGetResources(kdpy
->fd
);
757 if (!kdpy
->resources
) {
758 kms_display_destroy(&kdpy
->base
);
763 CALLOC(kdpy
->resources
->count_crtcs
, sizeof(*kdpy
->saved_crtcs
));
764 if (!kdpy
->saved_crtcs
) {
765 kms_display_destroy(&kdpy
->base
);
769 kdpy
->shown_surfaces
=
770 CALLOC(kdpy
->resources
->count_crtcs
, sizeof(*kdpy
->shown_surfaces
));
771 if (!kdpy
->shown_surfaces
) {
772 kms_display_destroy(&kdpy
->base
);
776 kdpy
->base
.destroy
= kms_display_destroy
;
777 kdpy
->base
.get_param
= kms_display_get_param
;
778 kdpy
->base
.get_configs
= kms_display_get_configs
;
780 kdpy
->base
.modeset
= &kms_display_modeset
;
785 struct native_probe
*
786 native_create_probe(EGLNativeDisplayType dpy
)
791 enum native_probe_result
792 native_get_probe_result(struct native_probe
*nprobe
)
794 return NATIVE_PROBE_UNKNOWN
;
797 /* the api is destroyed with the native display */
798 static struct drm_api
*drm_api
;
801 native_get_name(void)
803 static char kms_name
[32];
806 drm_api
= drm_api_create();
809 util_snprintf(kms_name
, sizeof(kms_name
), "KMS/%s", drm_api
->name
);
811 util_snprintf(kms_name
, sizeof(kms_name
), "KMS");
816 struct native_display
*
817 native_create_display(EGLNativeDisplayType dpy
,
818 struct native_event_handler
*event_handler
)
820 struct native_display
*ndpy
= NULL
;
823 drm_api
= drm_api_create();
826 ndpy
= kms_create_display(dpy
, event_handler
, drm_api
);