platform_wayland.c revision 6b369c4c7cd8a52f99bbff2a57fb316b33a87495
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(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 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->name = dri2_buf->dri_buffer->name; 539 wl_egl_pixmap->stride = dri2_buf->dri_buffer->pitch; 540 wl_egl_pixmap->destroy = dri2_wl_egl_pixmap_destroy; 541 wl_egl_pixmap->driver_private = dri2_buf; 542 543 wl_attr_list[1] = wl_egl_pixmap->width; 544 wl_attr_list[3] = wl_egl_pixmap->height; 545 wl_attr_list[5] = wl_egl_pixmap->stride / 4; 546 547 548 return dri2_create_image_khr(disp->Driver, disp, ctx, EGL_DRM_BUFFER_MESA, 549 (EGLClientBuffer)(intptr_t) wl_egl_pixmap->name, wl_attr_list); 550} 551 552static _EGLImage * 553dri2_wayland_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 554 _EGLContext *ctx, EGLenum target, 555 EGLClientBuffer buffer, const EGLint *attr_list) 556{ 557 (void) drv; 558 559 switch (target) { 560 case EGL_NATIVE_PIXMAP_KHR: 561 return dri2_create_image_khr_pixmap(disp, ctx, buffer, attr_list); 562 default: 563 return dri2_create_image_khr(drv, disp, ctx, target, buffer, attr_list); 564 } 565} 566 567static int 568dri2_wayland_authenticate(_EGLDisplay *disp, uint32_t id) 569{ 570 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 571 int ret = 0; 572 573 dri2_dpy->wl_dpy->authenticated = false; 574 575 wl_drm_authenticate(dri2_dpy->wl_dpy->drm, id); 576 force_roundtrip(dri2_dpy->wl_dpy->display); 577 578 if (!dri2_dpy->wl_dpy->authenticated) 579 ret = -1; 580 581 /* reset authenticated */ 582 dri2_dpy->wl_dpy->authenticated = true; 583 584 return ret; 585} 586 587/** 588 * Called via eglTerminate(), drv->API.Terminate(). 589 */ 590static EGLBoolean 591dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 592{ 593 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 594 595 _eglReleaseDisplayResources(drv, disp); 596 _eglCleanupDisplay(disp); 597 598 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 599 close(dri2_dpy->fd); 600 dlclose(dri2_dpy->driver); 601 free(dri2_dpy->driver_name); 602 free(dri2_dpy); 603 disp->DriverData = NULL; 604 605 return EGL_TRUE; 606} 607 608EGLBoolean 609dri2_initialize_wayland(_EGLDriver *drv, _EGLDisplay *disp) 610{ 611 struct dri2_egl_display *dri2_dpy; 612 int i; 613 614 drv->API.CreateWindowSurface = dri2_create_window_surface; 615 drv->API.CreatePixmapSurface = dri2_create_pixmap_surface; 616 drv->API.DestroySurface = dri2_destroy_surface; 617 drv->API.SwapBuffers = dri2_swap_buffers; 618 drv->API.CreateImageKHR = dri2_wayland_create_image_khr; 619 drv->API.Terminate = dri2_terminate; 620 621 dri2_dpy = malloc(sizeof *dri2_dpy); 622 if (!dri2_dpy) 623 return _eglError(EGL_BAD_ALLOC, "eglInitialize"); 624 625 memset(dri2_dpy, 0, sizeof *dri2_dpy); 626 627 disp->DriverData = (void *) dri2_dpy; 628 dri2_dpy->wl_dpy = disp->PlatformDisplay; 629 630 if (dri2_dpy->wl_dpy->fd == -1) 631 force_roundtrip(dri2_dpy->wl_dpy->display); 632 if (dri2_dpy->wl_dpy->fd == -1) 633 goto cleanup_dpy; 634 635 dri2_dpy->fd = dup(dri2_dpy->wl_dpy->fd); 636 if (dri2_dpy->fd < 0) { 637 _eglError(EGL_BAD_ALLOC, "DRI2: failed to dup fd"); 638 goto cleanup_dpy; 639 } 640 641 if (!dri2_dpy->wl_dpy->authenticated) 642 force_roundtrip(dri2_dpy->wl_dpy->display); 643 if (!dri2_dpy->wl_dpy->authenticated) 644 goto cleanup_dpy; 645 646 dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd); 647 if (dri2_dpy->driver_name == NULL) { 648 _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name"); 649 goto cleanup_fd; 650 } 651 652 dri2_dpy->device_name = strdup(dri2_dpy->wl_dpy->device_name); 653 if (dri2_dpy->device_name == NULL) { 654 _eglError(EGL_BAD_ALLOC, "DRI2: failed to get device name"); 655 goto cleanup_driver_name; 656 } 657 658 if (!dri2_load_driver(disp)) 659 goto cleanup_device_name; 660 661 dri2_dpy->dri2_loader_extension.base.name = __DRI_DRI2_LOADER; 662 dri2_dpy->dri2_loader_extension.base.version = 3; 663 dri2_dpy->dri2_loader_extension.getBuffers = dri2_get_buffers; 664 dri2_dpy->dri2_loader_extension.flushFrontBuffer = dri2_flush_front_buffer; 665 dri2_dpy->dri2_loader_extension.getBuffersWithFormat = 666 dri2_get_buffers_with_format; 667 668 dri2_dpy->extensions[0] = &dri2_dpy->dri2_loader_extension.base; 669 dri2_dpy->extensions[1] = &image_lookup_extension.base; 670 dri2_dpy->extensions[2] = NULL; 671 672 if (!dri2_create_screen(disp)) 673 goto cleanup_driver; 674 675 for (i = 0; dri2_dpy->driver_configs[i]; i++) 676 dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, 677 EGL_WINDOW_BIT | EGL_PIXMAP_BIT, NULL); 678 679 680 disp->Extensions.MESA_drm_image = EGL_TRUE; 681 disp->Extensions.KHR_image_base = EGL_TRUE; 682 disp->Extensions.KHR_image_pixmap = EGL_TRUE; 683 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 684 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; 685 686 disp->Extensions.WL_bind_wayland_display = EGL_TRUE; 687 dri2_dpy->authenticate = dri2_wayland_authenticate; 688 689 /* we're supporting EGL 1.4 */ 690 disp->VersionMajor = 1; 691 disp->VersionMinor = 4; 692 693 return EGL_TRUE; 694 695 cleanup_driver: 696 dlclose(dri2_dpy->driver); 697 cleanup_device_name: 698 free(dri2_dpy->device_name); 699 cleanup_driver_name: 700 free(dri2_dpy->driver_name); 701 cleanup_fd: 702 close(dri2_dpy->fd); 703 cleanup_dpy: 704 free(dri2_dpy); 705 706 return EGL_FALSE; 707} 708