egl_dri2.c revision b50703aea55450e04bcd8154335774786e0f253b
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 const unsigned int *rgba_masks) 116{ 117 struct dri2_egl_config *conf; 118 struct dri2_egl_display *dri2_dpy; 119 _EGLConfig base; 120 unsigned int attrib, value, double_buffer; 121 EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; 122 unsigned int dri_masks[4] = { 0, 0, 0, 0 }; 123 _EGLConfig *matching_config; 124 EGLint num_configs = 0; 125 EGLint config_id; 126 int i; 127 128 dri2_dpy = disp->DriverData; 129 _eglInitConfig(&base, disp, id); 130 131 i = 0; 132 double_buffer = 0; 133 bind_to_texture_rgb = 0; 134 bind_to_texture_rgba = 0; 135 136 while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { 137 switch (attrib) { 138 case __DRI_ATTRIB_RENDER_TYPE: 139 if (value & __DRI_ATTRIB_RGBA_BIT) 140 value = EGL_RGB_BUFFER; 141 else if (value & __DRI_ATTRIB_LUMINANCE_BIT) 142 value = EGL_LUMINANCE_BUFFER; 143 else 144 /* not valid */; 145 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); 146 break; 147 148 case __DRI_ATTRIB_CONFIG_CAVEAT: 149 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 150 value = EGL_NON_CONFORMANT_CONFIG; 151 else if (value & __DRI_ATTRIB_SLOW_BIT) 152 value = EGL_SLOW_CONFIG; 153 else 154 value = EGL_NONE; 155 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); 156 break; 157 158 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 159 bind_to_texture_rgb = value; 160 break; 161 162 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 163 bind_to_texture_rgba = value; 164 break; 165 166 case __DRI_ATTRIB_DOUBLE_BUFFER: 167 double_buffer = value; 168 break; 169 170 case __DRI_ATTRIB_RED_MASK: 171 dri_masks[0] = value; 172 break; 173 174 case __DRI_ATTRIB_GREEN_MASK: 175 dri_masks[1] = value; 176 break; 177 178 case __DRI_ATTRIB_BLUE_MASK: 179 dri_masks[2] = value; 180 break; 181 182 case __DRI_ATTRIB_ALPHA_MASK: 183 dri_masks[3] = value; 184 break; 185 186 default: 187 key = dri2_to_egl_attribute_map[attrib]; 188 if (key != 0) 189 _eglSetConfigKey(&base, key, value); 190 break; 191 } 192 } 193 194 if (attr_list) 195 for (i = 0; attr_list[i] != EGL_NONE; i += 2) 196 _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); 197 198 if (depth > 0 && depth != base.BufferSize) 199 return NULL; 200 201 if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks))) 202 return NULL; 203 204 base.NativeRenderable = EGL_TRUE; 205 206 base.SurfaceType = surface_type; 207 if (surface_type & (EGL_PBUFFER_BIT | 208 (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { 209 base.BindToTextureRGB = bind_to_texture_rgb; 210 if (base.AlphaSize > 0) 211 base.BindToTextureRGBA = bind_to_texture_rgba; 212 } 213 214 base.RenderableType = disp->ClientAPIs; 215 base.Conformant = disp->ClientAPIs; 216 217 if (!_eglValidateConfig(&base, EGL_FALSE)) { 218 _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); 219 return NULL; 220 } 221 222 config_id = base.ConfigID; 223 base.ConfigID = EGL_DONT_CARE; 224 base.SurfaceType = EGL_DONT_CARE; 225 num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, 226 (_EGLArrayForEach) dri2_match_config, &base); 227 228 if (num_configs == 1) { 229 conf = (struct dri2_egl_config *) matching_config; 230 231 if (double_buffer && !conf->dri_double_config) 232 conf->dri_double_config = dri_config; 233 else if (!double_buffer && !conf->dri_single_config) 234 conf->dri_single_config = dri_config; 235 else 236 /* a similar config type is already added (unlikely) => discard */ 237 return NULL; 238 } 239 else if (num_configs == 0) { 240 conf = malloc(sizeof *conf); 241 if (conf == NULL) 242 return NULL; 243 244 memcpy(&conf->base, &base, sizeof base); 245 if (double_buffer) { 246 conf->dri_double_config = dri_config; 247 conf->dri_single_config = NULL; 248 } else { 249 conf->dri_single_config = dri_config; 250 conf->dri_double_config = NULL; 251 } 252 conf->base.SurfaceType = 0; 253 conf->base.ConfigID = config_id; 254 255 _eglLinkConfig(&conf->base); 256 } 257 else { 258 assert(0); 259 return NULL; 260 } 261 262 if (double_buffer) { 263 surface_type &= ~EGL_PIXMAP_BIT; 264 265 if (dri2_dpy->swap_available) { 266 conf->base.MinSwapInterval = 0; 267 conf->base.MaxSwapInterval = 1000; /* XXX arbitrary value */ 268 } 269 } 270 271 conf->base.SurfaceType |= surface_type; 272 273 return conf; 274} 275 276__DRIimage * 277dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 278{ 279 _EGLDisplay *disp = data; 280 struct dri2_egl_image *dri2_img; 281 _EGLImage *img; 282 283 (void) screen; 284 285 img = _eglLookupImage(image, disp); 286 if (img == NULL) { 287 _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image"); 288 return NULL; 289 } 290 291 dri2_img = dri2_egl_image(image); 292 293 return dri2_img->dri_image; 294} 295 296const __DRIimageLookupExtension image_lookup_extension = { 297 { __DRI_IMAGE_LOOKUP, 1 }, 298 dri2_lookup_egl_image 299}; 300 301static const char dri_driver_path[] = DEFAULT_DRIVER_DIR; 302 303struct dri2_extension_match { 304 const char *name; 305 int version; 306 int offset; 307}; 308 309static struct dri2_extension_match dri2_driver_extensions[] = { 310 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 311 { __DRI_DRI2, 1, offsetof(struct dri2_egl_display, dri2) }, 312 { NULL, 0, 0 } 313}; 314 315static struct dri2_extension_match dri2_core_extensions[] = { 316 { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, 317 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 318 { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 319 { NULL, 0, 0 } 320}; 321 322static struct dri2_extension_match swrast_driver_extensions[] = { 323 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 324 { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, 325 { NULL } 326}; 327 328static struct dri2_extension_match swrast_core_extensions[] = { 329 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 330 { NULL } 331}; 332 333static EGLBoolean 334dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, 335 struct dri2_extension_match *matches, 336 const __DRIextension **extensions) 337{ 338 int i, j, ret = EGL_TRUE; 339 void *field; 340 341 for (i = 0; extensions[i]; i++) { 342 _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name); 343 for (j = 0; matches[j].name; j++) { 344 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 345 extensions[i]->version >= matches[j].version) { 346 field = ((char *) dri2_dpy + matches[j].offset); 347 *(const __DRIextension **) field = extensions[i]; 348 _eglLog(_EGL_INFO, "DRI2: found extension %s version %d", 349 extensions[i]->name, extensions[i]->version); 350 } 351 } 352 } 353 354 for (j = 0; matches[j].name; j++) { 355 field = ((char *) dri2_dpy + matches[j].offset); 356 if (*(const __DRIextension **) field == NULL) { 357 _eglLog(_EGL_FATAL, "DRI2: did not find extension %s version %d", 358 matches[j].name, matches[j].version); 359 ret = EGL_FALSE; 360 } 361 } 362 363 return ret; 364} 365 366static const __DRIextension ** 367dri2_open_driver(_EGLDisplay *disp) 368{ 369 struct dri2_egl_display *dri2_dpy = disp->DriverData; 370 const __DRIextension **extensions; 371 char path[PATH_MAX], *search_paths, *p, *next, *end; 372 373 search_paths = NULL; 374 if (geteuid() == getuid()) { 375 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 376 search_paths = getenv("LIBGL_DRIVERS_PATH"); 377 } 378 if (search_paths == NULL) 379 search_paths = DEFAULT_DRIVER_DIR; 380 381 dri2_dpy->driver = NULL; 382 end = search_paths + strlen(search_paths); 383 for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) { 384 int len; 385 next = strchr(p, ':'); 386 if (next == NULL) 387 next = end; 388 389 len = next - p; 390#if GLX_USE_TLS 391 snprintf(path, sizeof path, 392 "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name); 393 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 394#endif 395 if (dri2_dpy->driver == NULL) { 396 snprintf(path, sizeof path, 397 "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name); 398 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 399 if (dri2_dpy->driver == NULL) 400 _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror()); 401 } 402 } 403 404 if (dri2_dpy->driver == NULL) { 405 _eglLog(_EGL_WARNING, 406 "DRI2: failed to open %s (search paths %s)", 407 dri2_dpy->driver_name, search_paths); 408 return NULL; 409 } 410 411 _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path); 412 extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS); 413 if (extensions == NULL) { 414 _eglLog(_EGL_WARNING, 415 "DRI2: driver exports no extensions (%s)", dlerror()); 416 dlclose(dri2_dpy->driver); 417 } 418 419 return extensions; 420} 421 422EGLBoolean 423dri2_load_driver(_EGLDisplay *disp) 424{ 425 struct dri2_egl_display *dri2_dpy = disp->DriverData; 426 const __DRIextension **extensions; 427 428 extensions = dri2_open_driver(disp); 429 if (!extensions) 430 return EGL_FALSE; 431 432 if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { 433 dlclose(dri2_dpy->driver); 434 return EGL_FALSE; 435 } 436 437 return EGL_TRUE; 438} 439 440EGLBoolean 441dri2_load_driver_swrast(_EGLDisplay *disp) 442{ 443 struct dri2_egl_display *dri2_dpy = disp->DriverData; 444 const __DRIextension **extensions; 445 446 dri2_dpy->driver_name = "swrast"; 447 extensions = dri2_open_driver(disp); 448 449 if (!extensions) 450 return EGL_FALSE; 451 452 if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) { 453 dlclose(dri2_dpy->driver); 454 return EGL_FALSE; 455 } 456 457 return EGL_TRUE; 458} 459 460void 461dri2_setup_screen(_EGLDisplay *disp) 462{ 463 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 464 unsigned int api_mask; 465 466 if (dri2_dpy->dri2) { 467 if (dri2_dpy->dri2->base.version >= 2) 468 api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 469 else 470 api_mask = 1 << __DRI_API_OPENGL; 471 } else { 472 assert(dri2_dpy->swrast); 473 api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2; 474 } 475 476 disp->ClientAPIs = 0; 477 if (api_mask & (1 <<__DRI_API_OPENGL)) 478 disp->ClientAPIs |= EGL_OPENGL_BIT; 479 if (api_mask & (1 <<__DRI_API_GLES)) 480 disp->ClientAPIs |= EGL_OPENGL_ES_BIT; 481 if (api_mask & (1 << __DRI_API_GLES2)) 482 disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; 483 484 if (dri2_dpy->dri2) { 485 if (dri2_dpy->dri2->base.version >= 2) { 486 disp->Extensions.KHR_surfaceless_context = EGL_TRUE; 487 } 488 } else { 489 assert(dri2_dpy->swrast); 490 disp->Extensions.KHR_surfaceless_context = EGL_TRUE; 491 } 492 493 if (dri2_dpy->image) { 494 disp->Extensions.MESA_drm_image = EGL_TRUE; 495 disp->Extensions.KHR_image_base = EGL_TRUE; 496 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 497 } 498} 499 500EGLBoolean 501dri2_create_screen(_EGLDisplay *disp) 502{ 503 const __DRIextension **extensions; 504 struct dri2_egl_display *dri2_dpy; 505 506 dri2_dpy = disp->DriverData; 507 508 if (dri2_dpy->dri2) { 509 dri2_dpy->dri_screen = 510 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, 511 &dri2_dpy->driver_configs, disp); 512 } else { 513 assert(dri2_dpy->swrast); 514 dri2_dpy->dri_screen = 515 dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, 516 &dri2_dpy->driver_configs, disp); 517 } 518 519 if (dri2_dpy->dri_screen == NULL) { 520 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 521 return EGL_FALSE; 522 } 523 524 dri2_dpy->own_dri_screen = 1; 525 526 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 527 528 if (dri2_dpy->dri2) { 529 if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) 530 goto cleanup_dri_screen; 531 } else { 532 assert(dri2_dpy->swrast); 533 if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) 534 goto cleanup_dri_screen; 535 } 536 537 dri2_setup_screen(disp); 538 539 return EGL_TRUE; 540 541 cleanup_dri_screen: 542 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 543 544 return EGL_FALSE; 545} 546 547/** 548 * Called via eglInitialize(), GLX_drv->API.Initialize(). 549 */ 550static EGLBoolean 551dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) 552{ 553 /* not until swrast_dri is supported */ 554 if (disp->Options.UseFallback) 555 return EGL_FALSE; 556 557 switch (disp->Platform) { 558#ifdef HAVE_X11_PLATFORM 559 case _EGL_PLATFORM_X11: 560 if (disp->Options.TestOnly) 561 return EGL_TRUE; 562 return dri2_initialize_x11(drv, disp); 563#endif 564 565#ifdef HAVE_LIBUDEV 566#ifdef HAVE_DRM_PLATFORM 567 case _EGL_PLATFORM_DRM: 568 if (disp->Options.TestOnly) 569 return EGL_TRUE; 570 return dri2_initialize_drm(drv, disp); 571#endif 572#ifdef HAVE_WAYLAND_PLATFORM 573 case _EGL_PLATFORM_WAYLAND: 574 if (disp->Options.TestOnly) 575 return EGL_TRUE; 576 return dri2_initialize_wayland(drv, disp); 577#endif 578#endif 579#ifdef HAVE_ANDROID_PLATFORM 580 case _EGL_PLATFORM_ANDROID: 581 if (disp->Options.TestOnly) 582 return EGL_TRUE; 583 return dri2_initialize_android(drv, disp); 584#endif 585 586 default: 587 return EGL_FALSE; 588 } 589} 590 591/** 592 * Called via eglTerminate(), drv->API.Terminate(). 593 */ 594static EGLBoolean 595dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 596{ 597 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 598 599 _eglReleaseDisplayResources(drv, disp); 600 _eglCleanupDisplay(disp); 601 602 if (dri2_dpy->own_dri_screen) 603 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 604 if (dri2_dpy->fd) 605 close(dri2_dpy->fd); 606 if (dri2_dpy->driver) 607 dlclose(dri2_dpy->driver); 608 if (dri2_dpy->device_name) 609 free(dri2_dpy->device_name); 610 611 if (disp->PlatformDisplay == NULL) { 612 switch (disp->Platform) { 613#ifdef HAVE_X11_PLATFORM 614 case _EGL_PLATFORM_X11: 615 xcb_disconnect(dri2_dpy->conn); 616 break; 617#endif 618#ifdef HAVE_DRM_PLATFORM 619 case _EGL_PLATFORM_DRM: 620 if (dri2_dpy->own_device) { 621 gbm_device_destroy(&dri2_dpy->gbm_dri->base.base); 622 } 623 break; 624#endif 625 default: 626 break; 627 } 628 } 629 630 free(dri2_dpy); 631 disp->DriverData = NULL; 632 633 return EGL_TRUE; 634} 635 636 637/** 638 * Called via eglCreateContext(), drv->API.CreateContext(). 639 */ 640static _EGLContext * 641dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 642 _EGLContext *share_list, const EGLint *attrib_list) 643{ 644 struct dri2_egl_context *dri2_ctx; 645 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 646 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 647 __DRIcontext *shared = 648 dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; 649 struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 650 const __DRIconfig *dri_config; 651 int api; 652 653 (void) drv; 654 655 dri2_ctx = malloc(sizeof *dri2_ctx); 656 if (!dri2_ctx) { 657 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 658 return NULL; 659 } 660 661 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 662 goto cleanup; 663 664 switch (dri2_ctx->base.ClientAPI) { 665 case EGL_OPENGL_ES_API: 666 switch (dri2_ctx->base.ClientVersion) { 667 case 1: 668 api = __DRI_API_GLES; 669 break; 670 case 2: 671 api = __DRI_API_GLES2; 672 break; 673 default: 674 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 675 return NULL; 676 } 677 break; 678 case EGL_OPENGL_API: 679 api = __DRI_API_OPENGL; 680 break; 681 default: 682 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 683 return NULL; 684 } 685 686 if (conf != NULL) { 687 /* The config chosen here isn't necessarily 688 * used for surfaces later. 689 * A pixmap surface will use the single config. 690 * This opportunity depends on disabling the 691 * doubleBufferMode check in 692 * src/mesa/main/context.c:check_compatible() 693 */ 694 if (dri2_config->dri_double_config) 695 dri_config = dri2_config->dri_double_config; 696 else 697 dri_config = dri2_config->dri_single_config; 698 699 /* EGL_WINDOW_BIT is set only when there is a dri_double_config. This 700 * makes sure the back buffer will always be used. 701 */ 702 if (conf->SurfaceType & EGL_WINDOW_BIT) 703 dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER; 704 } 705 else 706 dri_config = NULL; 707 708 if (dri2_dpy->dri2) { 709 if (dri2_dpy->dri2->base.version >= 2) { 710 dri2_ctx->dri_context = 711 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 712 api, 713 dri_config, 714 shared, 715 dri2_ctx); 716 } else if (api == __DRI_API_OPENGL) { 717 dri2_ctx->dri_context = 718 dri2_dpy->dri2->createNewContext(dri2_dpy->dri_screen, 719 dri_config, 720 shared, 721 dri2_ctx); 722 } else { 723 /* fail */ 724 } 725 } else { 726 assert(dri2_dpy->swrast); 727 dri2_ctx->dri_context = 728 dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 729 api, 730 dri_config, 731 shared, 732 dri2_ctx); 733 } 734 735 if (!dri2_ctx->dri_context) 736 goto cleanup; 737 738 return &dri2_ctx->base; 739 740 cleanup: 741 free(dri2_ctx); 742 return NULL; 743} 744 745/** 746 * Called via eglDestroyContext(), drv->API.DestroyContext(). 747 */ 748static EGLBoolean 749dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 750{ 751 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 752 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 753 754 if (_eglPutContext(ctx)) { 755 dri2_dpy->core->destroyContext(dri2_ctx->dri_context); 756 free(dri2_ctx); 757 } 758 759 return EGL_TRUE; 760} 761 762/** 763 * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 764 */ 765static EGLBoolean 766dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 767 _EGLSurface *rsurf, _EGLContext *ctx) 768{ 769 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 770 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 771 struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); 772 struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); 773 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 774 _EGLContext *old_ctx; 775 _EGLSurface *old_dsurf, *old_rsurf; 776 __DRIdrawable *ddraw, *rdraw; 777 __DRIcontext *cctx; 778 779 /* make new bindings */ 780 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 781 return EGL_FALSE; 782 783 /* flush before context switch */ 784 if (old_ctx && dri2_drv->glFlush) 785 dri2_drv->glFlush(); 786 787 ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; 788 rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; 789 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 790 791 if (old_ctx) { 792 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 793 dri2_dpy->core->unbindContext(old_cctx); 794 } 795 796 if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || 797 dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 798 if (old_dsurf) 799 drv->API.DestroySurface(drv, disp, old_dsurf); 800 if (old_rsurf) 801 drv->API.DestroySurface(drv, disp, old_rsurf); 802 if (old_ctx) 803 drv->API.DestroyContext(drv, disp, old_ctx); 804 805 return EGL_TRUE; 806 } else { 807 /* undo the previous _eglBindContext */ 808 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); 809 assert(&dri2_ctx->base == ctx && 810 &dri2_dsurf->base == dsurf && 811 &dri2_rsurf->base == rsurf); 812 813 _eglPutSurface(dsurf); 814 _eglPutSurface(rsurf); 815 _eglPutContext(ctx); 816 817 _eglPutSurface(old_dsurf); 818 _eglPutSurface(old_rsurf); 819 _eglPutContext(old_ctx); 820 821 return EGL_FALSE; 822 } 823} 824 825/* 826 * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 827 */ 828static _EGLProc 829dri2_get_proc_address(_EGLDriver *drv, const char *procname) 830{ 831 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 832 833 return dri2_drv->get_proc_address(procname); 834} 835 836static EGLBoolean 837dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 838{ 839 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 840 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); 841 842 (void) drv; 843 844 /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 845 * we need to copy fake to real here.*/ 846 847 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 848 849 return EGL_TRUE; 850} 851 852static EGLBoolean 853dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) 854{ 855 (void) drv; 856 (void) disp; 857 858 if (engine != EGL_CORE_NATIVE_ENGINE) 859 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 860 /* glXWaitX(); */ 861 862 return EGL_TRUE; 863} 864 865static EGLBoolean 866dri2_bind_tex_image(_EGLDriver *drv, 867 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 868{ 869 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 870 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 871 struct dri2_egl_context *dri2_ctx; 872 _EGLContext *ctx; 873 GLint format, target; 874 875 ctx = _eglGetCurrentContext(); 876 dri2_ctx = dri2_egl_context(ctx); 877 878 if (!_eglBindTexImage(drv, disp, surf, buffer)) 879 return EGL_FALSE; 880 881 switch (dri2_surf->base.TextureFormat) { 882 case EGL_TEXTURE_RGB: 883 format = __DRI_TEXTURE_FORMAT_RGB; 884 break; 885 case EGL_TEXTURE_RGBA: 886 format = __DRI_TEXTURE_FORMAT_RGBA; 887 break; 888 default: 889 assert(0); 890 } 891 892 switch (dri2_surf->base.TextureTarget) { 893 case EGL_TEXTURE_2D: 894 target = GL_TEXTURE_2D; 895 break; 896 default: 897 assert(0); 898 } 899 900 (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context, 901 target, format, 902 dri2_surf->dri_drawable); 903 904 return EGL_TRUE; 905} 906 907static EGLBoolean 908dri2_release_tex_image(_EGLDriver *drv, 909 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 910{ 911#if __DRI_TEX_BUFFER_VERSION >= 3 912 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 913 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 914 struct dri2_egl_context *dri2_ctx; 915 _EGLContext *ctx; 916 GLint target; 917 918 ctx = _eglGetCurrentContext(); 919 dri2_ctx = dri2_egl_context(ctx); 920 921 if (!_eglReleaseTexImage(drv, disp, surf, buffer)) 922 return EGL_FALSE; 923 924 switch (dri2_surf->base.TextureTarget) { 925 case EGL_TEXTURE_2D: 926 target = GL_TEXTURE_2D; 927 break; 928 default: 929 assert(0); 930 } 931 if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL) 932 (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context, 933 target, 934 dri2_surf->dri_drawable); 935#endif 936 937 return EGL_TRUE; 938} 939 940static _EGLImage * 941dri2_create_image(_EGLDisplay *disp, __DRIimage *dri_image) 942{ 943 struct dri2_egl_image *dri2_img; 944 945 if (dri_image == NULL) { 946 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 947 return NULL; 948 } 949 950 dri2_img = malloc(sizeof *dri2_img); 951 if (!dri2_img) { 952 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 953 return NULL; 954 } 955 956 if (!_eglInitImage(&dri2_img->base, disp)) { 957 free(dri2_img); 958 return NULL; 959 } 960 961 dri2_img->dri_image = dri_image; 962 963 return &dri2_img->base; 964} 965 966static _EGLImage * 967dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 968 EGLClientBuffer buffer, 969 const EGLint *attr_list) 970{ 971 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 972 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 973 GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 974 __DRIimage *dri_image; 975 976 if (renderbuffer == 0) { 977 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 978 return EGL_NO_IMAGE_KHR; 979 } 980 981 dri_image = 982 dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, 983 renderbuffer, NULL); 984 985 return dri2_create_image(disp, dri_image); 986} 987 988static _EGLImage * 989dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 990 EGLClientBuffer buffer, const EGLint *attr_list) 991{ 992 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 993 EGLint format, name, pitch, err; 994 _EGLImageAttribs attrs; 995 __DRIimage *dri_image; 996 997 name = (EGLint) (uintptr_t) buffer; 998 999 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1000 if (err != EGL_SUCCESS) 1001 return NULL; 1002 1003 if (attrs.Width <= 0 || attrs.Height <= 0 || 1004 attrs.DRMBufferStrideMESA <= 0) { 1005 _eglError(EGL_BAD_PARAMETER, 1006 "bad width, height or stride"); 1007 return NULL; 1008 } 1009 1010 switch (attrs.DRMBufferFormatMESA) { 1011 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1012 format = __DRI_IMAGE_FORMAT_ARGB8888; 1013 pitch = attrs.DRMBufferStrideMESA; 1014 break; 1015 default: 1016 _eglError(EGL_BAD_PARAMETER, 1017 "dri2_create_image_khr: unsupported pixmap depth"); 1018 return NULL; 1019 } 1020 1021 dri_image = 1022 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1023 attrs.Width, 1024 attrs.Height, 1025 format, 1026 name, 1027 pitch, 1028 NULL); 1029 1030 return dri2_create_image(disp, dri_image); 1031} 1032 1033#ifdef HAVE_WAYLAND_PLATFORM 1034 1035/* This structure describes how a wl_buffer maps to one or more 1036 * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the 1037 * offsets and strides of the planes in the buffer. This table maps a 1038 * wl_drm format code to a description of the planes in the buffer 1039 * that lets us create a __DRIimage for each of the planes. */ 1040 1041static const struct wl_drm_format_descriptor { 1042 uint32_t wl_format; 1043 EGLint components; 1044 int nplanes; 1045 struct { 1046 int buffer_index; 1047 int width_shift; 1048 int height_shift; 1049 uint32_t dri_format; 1050 int cpp; 1051 } planes[3]; 1052} wl_drm_formats[] = { 1053 { WL_DRM_FORMAT_ARGB8888, EGL_TEXTURE_RGBA, 1, 1054 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 }, } }, 1055 1056 { WL_DRM_FORMAT_XRGB8888, EGL_TEXTURE_RGB, 1, 1057 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } }, 1058 1059 { WL_DRM_FORMAT_YUV410, EGL_TEXTURE_Y_U_V_WL, 3, 1060 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1061 { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, 1062 { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1063 1064 { WL_DRM_FORMAT_YUV411, EGL_TEXTURE_Y_U_V_WL, 3, 1065 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1066 { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1067 { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1068 1069 { WL_DRM_FORMAT_YUV420, EGL_TEXTURE_Y_U_V_WL, 3, 1070 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1071 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, 1072 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1073 1074 { WL_DRM_FORMAT_YUV422, EGL_TEXTURE_Y_U_V_WL, 3, 1075 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1076 { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1077 { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1078 1079 { WL_DRM_FORMAT_YUV444, EGL_TEXTURE_Y_U_V_WL, 3, 1080 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1081 { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1082 { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1083 1084 { WL_DRM_FORMAT_NV12, EGL_TEXTURE_Y_UV_WL, 2, 1085 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1086 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } }, 1087 1088 { WL_DRM_FORMAT_NV16, EGL_TEXTURE_Y_UV_WL, 2, 1089 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1090 { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } }, 1091 1092 /* For YUYV buffers, we set up two overlapping DRI images and treat 1093 * them as planar buffers in the compositors. Plane 0 is GR88 and 1094 * samples YU or YV pairs and places Y into the R component, while 1095 * plane 1 is ARGB and samples YUYV clusters and places pairs and 1096 * places U into the G component and V into A. This lets the 1097 * texture sampler interpolate the Y components correctly when 1098 * sampling from plane 0, and interpolate U and V correctly when 1099 * sampling from plane 1. */ 1100 { WL_DRM_FORMAT_YUYV, EGL_TEXTURE_Y_XUXV_WL, 2, 1101 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, 1102 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } } 1103}; 1104 1105static _EGLImage * 1106dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1107 EGLClientBuffer _buffer, 1108 const EGLint *attr_list) 1109{ 1110 struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; 1111 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1112 __DRIimage *dri_image; 1113 _EGLImageAttribs attrs; 1114 EGLint err; 1115 uint32_t format; 1116 int32_t offset, stride, plane, width, height; 1117 int cpp, index; 1118 const struct wl_drm_format_descriptor *f; 1119 1120 if (!wayland_buffer_is_drm(&buffer->buffer)) 1121 return NULL; 1122 1123 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1124 plane = attrs.PlaneWL; 1125 if (err != EGL_SUCCESS) { 1126 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 1127 return NULL; 1128 } 1129 1130 f = buffer->driver_format; 1131 if (plane < 0 || plane >= f->nplanes) { 1132 _eglError(EGL_BAD_PARAMETER, 1133 "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); 1134 return NULL; 1135 } 1136 1137 width = buffer->buffer.width >> f->planes[plane].width_shift; 1138 height = buffer->buffer.height >> f->planes[plane].height_shift; 1139 format = f->planes[plane].dri_format; 1140 cpp = f->planes[plane].cpp; 1141 index = f->planes[plane].buffer_index; 1142 offset = buffer->offset[index]; 1143 stride = buffer->stride[index]; 1144 1145 dri_image = dri2_dpy->image->createSubImage(buffer->driver_buffer, 1146 width, height, format, 1147 offset, stride / cpp, NULL); 1148 1149 return dri2_create_image(disp, dri_image); 1150} 1151#endif 1152 1153_EGLImage * 1154dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 1155 _EGLContext *ctx, EGLenum target, 1156 EGLClientBuffer buffer, const EGLint *attr_list) 1157{ 1158 (void) drv; 1159 1160 switch (target) { 1161 case EGL_GL_RENDERBUFFER_KHR: 1162 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 1163 case EGL_DRM_BUFFER_MESA: 1164 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 1165#ifdef HAVE_WAYLAND_PLATFORM 1166 case EGL_WAYLAND_BUFFER_WL: 1167 return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 1168#endif 1169 default: 1170 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1171 return EGL_NO_IMAGE_KHR; 1172 } 1173} 1174 1175static EGLBoolean 1176dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) 1177{ 1178 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1179 struct dri2_egl_image *dri2_img = dri2_egl_image(image); 1180 1181 (void) drv; 1182 1183 dri2_dpy->image->destroyImage(dri2_img->dri_image); 1184 free(dri2_img); 1185 1186 return EGL_TRUE; 1187} 1188 1189static _EGLImage * 1190dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, 1191 const EGLint *attr_list) 1192{ 1193 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1194 struct dri2_egl_image *dri2_img; 1195 _EGLImageAttribs attrs; 1196 unsigned int dri_use, valid_mask; 1197 int format; 1198 EGLint err = EGL_SUCCESS; 1199 1200 (void) drv; 1201 1202 dri2_img = malloc(sizeof *dri2_img); 1203 if (!dri2_img) { 1204 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1205 return EGL_NO_IMAGE_KHR; 1206 } 1207 1208 if (!attr_list) { 1209 err = EGL_BAD_PARAMETER; 1210 goto cleanup_img; 1211 } 1212 1213 if (!_eglInitImage(&dri2_img->base, disp)) { 1214 err = EGL_BAD_PARAMETER; 1215 goto cleanup_img; 1216 } 1217 1218 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1219 if (err != EGL_SUCCESS) 1220 goto cleanup_img; 1221 1222 if (attrs.Width <= 0 || attrs.Height <= 0) { 1223 _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", 1224 attrs.Width, attrs.Height); 1225 goto cleanup_img; 1226 } 1227 1228 switch (attrs.DRMBufferFormatMESA) { 1229 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1230 format = __DRI_IMAGE_FORMAT_ARGB8888; 1231 break; 1232 default: 1233 _eglLog(_EGL_WARNING, "bad image format value 0x%04x", 1234 attrs.DRMBufferFormatMESA); 1235 goto cleanup_img; 1236 } 1237 1238 valid_mask = 1239 EGL_DRM_BUFFER_USE_SCANOUT_MESA | 1240 EGL_DRM_BUFFER_USE_SHARE_MESA | 1241 EGL_DRM_BUFFER_USE_CURSOR_MESA; 1242 if (attrs.DRMBufferUseMESA & ~valid_mask) { 1243 _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", 1244 attrs.DRMBufferUseMESA & ~valid_mask); 1245 goto cleanup_img; 1246 } 1247 1248 dri_use = 0; 1249 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 1250 dri_use |= __DRI_IMAGE_USE_SHARE; 1251 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 1252 dri_use |= __DRI_IMAGE_USE_SCANOUT; 1253 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 1254 dri_use |= __DRI_IMAGE_USE_CURSOR; 1255 1256 dri2_img->dri_image = 1257 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 1258 attrs.Width, attrs.Height, 1259 format, dri_use, dri2_img); 1260 if (dri2_img->dri_image == NULL) { 1261 err = EGL_BAD_ALLOC; 1262 goto cleanup_img; 1263 } 1264 1265 return &dri2_img->base; 1266 1267 cleanup_img: 1268 free(dri2_img); 1269 _eglError(err, "dri2_create_drm_image_mesa"); 1270 1271 return EGL_NO_IMAGE_KHR; 1272} 1273 1274static EGLBoolean 1275dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 1276 EGLint *name, EGLint *handle, EGLint *stride) 1277{ 1278 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1279 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 1280 1281 (void) drv; 1282 1283 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 1284 __DRI_IMAGE_ATTRIB_NAME, name)) { 1285 _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 1286 return EGL_FALSE; 1287 } 1288 1289 if (handle) 1290 dri2_dpy->image->queryImage(dri2_img->dri_image, 1291 __DRI_IMAGE_ATTRIB_HANDLE, handle); 1292 1293 if (stride) 1294 dri2_dpy->image->queryImage(dri2_img->dri_image, 1295 __DRI_IMAGE_ATTRIB_STRIDE, stride); 1296 1297 return EGL_TRUE; 1298} 1299 1300#ifdef HAVE_WAYLAND_PLATFORM 1301 1302static void 1303dri2_wl_reference_buffer(void *user_data, uint32_t name, 1304 struct wl_drm_buffer *buffer) 1305{ 1306 _EGLDisplay *disp = user_data; 1307 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1308 int i; 1309 1310 for (i = 0; i < ARRAY_SIZE(wl_drm_formats); i++) 1311 if (wl_drm_formats[i].wl_format == buffer->format) { 1312 buffer->driver_format = &wl_drm_formats[i]; 1313 break; 1314 } 1315 1316 if (buffer->driver_format == NULL) 1317 return; 1318 1319 buffer->driver_buffer = 1320 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1321 buffer->buffer.width, 1322 buffer->buffer.height, 1323 __DRI_IMAGE_FORMAT_NONE, name, 1324 buffer->stride[0] / 4, 1325 NULL); 1326} 1327 1328static void 1329dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) 1330{ 1331 _EGLDisplay *disp = user_data; 1332 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1333 1334 dri2_dpy->image->destroyImage(buffer->driver_buffer); 1335} 1336 1337static struct wayland_drm_callbacks wl_drm_callbacks = { 1338 .authenticate = NULL, 1339 .reference_buffer = dri2_wl_reference_buffer, 1340 .release_buffer = dri2_wl_release_buffer 1341}; 1342 1343static EGLBoolean 1344dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1345 struct wl_display *wl_dpy) 1346{ 1347 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1348 1349 (void) drv; 1350 1351 if (dri2_dpy->wl_server_drm) 1352 return EGL_FALSE; 1353 1354 wl_drm_callbacks.authenticate = 1355 (int(*)(void *, uint32_t)) dri2_dpy->authenticate; 1356 1357 dri2_dpy->wl_server_drm = 1358 wayland_drm_init(wl_dpy, dri2_dpy->device_name, 1359 &wl_drm_callbacks, disp); 1360 1361 if (!dri2_dpy->wl_server_drm) 1362 return EGL_FALSE; 1363 1364 return EGL_TRUE; 1365} 1366 1367static EGLBoolean 1368dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1369 struct wl_display *wl_dpy) 1370{ 1371 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1372 1373 (void) drv; 1374 1375 if (!dri2_dpy->wl_server_drm) 1376 return EGL_FALSE; 1377 1378 wayland_drm_uninit(dri2_dpy->wl_server_drm); 1379 dri2_dpy->wl_server_drm = NULL; 1380 1381 return EGL_TRUE; 1382} 1383 1384static EGLBoolean 1385dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp, 1386 struct wl_buffer *_buffer, 1387 EGLint attribute, EGLint *value) 1388{ 1389 struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; 1390 const struct wl_drm_format_descriptor *format; 1391 1392 if (!wayland_buffer_is_drm(&buffer->buffer)) 1393 return EGL_FALSE; 1394 1395 format = buffer->driver_format; 1396 switch (attribute) { 1397 case EGL_TEXTURE_FORMAT: 1398 *value = format->components; 1399 return EGL_TRUE; 1400 case EGL_WIDTH: 1401 *value = buffer->buffer.width; 1402 break; 1403 case EGL_HEIGHT: 1404 *value = buffer->buffer.height; 1405 break; 1406 } 1407 1408 return EGL_FALSE; 1409} 1410#endif 1411 1412static void 1413dri2_unload(_EGLDriver *drv) 1414{ 1415 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1416 1417 if (dri2_drv->handle) 1418 dlclose(dri2_drv->handle); 1419 free(dri2_drv); 1420} 1421 1422static EGLBoolean 1423dri2_load(_EGLDriver *drv) 1424{ 1425 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1426#ifdef HAVE_SHARED_GLAPI 1427#ifdef HAVE_ANDROID_PLATFORM 1428 const char *libname = "libglapi.so"; 1429#else 1430 const char *libname = "libglapi.so.0"; 1431#endif 1432#else 1433 /* 1434 * Both libGL.so and libglapi.so are glapi providers. There is no way to 1435 * tell which one to load. 1436 */ 1437 const char *libname = NULL; 1438#endif 1439 void *handle; 1440 1441 /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */ 1442 handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); 1443 if (handle) { 1444 dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) 1445 dlsym(handle, "_glapi_get_proc_address"); 1446 if (!dri2_drv->get_proc_address || !libname) { 1447 /* no need to keep a reference */ 1448 dlclose(handle); 1449 handle = NULL; 1450 } 1451 } 1452 1453 /* if glapi is not available, loading DRI drivers will fail */ 1454 if (!dri2_drv->get_proc_address) { 1455 _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); 1456 return EGL_FALSE; 1457 } 1458 1459 dri2_drv->glFlush = (void (*)(void)) 1460 dri2_drv->get_proc_address("glFlush"); 1461 1462 dri2_drv->handle = handle; 1463 1464 return EGL_TRUE; 1465} 1466 1467/** 1468 * This is the main entrypoint into the driver, called by libEGL. 1469 * Create a new _EGLDriver object and init its dispatch table. 1470 */ 1471_EGLDriver * 1472_eglBuiltInDriverDRI2(const char *args) 1473{ 1474 struct dri2_egl_driver *dri2_drv; 1475 1476 (void) args; 1477 1478 dri2_drv = malloc(sizeof *dri2_drv); 1479 if (!dri2_drv) 1480 return NULL; 1481 1482 memset(dri2_drv, 0, sizeof *dri2_drv); 1483 1484 if (!dri2_load(&dri2_drv->base)) { 1485 free(dri2_drv); 1486 return NULL; 1487 } 1488 1489 _eglInitDriverFallbacks(&dri2_drv->base); 1490 dri2_drv->base.API.Initialize = dri2_initialize; 1491 dri2_drv->base.API.Terminate = dri2_terminate; 1492 dri2_drv->base.API.CreateContext = dri2_create_context; 1493 dri2_drv->base.API.DestroyContext = dri2_destroy_context; 1494 dri2_drv->base.API.MakeCurrent = dri2_make_current; 1495 dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; 1496 dri2_drv->base.API.WaitClient = dri2_wait_client; 1497 dri2_drv->base.API.WaitNative = dri2_wait_native; 1498 dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; 1499 dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; 1500 dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; 1501 dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; 1502 dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; 1503 dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; 1504#ifdef HAVE_WAYLAND_PLATFORM 1505 dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; 1506 dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; 1507 dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; 1508#endif 1509 1510 dri2_drv->base.Name = "DRI2"; 1511 dri2_drv->base.Unload = dri2_unload; 1512 1513 return &dri2_drv->base; 1514} 1515