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