egl_dri2.c revision 3464ebd5
1/* 2 * Copyright © 2010 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 */ 27 28#include <stdlib.h> 29#include <string.h> 30#include <stdio.h> 31#include <limits.h> 32#include <dlfcn.h> 33#include <fcntl.h> 34#include <errno.h> 35#include <unistd.h> 36#include <xf86drm.h> 37#include <GL/gl.h> 38#include <GL/internal/dri_interface.h> 39#include <sys/types.h> 40#include <sys/stat.h> 41 42#include "egl_dri2.h" 43 44const __DRIuseInvalidateExtension use_invalidate = { 45 { __DRI_USE_INVALIDATE, 1 } 46}; 47 48EGLint dri2_to_egl_attribute_map[] = { 49 0, 50 EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */ 51 EGL_LEVEL, /* __DRI_ATTRIB_LEVEL */ 52 EGL_RED_SIZE, /* __DRI_ATTRIB_RED_SIZE */ 53 EGL_GREEN_SIZE, /* __DRI_ATTRIB_GREEN_SIZE */ 54 EGL_BLUE_SIZE, /* __DRI_ATTRIB_BLUE_SIZE */ 55 EGL_LUMINANCE_SIZE, /* __DRI_ATTRIB_LUMINANCE_SIZE */ 56 EGL_ALPHA_SIZE, /* __DRI_ATTRIB_ALPHA_SIZE */ 57 0, /* __DRI_ATTRIB_ALPHA_MASK_SIZE */ 58 EGL_DEPTH_SIZE, /* __DRI_ATTRIB_DEPTH_SIZE */ 59 EGL_STENCIL_SIZE, /* __DRI_ATTRIB_STENCIL_SIZE */ 60 0, /* __DRI_ATTRIB_ACCUM_RED_SIZE */ 61 0, /* __DRI_ATTRIB_ACCUM_GREEN_SIZE */ 62 0, /* __DRI_ATTRIB_ACCUM_BLUE_SIZE */ 63 0, /* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */ 64 EGL_SAMPLE_BUFFERS, /* __DRI_ATTRIB_SAMPLE_BUFFERS */ 65 EGL_SAMPLES, /* __DRI_ATTRIB_SAMPLES */ 66 0, /* __DRI_ATTRIB_RENDER_TYPE, */ 67 0, /* __DRI_ATTRIB_CONFIG_CAVEAT */ 68 0, /* __DRI_ATTRIB_CONFORMANT */ 69 0, /* __DRI_ATTRIB_DOUBLE_BUFFER */ 70 0, /* __DRI_ATTRIB_STEREO */ 71 0, /* __DRI_ATTRIB_AUX_BUFFERS */ 72 0, /* __DRI_ATTRIB_TRANSPARENT_TYPE */ 73 0, /* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */ 74 0, /* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */ 75 0, /* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */ 76 0, /* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */ 77 0, /* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */ 78 0, /* __DRI_ATTRIB_FLOAT_MODE */ 79 0, /* __DRI_ATTRIB_RED_MASK */ 80 0, /* __DRI_ATTRIB_GREEN_MASK */ 81 0, /* __DRI_ATTRIB_BLUE_MASK */ 82 0, /* __DRI_ATTRIB_ALPHA_MASK */ 83 EGL_MAX_PBUFFER_WIDTH, /* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */ 84 EGL_MAX_PBUFFER_HEIGHT, /* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */ 85 EGL_MAX_PBUFFER_PIXELS, /* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */ 86 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */ 87 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */ 88 0, /* __DRI_ATTRIB_VISUAL_SELECT_GROUP */ 89 0, /* __DRI_ATTRIB_SWAP_METHOD */ 90 EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */ 91 EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */ 92 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */ 93 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */ 94 0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */ 95 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */ 96 EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */ 97 0, /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */ 98}; 99 100static EGLBoolean 101dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) 102{ 103 if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0) 104 return EGL_FALSE; 105 106 if (!_eglMatchConfig(conf, criteria)) 107 return EGL_FALSE; 108 109 return EGL_TRUE; 110} 111 112struct dri2_egl_config * 113dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 114 int depth, EGLint surface_type, const EGLint *attr_list) 115{ 116 struct dri2_egl_config *conf; 117 struct dri2_egl_display *dri2_dpy; 118 _EGLConfig base; 119 unsigned int attrib, value, double_buffer; 120 EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; 121 _EGLConfig *matching_config; 122 EGLint num_configs = 0; 123 EGLint config_id; 124 int i; 125 126 dri2_dpy = disp->DriverData; 127 _eglInitConfig(&base, disp, id); 128 129 i = 0; 130 double_buffer = 0; 131 bind_to_texture_rgb = 0; 132 bind_to_texture_rgba = 0; 133 134 while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { 135 switch (attrib) { 136 case __DRI_ATTRIB_RENDER_TYPE: 137 if (value & __DRI_ATTRIB_RGBA_BIT) 138 value = EGL_RGB_BUFFER; 139 else if (value & __DRI_ATTRIB_LUMINANCE_BIT) 140 value = EGL_LUMINANCE_BUFFER; 141 else 142 /* not valid */; 143 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); 144 break; 145 146 case __DRI_ATTRIB_CONFIG_CAVEAT: 147 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 148 value = EGL_NON_CONFORMANT_CONFIG; 149 else if (value & __DRI_ATTRIB_SLOW_BIT) 150 value = EGL_SLOW_CONFIG; 151 else 152 value = EGL_NONE; 153 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); 154 break; 155 156 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 157 bind_to_texture_rgb = value; 158 break; 159 160 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 161 bind_to_texture_rgba = value; 162 break; 163 164 case __DRI_ATTRIB_DOUBLE_BUFFER: 165 double_buffer = value; 166 break; 167 168 default: 169 key = dri2_to_egl_attribute_map[attrib]; 170 if (key != 0) 171 _eglSetConfigKey(&base, key, value); 172 break; 173 } 174 } 175 176 if (attr_list) 177 for (i = 0; attr_list[i] != EGL_NONE; i += 2) 178 _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); 179 180 if (depth > 0 && depth != base.BufferSize) 181 return NULL; 182 183 base.NativeRenderable = EGL_TRUE; 184 185 base.SurfaceType = surface_type; 186 if (surface_type & (EGL_PBUFFER_BIT | 187 (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { 188 base.BindToTextureRGB = bind_to_texture_rgb; 189 if (base.AlphaSize > 0) 190 base.BindToTextureRGBA = bind_to_texture_rgba; 191 } 192 193 base.RenderableType = disp->ClientAPIs; 194 base.Conformant = disp->ClientAPIs; 195 196 if (!_eglValidateConfig(&base, EGL_FALSE)) { 197 _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); 198 return NULL; 199 } 200 201 config_id = base.ConfigID; 202 base.ConfigID = EGL_DONT_CARE; 203 base.SurfaceType = EGL_DONT_CARE; 204 num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, 205 (_EGLArrayForEach) dri2_match_config, &base); 206 207 if (num_configs == 1) { 208 conf = (struct dri2_egl_config *) matching_config; 209 210 if (double_buffer && !conf->dri_double_config) 211 conf->dri_double_config = dri_config; 212 else if (!double_buffer && !conf->dri_single_config) 213 conf->dri_single_config = dri_config; 214 else 215 /* a similar config type is already added (unlikely) => discard */ 216 return NULL; 217 } 218 else if (num_configs == 0) { 219 conf = malloc(sizeof *conf); 220 if (conf == NULL) 221 return NULL; 222 223 memcpy(&conf->base, &base, sizeof base); 224 if (double_buffer) { 225 conf->dri_double_config = dri_config; 226 conf->dri_single_config = NULL; 227 } else { 228 conf->dri_single_config = dri_config; 229 conf->dri_double_config = NULL; 230 } 231 conf->base.SurfaceType = 0; 232 conf->base.ConfigID = config_id; 233 234 _eglLinkConfig(&conf->base); 235 } 236 else { 237 assert(0); 238 return NULL; 239 } 240 241 conf->base.SurfaceType |= surface_type & (!double_buffer ? EGL_PIXMAP_BIT: 242 (EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT)); 243 244 return conf; 245} 246 247__DRIimage * 248dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 249{ 250 _EGLDisplay *disp = data; 251 struct dri2_egl_image *dri2_img; 252 _EGLImage *img; 253 254 (void) screen; 255 256 img = _eglLookupImage(image, disp); 257 if (img == NULL) { 258 _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image"); 259 return NULL; 260 } 261 262 dri2_img = dri2_egl_image(image); 263 264 return dri2_img->dri_image; 265} 266 267const __DRIimageLookupExtension image_lookup_extension = { 268 { __DRI_IMAGE_LOOKUP, 1 }, 269 dri2_lookup_egl_image 270}; 271 272static const char dri_driver_path[] = DEFAULT_DRIVER_DIR; 273 274struct dri2_extension_match { 275 const char *name; 276 int version; 277 int offset; 278}; 279 280static struct dri2_extension_match dri2_driver_extensions[] = { 281 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 282 { __DRI_DRI2, 1, offsetof(struct dri2_egl_display, dri2) }, 283 { NULL, 0, 0 } 284}; 285 286static struct dri2_extension_match dri2_core_extensions[] = { 287 { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, 288 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 289 { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 290 { NULL, 0, 0 } 291}; 292 293static struct dri2_extension_match swrast_driver_extensions[] = { 294 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 295 { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, 296 { NULL } 297}; 298 299static struct dri2_extension_match swrast_core_extensions[] = { 300 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 301 { NULL } 302}; 303 304static EGLBoolean 305dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, 306 struct dri2_extension_match *matches, 307 const __DRIextension **extensions) 308{ 309 int i, j, ret = EGL_TRUE; 310 void *field; 311 312 for (i = 0; extensions[i]; i++) { 313 _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name); 314 for (j = 0; matches[j].name; j++) { 315 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 316 extensions[i]->version >= matches[j].version) { 317 field = ((char *) dri2_dpy + matches[j].offset); 318 *(const __DRIextension **) field = extensions[i]; 319 _eglLog(_EGL_INFO, "DRI2: found extension %s version %d", 320 extensions[i]->name, extensions[i]->version); 321 } 322 } 323 } 324 325 for (j = 0; matches[j].name; j++) { 326 field = ((char *) dri2_dpy + matches[j].offset); 327 if (*(const __DRIextension **) field == NULL) { 328 _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d", 329 matches[j].name, matches[j].version); 330 ret = EGL_FALSE; 331 } 332 } 333 334 return ret; 335} 336 337static const __DRIextension ** 338dri2_open_driver(_EGLDisplay *disp) 339{ 340 struct dri2_egl_display *dri2_dpy = disp->DriverData; 341 const __DRIextension **extensions; 342 char path[PATH_MAX], *search_paths, *p, *next, *end; 343 344 search_paths = NULL; 345 if (geteuid() == getuid()) { 346 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 347 search_paths = getenv("LIBGL_DRIVERS_PATH"); 348 } 349 if (search_paths == NULL) 350 search_paths = DEFAULT_DRIVER_DIR; 351 352 dri2_dpy->driver = NULL; 353 end = search_paths + strlen(search_paths); 354 for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) { 355 int len; 356 next = strchr(p, ':'); 357 if (next == NULL) 358 next = end; 359 360 len = next - p; 361#if GLX_USE_TLS 362 snprintf(path, sizeof path, 363 "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name); 364 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 365#endif 366 if (dri2_dpy->driver == NULL) { 367 snprintf(path, sizeof path, 368 "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name); 369 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 370 if (dri2_dpy->driver == NULL) 371 _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror()); 372 } 373 } 374 375 if (dri2_dpy->driver == NULL) { 376 _eglLog(_EGL_WARNING, 377 "DRI2: failed to open %s (search paths %s)", 378 dri2_dpy->driver_name, search_paths); 379 return NULL; 380 } 381 382 _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path); 383 extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS); 384 if (extensions == NULL) { 385 _eglLog(_EGL_WARNING, 386 "DRI2: driver exports no extensions (%s)", dlerror()); 387 dlclose(dri2_dpy->driver); 388 } 389 390 return extensions; 391} 392 393EGLBoolean 394dri2_load_driver(_EGLDisplay *disp) 395{ 396 struct dri2_egl_display *dri2_dpy = disp->DriverData; 397 const __DRIextension **extensions; 398 399 extensions = dri2_open_driver(disp); 400 if (!extensions) 401 return EGL_FALSE; 402 403 if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { 404 dlclose(dri2_dpy->driver); 405 return EGL_FALSE; 406 } 407 408 return EGL_TRUE; 409} 410 411EGLBoolean 412dri2_load_driver_swrast(_EGLDisplay *disp) 413{ 414 struct dri2_egl_display *dri2_dpy = disp->DriverData; 415 const __DRIextension **extensions; 416 417 dri2_dpy->driver_name = "swrast"; 418 extensions = dri2_open_driver(disp); 419 if (!extensions) { 420 /* try again with swrastg */ 421 dri2_dpy->driver_name = "swrastg"; 422 extensions = dri2_open_driver(disp); 423 } 424 425 if (!extensions) 426 return EGL_FALSE; 427 428 if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) { 429 dlclose(dri2_dpy->driver); 430 return EGL_FALSE; 431 } 432 433 return EGL_TRUE; 434} 435 436void 437dri2_setup_screen(_EGLDisplay *disp) 438{ 439 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 440 unsigned int api_mask; 441 442 if (dri2_dpy->dri2) { 443 if (dri2_dpy->dri2->base.version >= 2) 444 api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 445 else 446 api_mask = 1 << __DRI_API_OPENGL; 447 } else { 448 assert(dri2_dpy->swrast); 449 if (dri2_dpy->swrast->base.version >= 2) 450 api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2; 451 else 452 api_mask = 1 << __DRI_API_OPENGL; 453 } 454 455 disp->ClientAPIs = 0; 456 if (api_mask & (1 <<__DRI_API_OPENGL)) 457 disp->ClientAPIs |= EGL_OPENGL_BIT; 458 if (api_mask & (1 <<__DRI_API_GLES)) 459 disp->ClientAPIs |= EGL_OPENGL_ES_BIT; 460 if (api_mask & (1 << __DRI_API_GLES2)) 461 disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; 462 463 if (dri2_dpy->dri2) { 464 if (dri2_dpy->dri2->base.version >= 2) { 465 disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; 466 disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; 467 disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE; 468 } 469 } else { 470 assert(dri2_dpy->swrast); 471 if (dri2_dpy->swrast->base.version >= 2) { 472 disp->Extensions.KHR_surfaceless_gles1 = EGL_TRUE; 473 disp->Extensions.KHR_surfaceless_gles2 = EGL_TRUE; 474 disp->Extensions.KHR_surfaceless_opengl = EGL_TRUE; 475 } 476 } 477 478 if (dri2_dpy->image) { 479 disp->Extensions.MESA_drm_image = EGL_TRUE; 480 disp->Extensions.KHR_image_base = EGL_TRUE; 481 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 482 } 483} 484 485EGLBoolean 486dri2_create_screen(_EGLDisplay *disp) 487{ 488 const __DRIextension **extensions; 489 struct dri2_egl_display *dri2_dpy; 490 491 dri2_dpy = disp->DriverData; 492 493 if (dri2_dpy->dri2) { 494 dri2_dpy->dri_screen = 495 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, 496 &dri2_dpy->driver_configs, disp); 497 } else { 498 assert(dri2_dpy->swrast); 499 dri2_dpy->dri_screen = 500 dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, 501 &dri2_dpy->driver_configs, disp); 502 } 503 504 if (dri2_dpy->dri_screen == NULL) { 505 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 506 return EGL_FALSE; 507 } 508 509 dri2_dpy->own_dri_screen = 1; 510 511 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 512 513 if (dri2_dpy->dri2) { 514 if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) 515 goto cleanup_dri_screen; 516 } else { 517 assert(dri2_dpy->swrast); 518 if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) 519 goto cleanup_dri_screen; 520 } 521 522 dri2_setup_screen(disp); 523 524 return EGL_TRUE; 525 526 cleanup_dri_screen: 527 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 528 529 return EGL_FALSE; 530} 531 532/** 533 * Called via eglInitialize(), GLX_drv->API.Initialize(). 534 */ 535static EGLBoolean 536dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) 537{ 538 /* not until swrast_dri is supported */ 539 if (disp->Options.UseFallback) 540 return EGL_FALSE; 541 542 switch (disp->Platform) { 543#ifdef HAVE_X11_PLATFORM 544 case _EGL_PLATFORM_X11: 545 if (disp->Options.TestOnly) 546 return EGL_TRUE; 547 return dri2_initialize_x11(drv, disp); 548#endif 549 550#ifdef HAVE_LIBUDEV 551#ifdef HAVE_DRM_PLATFORM 552 case _EGL_PLATFORM_DRM: 553 if (disp->Options.TestOnly) 554 return EGL_TRUE; 555 return dri2_initialize_drm(drv, disp); 556#endif 557#ifdef HAVE_WAYLAND_PLATFORM 558 case _EGL_PLATFORM_WAYLAND: 559 if (disp->Options.TestOnly) 560 return EGL_TRUE; 561 return dri2_initialize_wayland(drv, disp); 562#endif 563#endif 564 565 default: 566 return EGL_FALSE; 567 } 568} 569 570/** 571 * Called via eglTerminate(), drv->API.Terminate(). 572 */ 573static EGLBoolean 574dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 575{ 576 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 577 578 _eglReleaseDisplayResources(drv, disp); 579 _eglCleanupDisplay(disp); 580 581 if (dri2_dpy->own_dri_screen) 582 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 583 if (dri2_dpy->fd) 584 close(dri2_dpy->fd); 585 if (dri2_dpy->driver) 586 dlclose(dri2_dpy->driver); 587 588 if (disp->PlatformDisplay == NULL) { 589 switch (disp->Platform) { 590#ifdef HAVE_X11_PLATFORM 591 case _EGL_PLATFORM_X11: 592 xcb_disconnect(dri2_dpy->conn); 593 break; 594#endif 595#ifdef HAVE_WAYLAND_PLATFORM 596 case _EGL_PLATFORM_WAYLAND: 597 wl_display_destroy(dri2_dpy->wl_dpy); 598 break; 599#endif 600 default: 601 break; 602 } 603 } 604 605 free(dri2_dpy); 606 disp->DriverData = NULL; 607 608 return EGL_TRUE; 609} 610 611 612/** 613 * Called via eglCreateContext(), drv->API.CreateContext(). 614 */ 615static _EGLContext * 616dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 617 _EGLContext *share_list, const EGLint *attrib_list) 618{ 619 struct dri2_egl_context *dri2_ctx; 620 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 621 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 622 struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 623 const __DRIconfig *dri_config; 624 int api; 625 626 (void) drv; 627 628 dri2_ctx = malloc(sizeof *dri2_ctx); 629 if (!dri2_ctx) { 630 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 631 return NULL; 632 } 633 634 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 635 goto cleanup; 636 637 switch (dri2_ctx->base.ClientAPI) { 638 case EGL_OPENGL_ES_API: 639 switch (dri2_ctx->base.ClientVersion) { 640 case 1: 641 api = __DRI_API_GLES; 642 break; 643 case 2: 644 api = __DRI_API_GLES2; 645 break; 646 default: 647 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 648 return NULL; 649 } 650 break; 651 case EGL_OPENGL_API: 652 api = __DRI_API_OPENGL; 653 break; 654 default: 655 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 656 return NULL; 657 } 658 659 if (conf != NULL) { 660 /* The config chosen here isn't necessarily 661 * used for surfaces later. 662 * A pixmap surface will use the single config. 663 * This opportunity depends on disabling the 664 * doubleBufferMode check in 665 * src/mesa/main/context.c:check_compatible() 666 */ 667 if (dri2_config->dri_double_config) 668 dri_config = dri2_config->dri_double_config; 669 else 670 dri_config = dri2_config->dri_single_config; 671 } 672 else 673 dri_config = NULL; 674 675 if (dri2_dpy->dri2) { 676 if (dri2_dpy->dri2->base.version >= 2) { 677 dri2_ctx->dri_context = 678 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 679 api, 680 dri_config, 681 dri2_ctx_shared ? 682 dri2_ctx_shared->dri_context : NULL, 683 dri2_ctx); 684 } else if (api == __DRI_API_OPENGL) { 685 dri2_ctx->dri_context = 686 dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen, 687 dri_config, 688 dri2_ctx_shared ? 689 dri2_ctx_shared->dri_context : NULL, 690 dri2_ctx); 691 } else { 692 /* fail */ 693 } 694 } else { 695 assert(dri2_dpy->swrast); 696 if (dri2_dpy->swrast->base.version >= 2) { 697 dri2_ctx->dri_context = 698 dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 699 api, 700 dri_config, 701 dri2_ctx_shared ? 702 dri2_ctx_shared->dri_context : NULL, 703 dri2_ctx); 704 } else if (api == __DRI_API_OPENGL) { 705 dri2_ctx->dri_context = 706 dri2_dpy->core->createNewContext(dri2_dpy->dri_screen, 707 dri_config, 708 dri2_ctx_shared ? 709 dri2_ctx_shared->dri_context : NULL, 710 dri2_ctx); 711 } else { 712 /* fail */ 713 } 714 } 715 716 if (!dri2_ctx->dri_context) 717 goto cleanup; 718 719 return &dri2_ctx->base; 720 721 cleanup: 722 free(dri2_ctx); 723 return NULL; 724} 725 726/** 727 * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 728 */ 729static EGLBoolean 730dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 731 _EGLSurface *rsurf, _EGLContext *ctx) 732{ 733 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 734 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 735 struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); 736 struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); 737 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 738 _EGLContext *old_ctx; 739 _EGLSurface *old_dsurf, *old_rsurf; 740 __DRIdrawable *ddraw, *rdraw; 741 __DRIcontext *cctx; 742 743 /* make new bindings */ 744 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 745 return EGL_FALSE; 746 747 /* flush before context switch */ 748 if (old_ctx && dri2_drv->glFlush) 749 dri2_drv->glFlush(); 750 751 ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; 752 rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; 753 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 754 755 if (old_ctx) { 756 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 757 dri2_dpy->core->unbindContext(old_cctx); 758 } 759 760 if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || 761 dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 762 if (old_dsurf) 763 drv->API.DestroySurface(drv, disp, old_dsurf); 764 if (old_rsurf) 765 drv->API.DestroySurface(drv, disp, old_rsurf); 766 /* no destroy? */ 767 if (old_ctx) 768 _eglPutContext(old_ctx); 769 770 return EGL_TRUE; 771 } else { 772 /* undo the previous _eglBindContext */ 773 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); 774 assert(&dri2_ctx->base == ctx && 775 &dri2_dsurf->base == dsurf && 776 &dri2_rsurf->base == rsurf); 777 778 _eglPutSurface(dsurf); 779 _eglPutSurface(rsurf); 780 _eglPutContext(ctx); 781 782 _eglPutSurface(old_dsurf); 783 _eglPutSurface(old_rsurf); 784 _eglPutContext(old_ctx); 785 786 return EGL_FALSE; 787 } 788} 789 790/* 791 * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 792 */ 793static _EGLProc 794dri2_get_proc_address(_EGLDriver *drv, const char *procname) 795{ 796 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 797 798 return dri2_drv->get_proc_address(procname); 799} 800 801static EGLBoolean 802dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 803{ 804 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 805 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); 806 807 (void) drv; 808 809 /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 810 * we need to copy fake to real here.*/ 811 812 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 813 814 return EGL_TRUE; 815} 816 817static EGLBoolean 818dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) 819{ 820 (void) drv; 821 (void) disp; 822 823 if (engine != EGL_CORE_NATIVE_ENGINE) 824 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 825 /* glXWaitX(); */ 826 827 return EGL_TRUE; 828} 829 830static EGLBoolean 831dri2_bind_tex_image(_EGLDriver *drv, 832 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 833{ 834 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 835 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 836 struct dri2_egl_context *dri2_ctx; 837 _EGLContext *ctx; 838 GLint format, target; 839 840 ctx = _eglGetCurrentContext(); 841 dri2_ctx = dri2_egl_context(ctx); 842 843 if (!_eglBindTexImage(drv, disp, surf, buffer)) 844 return EGL_FALSE; 845 846 switch (dri2_surf->base.TextureFormat) { 847 case EGL_TEXTURE_RGB: 848 format = __DRI_TEXTURE_FORMAT_RGB; 849 break; 850 case EGL_TEXTURE_RGBA: 851 format = __DRI_TEXTURE_FORMAT_RGBA; 852 break; 853 default: 854 assert(0); 855 } 856 857 switch (dri2_surf->base.TextureTarget) { 858 case EGL_TEXTURE_2D: 859 target = GL_TEXTURE_2D; 860 break; 861 default: 862 assert(0); 863 } 864 865 (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context, 866 target, format, 867 dri2_surf->dri_drawable); 868 869 return EGL_TRUE; 870} 871 872static EGLBoolean 873dri2_release_tex_image(_EGLDriver *drv, 874 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 875{ 876#if __DRI_TEX_BUFFER_VERSION >= 3 877 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 878 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 879 struct dri2_egl_context *dri2_ctx; 880 _EGLContext *ctx; 881 GLint target; 882 883 ctx = _eglGetCurrentContext(); 884 dri2_ctx = dri2_egl_context(ctx); 885 886 if (!_eglReleaseTexImage(drv, disp, surf, buffer)) 887 return EGL_FALSE; 888 889 switch (dri2_surf->base.TextureTarget) { 890 case EGL_TEXTURE_2D: 891 target = GL_TEXTURE_2D; 892 break; 893 default: 894 assert(0); 895 } 896 if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL) 897 (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context, 898 target, 899 dri2_surf->dri_drawable); 900#endif 901 902 return EGL_TRUE; 903} 904 905static _EGLImage * 906dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 907 EGLClientBuffer buffer, 908 const EGLint *attr_list) 909{ 910 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 911 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 912 struct dri2_egl_image *dri2_img; 913 GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 914 915 if (renderbuffer == 0) { 916 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 917 return EGL_NO_IMAGE_KHR; 918 } 919 920 dri2_img = malloc(sizeof *dri2_img); 921 if (!dri2_img) { 922 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 923 return EGL_NO_IMAGE_KHR; 924 } 925 926 if (!_eglInitImage(&dri2_img->base, disp)) 927 return EGL_NO_IMAGE_KHR; 928 929 dri2_img->dri_image = 930 dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, 931 renderbuffer, 932 dri2_img); 933 934 return &dri2_img->base; 935} 936 937static _EGLImage * 938dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 939 EGLClientBuffer buffer, const EGLint *attr_list) 940{ 941 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 942 struct dri2_egl_image *dri2_img; 943 EGLint format, name, pitch, err; 944 _EGLImageAttribs attrs; 945 946 (void) ctx; 947 948 name = (EGLint) (uintptr_t) buffer; 949 950 err = _eglParseImageAttribList(&attrs, disp, attr_list); 951 if (err != EGL_SUCCESS) 952 return NULL; 953 954 if (attrs.Width <= 0 || attrs.Height <= 0 || 955 attrs.DRMBufferStrideMESA <= 0) { 956 _eglError(EGL_BAD_PARAMETER, 957 "bad width, height or stride"); 958 return NULL; 959 } 960 961 switch (attrs.DRMBufferFormatMESA) { 962 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 963 format = __DRI_IMAGE_FORMAT_ARGB8888; 964 pitch = attrs.DRMBufferStrideMESA; 965 break; 966 default: 967 _eglError(EGL_BAD_PARAMETER, 968 "dri2_create_image_khr: unsupported pixmap depth"); 969 return NULL; 970 } 971 972 dri2_img = malloc(sizeof *dri2_img); 973 if (!dri2_img) { 974 _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm"); 975 return NULL; 976 } 977 978 if (!_eglInitImage(&dri2_img->base, disp)) { 979 free(dri2_img); 980 return NULL; 981 } 982 983 dri2_img->dri_image = 984 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 985 attrs.Width, 986 attrs.Height, 987 format, 988 name, 989 pitch, 990 dri2_img); 991 if (dri2_img->dri_image == NULL) { 992 free(dri2_img); 993 _eglError(EGL_BAD_ALLOC, "dri2_create_image_mesa_drm"); 994 return NULL; 995 } 996 997 return &dri2_img->base; 998} 999 1000#ifdef HAVE_WAYLAND_PLATFORM 1001static _EGLImage * 1002dri2_reference_drm_image(_EGLDisplay *disp, _EGLContext *ctx, 1003 __DRIimage *dri_image, EGLint width, EGLint height) 1004{ 1005 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1006 EGLint attr_list[] = { 1007 EGL_WIDTH, 0, 1008 EGL_HEIGHT, 0, 1009 EGL_DRM_BUFFER_STRIDE_MESA, 0, 1010 EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, 1011 EGL_NONE 1012 }; 1013 EGLint name, stride; 1014 1015 dri2_dpy->image->queryImage(dri_image, __DRI_IMAGE_ATTRIB_NAME, &name); 1016 dri2_dpy->image->queryImage(dri_image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); 1017 1018 attr_list[1] = width; 1019 attr_list[3] = height; 1020 attr_list[5] = stride / 4; 1021 1022 return dri2_create_image_mesa_drm_buffer(disp, ctx, 1023 (EGLClientBuffer)(intptr_t) name, 1024 attr_list); 1025} 1026 1027static _EGLImage * 1028dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1029 EGLClientBuffer _buffer, 1030 const EGLint *attr_list) 1031{ 1032 struct wl_buffer *buffer = (struct wl_buffer *) _buffer; 1033 (void) attr_list; 1034 1035 if (!wayland_buffer_is_drm(buffer)) 1036 return NULL; 1037 1038 return dri2_reference_drm_image(disp, ctx, 1039 wayland_drm_buffer_get_buffer(buffer), 1040 buffer->width, 1041 buffer->height); 1042} 1043#endif 1044 1045_EGLImage * 1046dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 1047 _EGLContext *ctx, EGLenum target, 1048 EGLClientBuffer buffer, const EGLint *attr_list) 1049{ 1050 (void) drv; 1051 1052 switch (target) { 1053 case EGL_GL_RENDERBUFFER_KHR: 1054 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 1055 case EGL_DRM_BUFFER_MESA: 1056 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 1057#ifdef HAVE_WAYLAND_PLATFORM 1058 case EGL_WAYLAND_BUFFER_WL: 1059 return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 1060#endif 1061 default: 1062 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1063 return EGL_NO_IMAGE_KHR; 1064 } 1065} 1066 1067static EGLBoolean 1068dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) 1069{ 1070 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1071 struct dri2_egl_image *dri2_img = dri2_egl_image(image); 1072 1073 (void) drv; 1074 1075 dri2_dpy->image->destroyImage(dri2_img->dri_image); 1076 free(dri2_img); 1077 1078 return EGL_TRUE; 1079} 1080 1081static _EGLImage * 1082dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, 1083 const EGLint *attr_list) 1084{ 1085 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1086 struct dri2_egl_image *dri2_img; 1087 _EGLImageAttribs attrs; 1088 unsigned int dri_use, valid_mask; 1089 int format; 1090 EGLint err = EGL_SUCCESS; 1091 1092 (void) drv; 1093 1094 dri2_img = malloc(sizeof *dri2_img); 1095 if (!dri2_img) { 1096 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1097 return EGL_NO_IMAGE_KHR; 1098 } 1099 1100 if (!attr_list) { 1101 err = EGL_BAD_PARAMETER; 1102 goto cleanup_img; 1103 } 1104 1105 if (!_eglInitImage(&dri2_img->base, disp)) { 1106 err = EGL_BAD_PARAMETER; 1107 goto cleanup_img; 1108 } 1109 1110 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1111 if (err != EGL_SUCCESS) 1112 goto cleanup_img; 1113 1114 if (attrs.Width <= 0 || attrs.Height <= 0) { 1115 _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", 1116 attrs.Width, attrs.Height); 1117 goto cleanup_img; 1118 } 1119 1120 switch (attrs.DRMBufferFormatMESA) { 1121 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1122 format = __DRI_IMAGE_FORMAT_ARGB8888; 1123 break; 1124 default: 1125 _eglLog(_EGL_WARNING, "bad image format value 0x%04x", 1126 attrs.DRMBufferFormatMESA); 1127 goto cleanup_img; 1128 } 1129 1130 valid_mask = 1131 EGL_DRM_BUFFER_USE_SCANOUT_MESA | 1132 EGL_DRM_BUFFER_USE_SHARE_MESA | 1133 EGL_DRM_BUFFER_USE_CURSOR_MESA; 1134 if (attrs.DRMBufferUseMESA & ~valid_mask) { 1135 _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", 1136 attrs.DRMBufferUseMESA & ~valid_mask); 1137 goto cleanup_img; 1138 } 1139 1140 dri_use = 0; 1141 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 1142 dri_use |= __DRI_IMAGE_USE_SHARE; 1143 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 1144 dri_use |= __DRI_IMAGE_USE_SCANOUT; 1145 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 1146 dri_use |= __DRI_IMAGE_USE_CURSOR; 1147 1148 dri2_img->dri_image = 1149 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 1150 attrs.Width, attrs.Height, 1151 format, dri_use, dri2_img); 1152 if (dri2_img->dri_image == NULL) { 1153 err = EGL_BAD_ALLOC; 1154 goto cleanup_img; 1155 } 1156 1157 return &dri2_img->base; 1158 1159 cleanup_img: 1160 free(dri2_img); 1161 _eglError(err, "dri2_create_drm_image_mesa"); 1162 1163 return EGL_NO_IMAGE_KHR; 1164} 1165 1166static EGLBoolean 1167dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 1168 EGLint *name, EGLint *handle, EGLint *stride) 1169{ 1170 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1171 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 1172 1173 (void) drv; 1174 1175 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 1176 __DRI_IMAGE_ATTRIB_NAME, name)) { 1177 _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 1178 return EGL_FALSE; 1179 } 1180 1181 if (handle) 1182 dri2_dpy->image->queryImage(dri2_img->dri_image, 1183 __DRI_IMAGE_ATTRIB_HANDLE, handle); 1184 1185 if (stride) 1186 dri2_dpy->image->queryImage(dri2_img->dri_image, 1187 __DRI_IMAGE_ATTRIB_STRIDE, stride); 1188 1189 return EGL_TRUE; 1190} 1191 1192#ifdef HAVE_WAYLAND_PLATFORM 1193 1194static void * 1195dri2_wl_reference_buffer(void *user_data, uint32_t name, 1196 int32_t width, int32_t height, 1197 uint32_t stride, struct wl_visual *visual) 1198{ 1199 _EGLDisplay *disp = user_data; 1200 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1201 __DRIimage *image; 1202 1203 image = dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1204 width, height, 1205 __DRI_IMAGE_FORMAT_ARGB8888, 1206 name, stride / 4, 1207 NULL); 1208 1209 return image; 1210} 1211 1212static void 1213dri2_wl_release_buffer(void *user_data, void *buffer) 1214{ 1215 _EGLDisplay *disp = user_data; 1216 __DRIimage *image = buffer; 1217 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1218 1219 dri2_dpy->image->destroyImage(image); 1220} 1221 1222static struct wayland_drm_callbacks wl_drm_callbacks = { 1223 .authenticate = NULL, 1224 .reference_buffer = dri2_wl_reference_buffer, 1225 .release_buffer = dri2_wl_release_buffer 1226}; 1227 1228static EGLBoolean 1229dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1230 struct wl_display *wl_dpy) 1231{ 1232 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1233 1234 (void) drv; 1235 1236 if (dri2_dpy->wl_server_drm) 1237 return EGL_FALSE; 1238 1239 wl_drm_callbacks.authenticate = 1240 (int(*)(void *, uint32_t)) dri2_dpy->authenticate; 1241 1242 dri2_dpy->wl_server_drm = 1243 wayland_drm_init(wl_dpy, dri2_dpy->device_name, 1244 &wl_drm_callbacks, disp); 1245 1246 if (!dri2_dpy->wl_server_drm) 1247 return EGL_FALSE; 1248 1249 return EGL_TRUE; 1250} 1251 1252static EGLBoolean 1253dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1254 struct wl_display *wl_dpy) 1255{ 1256 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1257 1258 (void) drv; 1259 1260 if (!dri2_dpy->wl_server_drm) 1261 return EGL_FALSE; 1262 1263 wayland_drm_uninit(dri2_dpy->wl_server_drm); 1264 dri2_dpy->wl_server_drm = NULL; 1265 1266 return EGL_TRUE; 1267} 1268#endif 1269 1270static void 1271dri2_unload(_EGLDriver *drv) 1272{ 1273 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1274 1275 if (dri2_drv->handle) 1276 dlclose(dri2_drv->handle); 1277 free(dri2_drv); 1278} 1279 1280static EGLBoolean 1281dri2_load(_EGLDriver *drv) 1282{ 1283 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1284#ifdef HAVE_SHARED_GLAPI 1285 const char *libname = "libglapi.so.0"; 1286#else 1287 /* 1288 * Both libGL.so and libglapi.so are glapi providers. There is no way to 1289 * tell which one to load. 1290 */ 1291 const char *libname = NULL; 1292#endif 1293 void *handle; 1294 1295 /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */ 1296 handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); 1297 if (handle) { 1298 dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) 1299 dlsym(handle, "_glapi_get_proc_address"); 1300 if (!dri2_drv->get_proc_address || !libname) { 1301 /* no need to keep a reference */ 1302 dlclose(handle); 1303 handle = NULL; 1304 } 1305 } 1306 1307 /* if glapi is not available, loading DRI drivers will fail */ 1308 if (!dri2_drv->get_proc_address) { 1309 _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); 1310 return EGL_FALSE; 1311 } 1312 1313 dri2_drv->glFlush = (void (*)(void)) 1314 dri2_drv->get_proc_address("glFlush"); 1315 1316 dri2_drv->handle = handle; 1317 1318 return EGL_TRUE; 1319} 1320 1321/** 1322 * This is the main entrypoint into the driver, called by libEGL. 1323 * Create a new _EGLDriver object and init its dispatch table. 1324 */ 1325_EGLDriver * 1326_EGL_MAIN(const char *args) 1327{ 1328 struct dri2_egl_driver *dri2_drv; 1329 1330 (void) args; 1331 1332 dri2_drv = malloc(sizeof *dri2_drv); 1333 if (!dri2_drv) 1334 return NULL; 1335 1336 memset(dri2_drv, 0, sizeof *dri2_drv); 1337 1338 if (!dri2_load(&dri2_drv->base)) 1339 return NULL; 1340 1341 _eglInitDriverFallbacks(&dri2_drv->base); 1342 dri2_drv->base.API.Initialize = dri2_initialize; 1343 dri2_drv->base.API.Terminate = dri2_terminate; 1344 dri2_drv->base.API.CreateContext = dri2_create_context; 1345 dri2_drv->base.API.MakeCurrent = dri2_make_current; 1346 dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; 1347 dri2_drv->base.API.WaitClient = dri2_wait_client; 1348 dri2_drv->base.API.WaitNative = dri2_wait_native; 1349 dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; 1350 dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; 1351 dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; 1352 dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; 1353 dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; 1354 dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; 1355#ifdef HAVE_WAYLAND_PLATFORM 1356 dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; 1357 dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; 1358#endif 1359 1360 dri2_drv->base.Name = "DRI2"; 1361 dri2_drv->base.Unload = dri2_unload; 1362 1363 return &dri2_drv->base; 1364} 1365