platform_wayland.c revision 2225397d1cf5e4f4a1293495f3a26bd33e5d7ac3
1/* 2 * Copyright © 2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Kristian Høgsberg <krh@bitplanet.net> 26 * Benjamin Franzke <benjaminfranzke@googlemail.com> 27 */ 28 29#include <stdlib.h> 30#include <string.h> 31#include <limits.h> 32#include <dlfcn.h> 33#include <errno.h> 34#include <unistd.h> 35#include <fcntl.h> 36#include <xf86drm.h> 37 38#include "egl_dri2.h" 39 40#include <wayland-client.h> 41#include "wayland-drm-client-protocol.h" 42 43static void 44sync_callback(void *data) 45{ 46 int *done = data; 47 48 *done = 1; 49} 50 51static void 52force_roundtrip(struct wl_display *display) 53{ 54 int done = 0; 55 56 wl_display_sync_callback(display, sync_callback, &done); 57 wl_display_iterate(display, WL_DISPLAY_WRITABLE); 58 while (!done) 59 wl_display_iterate(display, WL_DISPLAY_READABLE); 60} 61 62 63/** 64 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 65 */ 66static _EGLSurface * 67dri2_create_surface(_EGLDriver *drv, _EGLDisplay *disp, EGLint type, 68 _EGLConfig *conf, EGLNativeWindowType window, 69 const EGLint *attrib_list) 70{ 71 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 72 struct dri2_egl_config *dri2_conf = dri2_egl_config(conf); 73 struct dri2_egl_surface *dri2_surf; 74 struct dri2_egl_buffer *dri2_buf; 75 int i; 76 77 (void) drv; 78 79 dri2_surf = malloc(sizeof *dri2_surf); 80 if (!dri2_surf) { 81 _eglError(EGL_BAD_ALLOC, "dri2_create_surface"); 82 return NULL; 83 } 84 85 if (!_eglInitSurface(&dri2_surf->base, disp, type, conf, attrib_list)) 86 goto cleanup_surf; 87 88 for (i = 0; i < WL_BUFFER_COUNT; ++i) 89 dri2_surf->wl_drm_buffer[i] = NULL; 90 91 for (i = 0; i < __DRI_BUFFER_COUNT; ++i) 92 dri2_surf->dri_buffers[i] = NULL; 93 94 dri2_surf->pending_buffer = NULL; 95 dri2_surf->block_swap_buffers = EGL_FALSE; 96 97 switch (type) { 98 case EGL_WINDOW_BIT: 99 dri2_surf->wl_win = (struct wl_egl_window *) window; 100 dri2_surf->type = DRI2_WINDOW_SURFACE; 101 102 dri2_surf->base.Width = -1; 103 dri2_surf->base.Height = -1; 104 break; 105 case EGL_PIXMAP_BIT: 106 dri2_surf->wl_pix = (struct wl_egl_pixmap *) window; 107 dri2_surf->type = DRI2_PIXMAP_SURFACE; 108 109 dri2_surf->base.Width = dri2_surf->wl_pix->width; 110 dri2_surf->base.Height = dri2_surf->wl_pix->height; 111 112 if (dri2_surf->wl_pix->driver_private) { 113 dri2_buf = dri2_surf->wl_pix->driver_private; 114 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = dri2_buf->dri_buffer; 115 } 116 break; 117 default: 118 goto cleanup_surf; 119 } 120 121 dri2_surf->dri_drawable = 122 (*dri2_dpy->dri2->createNewDrawable) (dri2_dpy->dri_screen, 123 type == EGL_WINDOW_BIT ? 124 dri2_conf->dri_double_config : 125 dri2_conf->dri_single_config, 126 dri2_surf); 127 if (dri2_surf->dri_drawable == NULL) { 128 _eglError(EGL_BAD_ALLOC, "dri2->createNewDrawable"); 129 goto cleanup_dri_drawable; 130 } 131 132 return &dri2_surf->base; 133 134 cleanup_dri_drawable: 135 dri2_dpy->core->destroyDrawable(dri2_surf->dri_drawable); 136 cleanup_surf: 137 free(dri2_surf); 138 139 return NULL; 140} 141 142/** 143 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). 144 */ 145static _EGLSurface * 146dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *disp, 147 _EGLConfig *conf, EGLNativeWindowType window, 148 const EGLint *attrib_list) 149{ 150 return dri2_create_surface(drv, disp, EGL_WINDOW_BIT, conf, 151 window, attrib_list); 152} 153 154static _EGLSurface * 155dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *disp, 156 _EGLConfig *conf, EGLNativePixmapType pixmap, 157 const EGLint *attrib_list) 158{ 159 return dri2_create_surface(drv, disp, EGL_PIXMAP_BIT, conf, 160 pixmap, attrib_list); 161} 162 163/** 164 * Called via eglDestroySurface(), drv->API.DestroySurface(). 165 */ 166static EGLBoolean 167dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) 168{ 169 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 170 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 171 int i; 172 173 (void) drv; 174 175 if (!_eglPutSurface(surf)) 176 return EGL_TRUE; 177 178 (*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable); 179 180 for (i = 0; i < WL_BUFFER_COUNT; ++i) 181 if (dri2_surf->wl_drm_buffer[i]) 182 wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]); 183 184 for (i = 0; i < __DRI_BUFFER_COUNT; ++i) 185 if (dri2_surf->dri_buffers[i] && !(i == __DRI_BUFFER_FRONT_LEFT && 186 dri2_surf->type == DRI2_PIXMAP_SURFACE)) 187 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 188 dri2_surf->dri_buffers[i]); 189 190 free(surf); 191 192 return EGL_TRUE; 193} 194 195static void 196dri2_wl_egl_pixmap_destroy(struct wl_egl_pixmap *egl_pixmap) 197{ 198 struct dri2_egl_buffer *dri2_buf = egl_pixmap->driver_private; 199 200 assert(dri2_buf); 201 202 dri2_buf->dri2_dpy->dri2->releaseBuffer(dri2_buf->dri2_dpy->dri_screen, 203 dri2_buf->dri_buffer); 204 205 free(dri2_buf); 206 207 egl_pixmap->driver_private = NULL; 208 egl_pixmap->destroy = NULL; 209} 210 211static void 212dri2_process_back_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) 213{ 214 struct dri2_egl_display *dri2_dpy = 215 dri2_egl_display(dri2_surf->base.Resource.Display); 216 217 (void) format; 218 219 switch (dri2_surf->type) { 220 case DRI2_WINDOW_SURFACE: 221 /* allocate a front buffer for our double-buffered window*/ 222 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT] = 223 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, 224 __DRI_BUFFER_FRONT_LEFT, format, 225 dri2_surf->base.Width, dri2_surf->base.Height); 226 break; 227 default: 228 break; 229 } 230} 231 232static void 233dri2_process_front_buffer(struct dri2_egl_surface *dri2_surf, unsigned format) 234{ 235 struct dri2_egl_display *dri2_dpy = 236 dri2_egl_display(dri2_surf->base.Resource.Display); 237 struct dri2_egl_buffer *dri2_buf; 238 239 switch (dri2_surf->type) { 240 case DRI2_PIXMAP_SURFACE: 241 dri2_buf = malloc(sizeof *dri2_buf); 242 if (!dri2_buf) 243 return; 244 245 dri2_buf->dri_buffer = dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]; 246 dri2_buf->dri2_dpy = dri2_dpy; 247 248 dri2_surf->wl_pix->driver_private = dri2_buf; 249 dri2_surf->wl_pix->destroy = dri2_wl_egl_pixmap_destroy; 250 break; 251 default: 252 break; 253 } 254} 255 256static void 257dri2_release_pending_buffer(void *data) 258{ 259 struct dri2_egl_surface *dri2_surf = data; 260 struct dri2_egl_display *dri2_dpy = 261 dri2_egl_display(dri2_surf->base.Resource.Display); 262 263 /* FIXME: print internal error */ 264 if (!dri2_surf->pending_buffer) 265 return; 266 267 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 268 dri2_surf->pending_buffer); 269 dri2_surf->pending_buffer = NULL; 270} 271 272static void 273dri2_release_buffers(struct dri2_egl_surface *dri2_surf) 274{ 275 struct dri2_egl_display *dri2_dpy = 276 dri2_egl_display(dri2_surf->base.Resource.Display); 277 int i; 278 279 for (i = 0; i < __DRI_BUFFER_COUNT; ++i) { 280 if (dri2_surf->dri_buffers[i]) { 281 switch (i) { 282 case __DRI_BUFFER_FRONT_LEFT: 283 if (dri2_surf->pending_buffer) 284 force_roundtrip(dri2_dpy->wl_dpy); 285 dri2_surf->pending_buffer = dri2_surf->dri_buffers[i]; 286 wl_display_sync_callback(dri2_dpy->wl_dpy, 287 dri2_release_pending_buffer, dri2_surf); 288 break; 289 default: 290 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 291 dri2_surf->dri_buffers[i]); 292 break; 293 } 294 dri2_surf->dri_buffers[i] = NULL; 295 } 296 } 297} 298 299static __DRIbuffer * 300dri2_get_buffers_with_format(__DRIdrawable * driDrawable, 301 int *width, int *height, 302 unsigned int *attachments, int count, 303 int *out_count, void *loaderPrivate) 304{ 305 struct dri2_egl_surface *dri2_surf = loaderPrivate; 306 struct dri2_egl_display *dri2_dpy = 307 dri2_egl_display(dri2_surf->base.Resource.Display); 308 int i; 309 310 if (dri2_surf->type == DRI2_WINDOW_SURFACE && 311 (dri2_surf->base.Width != dri2_surf->wl_win->width || 312 dri2_surf->base.Height != dri2_surf->wl_win->height)) { 313 314 dri2_release_buffers(dri2_surf); 315 316 dri2_surf->base.Width = dri2_surf->wl_win->width; 317 dri2_surf->base.Height = dri2_surf->wl_win->height; 318 dri2_surf->dx = dri2_surf->wl_win->dx; 319 dri2_surf->dy = dri2_surf->wl_win->dy; 320 321 for (i = 0; i < WL_BUFFER_COUNT; ++i) { 322 if (dri2_surf->wl_drm_buffer[i]) 323 wl_buffer_destroy(dri2_surf->wl_drm_buffer[i]); 324 dri2_surf->wl_drm_buffer[i] = NULL; 325 } 326 } 327 328 dri2_surf->buffer_count = 0; 329 for (i = 0; i < 2*count; i+=2) { 330 assert(attachments[i] < __DRI_BUFFER_COUNT); 331 assert(dri2_surf->buffer_count < 5); 332 333 if (dri2_surf->dri_buffers[attachments[i]] == NULL) { 334 335 dri2_surf->dri_buffers[attachments[i]] = 336 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, 337 attachments[i], attachments[i+1], 338 dri2_surf->base.Width, dri2_surf->base.Height); 339 340 if (!dri2_surf->dri_buffers[attachments[i]]) 341 continue; 342 343 if (attachments[i] == __DRI_BUFFER_FRONT_LEFT) 344 dri2_process_front_buffer(dri2_surf, attachments[i+1]); 345 else if (attachments[i] == __DRI_BUFFER_BACK_LEFT) 346 dri2_process_back_buffer(dri2_surf, attachments[i+1]); 347 } 348 349 memcpy(&dri2_surf->buffers[dri2_surf->buffer_count], 350 dri2_surf->dri_buffers[attachments[i]], 351 sizeof(__DRIbuffer)); 352 353 dri2_surf->buffer_count++; 354 } 355 356 assert(dri2_surf->type == DRI2_PIXMAP_SURFACE || 357 dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); 358 359 *out_count = dri2_surf->buffer_count; 360 if (dri2_surf->buffer_count == 0) 361 return NULL; 362 363 *width = dri2_surf->base.Width; 364 *height = dri2_surf->base.Height; 365 366 return dri2_surf->buffers; 367} 368 369static __DRIbuffer * 370dri2_get_buffers(__DRIdrawable * driDrawable, 371 int *width, int *height, 372 unsigned int *attachments, int count, 373 int *out_count, void *loaderPrivate) 374{ 375 unsigned int *attachments_with_format; 376 __DRIbuffer *buffer; 377 const unsigned int format = 32; 378 int i; 379 380 attachments_with_format = calloc(count * 2, sizeof(unsigned int)); 381 if (!attachments_with_format) { 382 *out_count = 0; 383 return NULL; 384 } 385 386 for (i = 0; i < count; ++i) { 387 attachments_with_format[2*i] = attachments[i]; 388 attachments_with_format[2*i + 1] = format; 389 } 390 391 buffer = 392 dri2_get_buffers_with_format(driDrawable, 393 width, height, 394 attachments_with_format, count, 395 out_count, loaderPrivate); 396 397 free(attachments_with_format); 398 399 return buffer; 400} 401 402 403static void 404dri2_flush_front_buffer(__DRIdrawable * driDrawable, void *loaderPrivate) 405{ 406 (void) driDrawable; 407 408 /* FIXME: Does EGL support front buffer rendering at all? */ 409 410#if 0 411 struct dri2_egl_surface *dri2_surf = loaderPrivate; 412 413 dri2WaitGL(dri2_surf); 414#else 415 (void) loaderPrivate; 416#endif 417} 418 419static struct wl_buffer * 420wayland_create_buffer(struct dri2_egl_surface *dri2_surf, __DRIbuffer *buffer) 421{ 422 struct dri2_egl_display *dri2_dpy = 423 dri2_egl_display(dri2_surf->base.Resource.Display); 424 425 return wl_drm_create_buffer(dri2_dpy->wl_drm, buffer->name, 426 dri2_surf->base.Width, dri2_surf->base.Height, 427 buffer->pitch, dri2_surf->wl_win->visual); 428} 429 430static void 431wayland_frame_callback(struct wl_surface *surface, void *data, uint32_t time) 432{ 433 struct dri2_egl_surface *dri2_surf = data; 434 435 dri2_surf->block_swap_buffers = EGL_FALSE; 436} 437 438static inline void 439pointer_swap(const void **p1, const void **p2) 440{ 441 const void *tmp = *p1; 442 *p1 = *p2; 443 *p2 = tmp; 444} 445 446/** 447 * Called via eglSwapBuffers(), drv->API.SwapBuffers(). 448 */ 449static EGLBoolean 450dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) 451{ 452 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 453 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw); 454 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 455 456 while (dri2_surf->block_swap_buffers) 457 wl_display_iterate(dri2_dpy->wl_dpy, WL_DISPLAY_READABLE); 458 459 dri2_surf->block_swap_buffers = EGL_TRUE; 460 wl_display_frame_callback(dri2_dpy->wl_dpy, 461 dri2_surf->wl_win->surface, 462 wayland_frame_callback, dri2_surf); 463 464 if (dri2_surf->type == DRI2_WINDOW_SURFACE) { 465 pointer_swap( 466 (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT], 467 (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]); 468 469 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment = 470 __DRI_BUFFER_FRONT_LEFT; 471 dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment = 472 __DRI_BUFFER_BACK_LEFT; 473 474 pointer_swap((const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], 475 (const void **) &dri2_surf->wl_drm_buffer[WL_BUFFER_BACK]); 476 477 if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT]) 478 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] = 479 wayland_create_buffer(dri2_surf, 480 dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]); 481 482 wl_surface_attach(dri2_surf->wl_win->surface, 483 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], 484 dri2_surf->dx, dri2_surf->dy); 485 486 dri2_surf->wl_win->attached_width = dri2_surf->base.Width; 487 dri2_surf->wl_win->attached_height = dri2_surf->base.Height; 488 /* reset resize growing parameters */ 489 dri2_surf->dx = 0; 490 dri2_surf->dy = 0; 491 492 wl_surface_damage(dri2_surf->wl_win->surface, 0, 0, 493 dri2_surf->base.Width, dri2_surf->base.Height); 494 } 495 496 _EGLContext *ctx; 497 if (dri2_drv->glFlush) { 498 ctx = _eglGetCurrentContext(); 499 if (ctx && ctx->DrawSurface == &dri2_surf->base) 500 dri2_drv->glFlush(); 501 } 502 503 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 504 (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable); 505 506 return EGL_TRUE; 507} 508 509/** 510 * Called via eglCreateImageKHR(), drv->API.CreateImageKHR(). 511 */ 512static _EGLImage * 513dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx, 514 EGLClientBuffer buffer, const EGLint *attr_list) 515{ 516 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 517 struct wl_egl_pixmap *wl_egl_pixmap = (struct wl_egl_pixmap *) buffer; 518 struct dri2_egl_buffer *dri2_buf; 519 EGLint wl_attr_list[] = { 520 EGL_WIDTH, 0, 521 EGL_HEIGHT, 0, 522 EGL_DRM_BUFFER_STRIDE_MESA, 0, 523 EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, 524 EGL_NONE 525 }; 526 527 dri2_buf = malloc(sizeof *dri2_buf); 528 if (!dri2_buf) 529 return NULL; 530 531 dri2_buf->dri2_dpy = dri2_dpy; 532 dri2_buf->dri_buffer = 533 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, 534 __DRI_BUFFER_FRONT_LEFT, 32, 535 wl_egl_pixmap->width, 536 wl_egl_pixmap->height); 537 538 wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy; 539 wl_egl_pixmap->driver_private = dri2_buf; 540 541 wl_egl_pixmap->buffer = 542 wl_drm_create_buffer(dri2_dpy->wl_drm, 543 dri2_buf->dri_buffer->name, 544 wl_egl_pixmap->width, 545 wl_egl_pixmap->height, 546 dri2_buf->dri_buffer->pitch, 547 wl_egl_pixmap->visual); 548 549 wl_attr_list[1] = wl_egl_pixmap->width; 550 wl_attr_list[3] = wl_egl_pixmap->height; 551 wl_attr_list[5] = dri2_buf->dri_buffer->pitch / 4; 552 553 return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA, 554 (EGLClientBuffer)(intptr_t) dri2_buf->dri_buffer->name, wl_attr_list); 555} 556 557static _EGLImage * 558dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 559 _EGLContext *ctx, EGLenum target, 560 EGLClientBuffer buffer, const EGLint *attr_list) 561{ 562 (void) drv; 563 564 switch (target) { 565 case EGL_NATIVE_PIXMAP_KHR: 566 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); 567 default: 568 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); 569 } 570} 571 572static int 573dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id) 574{ 575 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 576 int ret = 0; 577 578 dri2_dpy->authenticated = false; 579 580 wl_drm_authenticate(dri2_dpy->wl_drm, id); 581 force_roundtrip(dri2_dpy->wl_dpy); 582 583 if (!dri2_dpy->authenticated) 584 ret = -1; 585 586 /* reset authenticated */ 587 dri2_dpy->authenticated = true; 588 589 return ret; 590} 591 592/** 593 * Called via eglTerminate(), drv->API.Terminate(). 594 */ 595static EGLBoolean 596dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 597{ 598 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 599 600 _eglReleaseDisplayResources(drv, disp); 601 _eglCleanupDisplay(disp); 602 603 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 604 close(dri2_dpy->fd); 605 dlclose(dri2_dpy->driver); 606 free(dri2_dpy->driver_name); 607 free(dri2_dpy); 608 disp->DriverData = NULL; 609 610 return EGL_TRUE; 611} 612 613static void 614drm_handle_device(void *data, struct wl_drm *drm, const char *device) 615{ 616 struct dri2_egl_display *dri2_dpy = data; 617 drm_magic_t magic; 618 619 dri2_dpy->device_name = strdup(device); 620 if (!dri2_dpy->device_name) 621 return; 622 623 dri2_dpy->fd = open(dri2_dpy->device_name, O_RDWR); 624 if (dri2_dpy->fd == -1) { 625 _eglLog(_EGL_WARNING, "wayland-egl: could not open %s (%s)", 626 dri2_dpy->device_name, strerror(errno)); 627 return; 628 } 629 630 drmGetMagic(dri2_dpy->fd, &magic); 631 wl_drm_authenticate(dri2_dpy->wl_drm, magic); 632} 633 634static void 635drm_handle_authenticated(void *data, struct wl_drm *drm) 636{ 637 struct dri2_egl_display *dri2_dpy = data; 638 639 dri2_dpy->authenticated = true; 640} 641 642static const struct wl_drm_listener drm_listener = { 643 drm_handle_device, 644 drm_handle_authenticated 645}; 646 647EGLBoolean 648dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp) 649{ 650 struct dri2_egl_display *dri2_dpy; 651 uint32_t id; 652 int i; 653 654 drv->API.CreateWindowSurface = dri2_create_window_surface; 655 drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; 656 drv->API.DestroySurface = dri2_destroy_surface; 657 drv->API.SwapBuffers = dri2_swap_buffers; 658 drv->API.CreateImageKHR = dri2_wayland_create_image_khr; 659 drv->API.Terminate = dri2_terminate; 660 661 dri2_dpy = malloc(sizeof *dri2_dpy); 662 if (!dri2_dpy) 663 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 664 665 memset(dri2_dpy, 0, sizeof *dri2_dpy); 666 667 disp->DriverData = (void *) dri2_dpy; 668 dri2_dpy->wl_dpy = disp->PlatformDisplay; 669 670 id = wl_display_get_global(dri2_dpy->wl_dpy, "wl_drm", 1); 671 if (id == 0) 672 wl_display_iterate(dri2_dpy->wl_dpy, WL_DISPLAY_READABLE); 673 id = wl_display_get_global(dri2_dpy->wl_dpy, "wl_drm", 1); 674 if (id == 0) 675 goto cleanup_dpy; 676 dri2_dpy->wl_drm = wl_drm_create(dri2_dpy->wl_dpy, id, 1); 677 if (!dri2_dpy->wl_drm) 678 goto cleanup_dpy; 679 wl_drm_add_listener(dri2_dpy->wl_drm, &drm_listener, dri2_dpy); 680 force_roundtrip(dri2_dpy->wl_dpy); 681 if (dri2_dpy->fd == -1) 682 goto cleanup_drm; 683 684 force_roundtrip(dri2_dpy->wl_dpy); 685 if (!dri2_dpy->authenticated) 686 goto cleanup_fd; 687 688 dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); 689 if (dri2_dpy->driver_name == NULL) { 690 _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); 691 goto cleanup_fd; 692 } 693 694 if (!dri2_load_driver(disp)) 695 goto cleanup_driver_name; 696 697 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; 698 dri2_dpy->dri2_loader_extension.base.version = 3; 699 dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers; 700 dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer; 701 dri2_dpy->dri2_loader_extension.getBuffersWithFormat = 702 dri2_get_buffers_with_format; 703 704 dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base; 705 dri2_dpy->extensions[1] = &image_lookup_extension.base; 706 dri2_dpy->extensions[2] = NULL; 707 708 if (!dri2_create_screen(disp)) 709 goto cleanup_driver; 710 711 for (i = 0; dri2_dpy->driver_configs[i]; i++) 712 dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 713 EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL); 714 715 716 disp->Extensions.KHR_image_pixmap = EGL_TRUE; 717 718 disp->Extensions.WL_bind_wayland_display = EGL_TRUE; 719 dri2_dpy->authenticate = dri2_wayland_authenticate; 720 721 /* we're supporting EGL 1.4 */ 722 disp->VersionMajor = 1; 723 disp->VersionMinor = 4; 724 725 return EGL_TRUE; 726 727 cleanup_driver: 728 dlclose(dri2_dpy->driver); 729 cleanup_driver_name: 730 free(dri2_dpy->driver_name); 731 cleanup_fd: 732 close(dri2_dpy->fd); 733 cleanup_drm: 734 free(dri2_dpy->device_name); 735 wl_drm_destroy(dri2_dpy->wl_drm); 736 cleanup_dpy: 737 free(dri2_dpy); 738 739 return EGL_FALSE; 740} 741