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, 2, 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, 0, 0 } 326}; 327 328static struct dri2_extension_match swrast_core_extensions[] = { 329 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 330 { NULL, 0, 0 } 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 api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 468 } else { 469 assert(dri2_dpy->swrast); 470 api_mask = 1 << __DRI_API_OPENGL | 1 << __DRI_API_GLES | 1 << __DRI_API_GLES2; 471 } 472 473 disp->ClientAPIs = 0; 474 if (api_mask & (1 <<__DRI_API_OPENGL)) 475 disp->ClientAPIs |= EGL_OPENGL_BIT; 476 if (api_mask & (1 <<__DRI_API_GLES)) 477 disp->ClientAPIs |= EGL_OPENGL_ES_BIT; 478 if (api_mask & (1 << __DRI_API_GLES2)) 479 disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; 480 481 assert(dri2_dpy->dri2 || dri2_dpy->swrast); 482 disp->Extensions.KHR_surfaceless_context = EGL_TRUE; 483 484 if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) { 485 disp->Extensions.KHR_create_context = EGL_TRUE; 486 487 if (dri2_dpy->robustness) 488 disp->Extensions.EXT_create_context_robustness = EGL_TRUE; 489 } 490 491 if (dri2_dpy->image) { 492 disp->Extensions.MESA_drm_image = EGL_TRUE; 493 disp->Extensions.KHR_image_base = EGL_TRUE; 494 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 495 } 496} 497 498EGLBoolean 499dri2_create_screen(_EGLDisplay *disp) 500{ 501 const __DRIextension **extensions; 502 struct dri2_egl_display *dri2_dpy; 503 504 dri2_dpy = disp->DriverData; 505 506 if (dri2_dpy->dri2) { 507 dri2_dpy->dri_screen = 508 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions, 509 &dri2_dpy->driver_configs, disp); 510 } else { 511 assert(dri2_dpy->swrast); 512 dri2_dpy->dri_screen = 513 dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, 514 &dri2_dpy->driver_configs, disp); 515 } 516 517 if (dri2_dpy->dri_screen == NULL) { 518 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 519 return EGL_FALSE; 520 } 521 522 dri2_dpy->own_dri_screen = 1; 523 524 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 525 526 if (dri2_dpy->dri2) { 527 unsigned i; 528 529 if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) 530 goto cleanup_dri_screen; 531 532 for (i = 0; extensions[i]; i++) { 533 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) { 534 dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i]; 535 } 536 } 537 } else { 538 assert(dri2_dpy->swrast); 539 if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) 540 goto cleanup_dri_screen; 541 } 542 543 dri2_setup_screen(disp); 544 545 return EGL_TRUE; 546 547 cleanup_dri_screen: 548 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 549 550 return EGL_FALSE; 551} 552 553/** 554 * Called via eglInitialize(), GLX_drv->API.Initialize(). 555 */ 556static EGLBoolean 557dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) 558{ 559 /* not until swrast_dri is supported */ 560 if (disp->Options.UseFallback) 561 return EGL_FALSE; 562 563 switch (disp->Platform) { 564#ifdef HAVE_X11_PLATFORM 565 case _EGL_PLATFORM_X11: 566 if (disp->Options.TestOnly) 567 return EGL_TRUE; 568 return dri2_initialize_x11(drv, disp); 569#endif 570 571#ifdef HAVE_LIBUDEV 572#ifdef HAVE_DRM_PLATFORM 573 case _EGL_PLATFORM_DRM: 574 if (disp->Options.TestOnly) 575 return EGL_TRUE; 576 return dri2_initialize_drm(drv, disp); 577#endif 578#ifdef HAVE_WAYLAND_PLATFORM 579 case _EGL_PLATFORM_WAYLAND: 580 if (disp->Options.TestOnly) 581 return EGL_TRUE; 582 return dri2_initialize_wayland(drv, disp); 583#endif 584#endif 585#ifdef HAVE_ANDROID_PLATFORM 586 case _EGL_PLATFORM_ANDROID: 587 if (disp->Options.TestOnly) 588 return EGL_TRUE; 589 return dri2_initialize_android(drv, disp); 590#endif 591 592 default: 593 return EGL_FALSE; 594 } 595} 596 597/** 598 * Called via eglTerminate(), drv->API.Terminate(). 599 */ 600static EGLBoolean 601dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 602{ 603 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 604 605 _eglReleaseDisplayResources(drv, disp); 606 _eglCleanupDisplay(disp); 607 608 if (dri2_dpy->own_dri_screen) 609 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 610 if (dri2_dpy->fd) 611 close(dri2_dpy->fd); 612 if (dri2_dpy->driver) 613 dlclose(dri2_dpy->driver); 614 if (dri2_dpy->device_name) 615 free(dri2_dpy->device_name); 616 617 if (disp->PlatformDisplay == NULL) { 618 switch (disp->Platform) { 619#ifdef HAVE_X11_PLATFORM 620 case _EGL_PLATFORM_X11: 621 xcb_disconnect(dri2_dpy->conn); 622 break; 623#endif 624#ifdef HAVE_DRM_PLATFORM 625 case _EGL_PLATFORM_DRM: 626 if (dri2_dpy->own_device) { 627 gbm_device_destroy(&dri2_dpy->gbm_dri->base.base); 628 } 629 break; 630#endif 631 default: 632 break; 633 } 634 } 635 636 free(dri2_dpy); 637 disp->DriverData = NULL; 638 639 return EGL_TRUE; 640} 641 642/** 643 * Set the error code after a call to 644 * dri2_egl_display::dri2::createContextAttribs. 645 */ 646static void 647dri2_create_context_attribs_error(int dri_error) 648{ 649 EGLint egl_error; 650 651 switch (dri_error) { 652 case __DRI_CTX_ERROR_SUCCESS: 653 return; 654 655 case __DRI_CTX_ERROR_NO_MEMORY: 656 egl_error = EGL_BAD_ALLOC; 657 break; 658 659 /* From the EGL_KHR_create_context spec, section "Errors": 660 * 661 * * If <config> does not support a client API context compatible 662 * with the requested API major and minor version, [...] context flags, 663 * and context reset notification behavior (for client API types where 664 * these attributes are supported), then an EGL_BAD_MATCH error is 665 * generated. 666 * 667 * * If an OpenGL ES context is requested and the values for 668 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 669 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 670 * is not defined, than an EGL_BAD_MATCH error is generated. 671 * 672 * * If an OpenGL context is requested, the requested version is 673 * greater than 3.2, and the value for attribute 674 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any 675 * bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and 676 * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than 677 * one of these bits set; or if the implementation does not support 678 * the requested profile, then an EGL_BAD_MATCH error is generated. 679 */ 680 case __DRI_CTX_ERROR_BAD_API: 681 case __DRI_CTX_ERROR_BAD_VERSION: 682 case __DRI_CTX_ERROR_BAD_FLAG: 683 egl_error = EGL_BAD_MATCH; 684 break; 685 686 /* From the EGL_KHR_create_context spec, section "Errors": 687 * 688 * * If an attribute name or attribute value in <attrib_list> is not 689 * recognized (including unrecognized bits in bitmask attributes), 690 * then an EGL_BAD_ATTRIBUTE error is generated." 691 */ 692 case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE: 693 case __DRI_CTX_ERROR_UNKNOWN_FLAG: 694 egl_error = EGL_BAD_ATTRIBUTE; 695 break; 696 697 default: 698 assert(0); 699 egl_error = EGL_BAD_MATCH; 700 break; 701 } 702 703 _eglError(egl_error, "dri2_create_context"); 704} 705 706/** 707 * Called via eglCreateContext(), drv->API.CreateContext(). 708 */ 709static _EGLContext * 710dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 711 _EGLContext *share_list, const EGLint *attrib_list) 712{ 713 struct dri2_egl_context *dri2_ctx; 714 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 715 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 716 __DRIcontext *shared = 717 dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; 718 struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 719 const __DRIconfig *dri_config; 720 int api; 721 722 (void) drv; 723 724 dri2_ctx = malloc(sizeof *dri2_ctx); 725 if (!dri2_ctx) { 726 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 727 return NULL; 728 } 729 730 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 731 goto cleanup; 732 733 switch (dri2_ctx->base.ClientAPI) { 734 case EGL_OPENGL_ES_API: 735 switch (dri2_ctx->base.ClientMajorVersion) { 736 case 1: 737 api = __DRI_API_GLES; 738 break; 739 case 2: 740 case 3: 741 api = __DRI_API_GLES2; 742 break; 743 default: 744 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 745 return NULL; 746 } 747 break; 748 case EGL_OPENGL_API: 749 if ((dri2_ctx->base.ClientMajorVersion >= 4 750 || (dri2_ctx->base.ClientMajorVersion == 3 751 && dri2_ctx->base.ClientMinorVersion >= 2)) 752 && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) 753 api = __DRI_API_OPENGL_CORE; 754 else 755 api = __DRI_API_OPENGL; 756 break; 757 default: 758 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 759 return NULL; 760 } 761 762 if (conf != NULL) { 763 /* The config chosen here isn't necessarily 764 * used for surfaces later. 765 * A pixmap surface will use the single config. 766 * This opportunity depends on disabling the 767 * doubleBufferMode check in 768 * src/mesa/main/context.c:check_compatible() 769 */ 770 if (dri2_config->dri_double_config) 771 dri_config = dri2_config->dri_double_config; 772 else 773 dri_config = dri2_config->dri_single_config; 774 775 /* EGL_WINDOW_BIT is set only when there is a dri_double_config. This 776 * makes sure the back buffer will always be used. 777 */ 778 if (conf->SurfaceType & EGL_WINDOW_BIT) 779 dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER; 780 } 781 else 782 dri_config = NULL; 783 784 if (dri2_dpy->dri2) { 785 if (dri2_dpy->dri2->base.version >= 3) { 786 unsigned error; 787 unsigned num_attribs = 0; 788 uint32_t ctx_attribs[8]; 789 790 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 791 ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion; 792 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 793 ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion; 794 795 if (dri2_ctx->base.Flags != 0) { 796 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 797 * extension, don't even try to send it the robust-access flag. 798 * It may explode. Instead, generate the required EGL error here. 799 */ 800 if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0 801 && !dri2_dpy->robustness) { 802 _eglError(EGL_BAD_MATCH, "eglCreateContext"); 803 goto cleanup; 804 } 805 806 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS; 807 ctx_attribs[num_attribs++] = dri2_ctx->base.Flags; 808 } 809 810 if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) { 811 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 812 * extension, don't even try to send it a reset strategy. It may 813 * explode. Instead, generate the required EGL error here. 814 */ 815 if (!dri2_dpy->robustness) { 816 _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 817 goto cleanup; 818 } 819 820 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 821 ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT; 822 } 823 824 assert(num_attribs <= ARRAY_SIZE(ctx_attribs)); 825 826 dri2_ctx->dri_context = 827 dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen, 828 api, 829 dri_config, 830 shared, 831 num_attribs / 2, 832 ctx_attribs, 833 & error, 834 dri2_ctx); 835 dri2_create_context_attribs_error(error); 836 } else { 837 dri2_ctx->dri_context = 838 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 839 api, 840 dri_config, 841 shared, 842 dri2_ctx); 843 } 844 } else { 845 assert(dri2_dpy->swrast); 846 dri2_ctx->dri_context = 847 dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 848 api, 849 dri_config, 850 shared, 851 dri2_ctx); 852 } 853 854 if (!dri2_ctx->dri_context) 855 goto cleanup; 856 857 return &dri2_ctx->base; 858 859 cleanup: 860 free(dri2_ctx); 861 return NULL; 862} 863 864/** 865 * Called via eglDestroyContext(), drv->API.DestroyContext(). 866 */ 867static EGLBoolean 868dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 869{ 870 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 871 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 872 873 if (_eglPutContext(ctx)) { 874 dri2_dpy->core->destroyContext(dri2_ctx->dri_context); 875 free(dri2_ctx); 876 } 877 878 return EGL_TRUE; 879} 880 881/** 882 * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 883 */ 884static EGLBoolean 885dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 886 _EGLSurface *rsurf, _EGLContext *ctx) 887{ 888 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 889 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 890 struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); 891 struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); 892 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 893 _EGLContext *old_ctx; 894 _EGLSurface *old_dsurf, *old_rsurf; 895 __DRIdrawable *ddraw, *rdraw; 896 __DRIcontext *cctx; 897 898 /* make new bindings */ 899 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 900 return EGL_FALSE; 901 902 /* flush before context switch */ 903 if (old_ctx && dri2_drv->glFlush) 904 dri2_drv->glFlush(); 905 906 ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; 907 rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; 908 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 909 910 if (old_ctx) { 911 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 912 dri2_dpy->core->unbindContext(old_cctx); 913 } 914 915 if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || 916 dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 917 if (old_dsurf) 918 drv->API.DestroySurface(drv, disp, old_dsurf); 919 if (old_rsurf) 920 drv->API.DestroySurface(drv, disp, old_rsurf); 921 if (old_ctx) 922 drv->API.DestroyContext(drv, disp, old_ctx); 923 924 return EGL_TRUE; 925 } else { 926 /* undo the previous _eglBindContext */ 927 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); 928 assert(&dri2_ctx->base == ctx && 929 &dri2_dsurf->base == dsurf && 930 &dri2_rsurf->base == rsurf); 931 932 _eglPutSurface(dsurf); 933 _eglPutSurface(rsurf); 934 _eglPutContext(ctx); 935 936 _eglPutSurface(old_dsurf); 937 _eglPutSurface(old_rsurf); 938 _eglPutContext(old_ctx); 939 940 return EGL_FALSE; 941 } 942} 943 944/* 945 * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 946 */ 947static _EGLProc 948dri2_get_proc_address(_EGLDriver *drv, const char *procname) 949{ 950 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 951 952 return dri2_drv->get_proc_address(procname); 953} 954 955static EGLBoolean 956dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 957{ 958 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 959 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); 960 961 (void) drv; 962 963 /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 964 * we need to copy fake to real here.*/ 965 966 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 967 968 return EGL_TRUE; 969} 970 971static EGLBoolean 972dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) 973{ 974 (void) drv; 975 (void) disp; 976 977 if (engine != EGL_CORE_NATIVE_ENGINE) 978 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 979 /* glXWaitX(); */ 980 981 return EGL_TRUE; 982} 983 984static EGLBoolean 985dri2_bind_tex_image(_EGLDriver *drv, 986 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 987{ 988 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 989 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 990 struct dri2_egl_context *dri2_ctx; 991 _EGLContext *ctx; 992 GLint format, target; 993 994 ctx = _eglGetCurrentContext(); 995 dri2_ctx = dri2_egl_context(ctx); 996 997 if (!_eglBindTexImage(drv, disp, surf, buffer)) 998 return EGL_FALSE; 999 1000 switch (dri2_surf->base.TextureFormat) { 1001 case EGL_TEXTURE_RGB: 1002 format = __DRI_TEXTURE_FORMAT_RGB; 1003 break; 1004 case EGL_TEXTURE_RGBA: 1005 format = __DRI_TEXTURE_FORMAT_RGBA; 1006 break; 1007 default: 1008 assert(0); 1009 } 1010 1011 switch (dri2_surf->base.TextureTarget) { 1012 case EGL_TEXTURE_2D: 1013 target = GL_TEXTURE_2D; 1014 break; 1015 default: 1016 assert(0); 1017 } 1018 1019 (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context, 1020 target, format, 1021 dri2_surf->dri_drawable); 1022 1023 return EGL_TRUE; 1024} 1025 1026static EGLBoolean 1027dri2_release_tex_image(_EGLDriver *drv, 1028 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 1029{ 1030#if __DRI_TEX_BUFFER_VERSION >= 3 1031 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1032 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1033 struct dri2_egl_context *dri2_ctx; 1034 _EGLContext *ctx; 1035 GLint target; 1036 1037 ctx = _eglGetCurrentContext(); 1038 dri2_ctx = dri2_egl_context(ctx); 1039 1040 if (!_eglReleaseTexImage(drv, disp, surf, buffer)) 1041 return EGL_FALSE; 1042 1043 switch (dri2_surf->base.TextureTarget) { 1044 case EGL_TEXTURE_2D: 1045 target = GL_TEXTURE_2D; 1046 break; 1047 default: 1048 assert(0); 1049 } 1050 if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL) 1051 (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context, 1052 target, 1053 dri2_surf->dri_drawable); 1054#endif 1055 1056 return EGL_TRUE; 1057} 1058 1059static _EGLImage * 1060dri2_create_image(_EGLDisplay *disp, __DRIimage *dri_image) 1061{ 1062 struct dri2_egl_image *dri2_img; 1063 1064 if (dri_image == NULL) { 1065 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1066 return NULL; 1067 } 1068 1069 dri2_img = malloc(sizeof *dri2_img); 1070 if (!dri2_img) { 1071 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1072 return NULL; 1073 } 1074 1075 if (!_eglInitImage(&dri2_img->base, disp)) { 1076 free(dri2_img); 1077 return NULL; 1078 } 1079 1080 dri2_img->dri_image = dri_image; 1081 1082 return &dri2_img->base; 1083} 1084 1085static _EGLImage * 1086dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 1087 EGLClientBuffer buffer, 1088 const EGLint *attr_list) 1089{ 1090 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1091 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1092 GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 1093 __DRIimage *dri_image; 1094 1095 if (renderbuffer == 0) { 1096 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1097 return EGL_NO_IMAGE_KHR; 1098 } 1099 1100 dri_image = 1101 dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, 1102 renderbuffer, NULL); 1103 1104 return dri2_create_image(disp, dri_image); 1105} 1106 1107static _EGLImage * 1108dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1109 EGLClientBuffer buffer, const EGLint *attr_list) 1110{ 1111 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1112 EGLint format, name, pitch, err; 1113 _EGLImageAttribs attrs; 1114 __DRIimage *dri_image; 1115 1116 name = (EGLint) (uintptr_t) buffer; 1117 1118 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1119 if (err != EGL_SUCCESS) 1120 return NULL; 1121 1122 if (attrs.Width <= 0 || attrs.Height <= 0 || 1123 attrs.DRMBufferStrideMESA <= 0) { 1124 _eglError(EGL_BAD_PARAMETER, 1125 "bad width, height or stride"); 1126 return NULL; 1127 } 1128 1129 switch (attrs.DRMBufferFormatMESA) { 1130 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1131 format = __DRI_IMAGE_FORMAT_ARGB8888; 1132 pitch = attrs.DRMBufferStrideMESA; 1133 break; 1134 default: 1135 _eglError(EGL_BAD_PARAMETER, 1136 "dri2_create_image_khr: unsupported pixmap depth"); 1137 return NULL; 1138 } 1139 1140 dri_image = 1141 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1142 attrs.Width, 1143 attrs.Height, 1144 format, 1145 name, 1146 pitch, 1147 NULL); 1148 1149 return dri2_create_image(disp, dri_image); 1150} 1151 1152#ifdef HAVE_WAYLAND_PLATFORM 1153 1154/* This structure describes how a wl_buffer maps to one or more 1155 * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the 1156 * offsets and strides of the planes in the buffer. This table maps a 1157 * wl_drm format code to a description of the planes in the buffer 1158 * that lets us create a __DRIimage for each of the planes. */ 1159 1160static const struct wl_drm_components_descriptor { 1161 uint32_t dri_components; 1162 EGLint components; 1163 int nplanes; 1164} wl_drm_components[] = { 1165 { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 }, 1166 { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 }, 1167 { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 }, 1168 { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 }, 1169 { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 }, 1170}; 1171 1172static _EGLImage * 1173dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1174 EGLClientBuffer _buffer, 1175 const EGLint *attr_list) 1176{ 1177 struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; 1178 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1179 const struct wl_drm_components_descriptor *f; 1180 __DRIimage *dri_image; 1181 _EGLImageAttribs attrs; 1182 EGLint err; 1183 int32_t plane; 1184 1185 if (!wayland_buffer_is_drm(&buffer->buffer)) 1186 return NULL; 1187 1188 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1189 plane = attrs.PlaneWL; 1190 if (err != EGL_SUCCESS) { 1191 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 1192 return NULL; 1193 } 1194 1195 f = buffer->driver_format; 1196 if (plane < 0 || plane >= f->nplanes) { 1197 _eglError(EGL_BAD_PARAMETER, 1198 "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); 1199 return NULL; 1200 } 1201 1202 dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL); 1203 1204 if (dri_image == NULL) { 1205 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 1206 return NULL; 1207 } 1208 1209 return dri2_create_image(disp, dri_image); 1210} 1211#endif 1212 1213_EGLImage * 1214dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 1215 _EGLContext *ctx, EGLenum target, 1216 EGLClientBuffer buffer, const EGLint *attr_list) 1217{ 1218 (void) drv; 1219 1220 switch (target) { 1221 case EGL_GL_RENDERBUFFER_KHR: 1222 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 1223 case EGL_DRM_BUFFER_MESA: 1224 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 1225#ifdef HAVE_WAYLAND_PLATFORM 1226 case EGL_WAYLAND_BUFFER_WL: 1227 return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 1228#endif 1229 default: 1230 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1231 return EGL_NO_IMAGE_KHR; 1232 } 1233} 1234 1235static EGLBoolean 1236dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) 1237{ 1238 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1239 struct dri2_egl_image *dri2_img = dri2_egl_image(image); 1240 1241 (void) drv; 1242 1243 dri2_dpy->image->destroyImage(dri2_img->dri_image); 1244 free(dri2_img); 1245 1246 return EGL_TRUE; 1247} 1248 1249static _EGLImage * 1250dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, 1251 const EGLint *attr_list) 1252{ 1253 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1254 struct dri2_egl_image *dri2_img; 1255 _EGLImageAttribs attrs; 1256 unsigned int dri_use, valid_mask; 1257 int format; 1258 EGLint err = EGL_SUCCESS; 1259 1260 (void) drv; 1261 1262 dri2_img = malloc(sizeof *dri2_img); 1263 if (!dri2_img) { 1264 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1265 return EGL_NO_IMAGE_KHR; 1266 } 1267 1268 if (!attr_list) { 1269 err = EGL_BAD_PARAMETER; 1270 goto cleanup_img; 1271 } 1272 1273 if (!_eglInitImage(&dri2_img->base, disp)) { 1274 err = EGL_BAD_PARAMETER; 1275 goto cleanup_img; 1276 } 1277 1278 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1279 if (err != EGL_SUCCESS) 1280 goto cleanup_img; 1281 1282 if (attrs.Width <= 0 || attrs.Height <= 0) { 1283 _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", 1284 attrs.Width, attrs.Height); 1285 goto cleanup_img; 1286 } 1287 1288 switch (attrs.DRMBufferFormatMESA) { 1289 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1290 format = __DRI_IMAGE_FORMAT_ARGB8888; 1291 break; 1292 default: 1293 _eglLog(_EGL_WARNING, "bad image format value 0x%04x", 1294 attrs.DRMBufferFormatMESA); 1295 goto cleanup_img; 1296 } 1297 1298 valid_mask = 1299 EGL_DRM_BUFFER_USE_SCANOUT_MESA | 1300 EGL_DRM_BUFFER_USE_SHARE_MESA | 1301 EGL_DRM_BUFFER_USE_CURSOR_MESA; 1302 if (attrs.DRMBufferUseMESA & ~valid_mask) { 1303 _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", 1304 attrs.DRMBufferUseMESA & ~valid_mask); 1305 goto cleanup_img; 1306 } 1307 1308 dri_use = 0; 1309 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 1310 dri_use |= __DRI_IMAGE_USE_SHARE; 1311 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 1312 dri_use |= __DRI_IMAGE_USE_SCANOUT; 1313 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 1314 dri_use |= __DRI_IMAGE_USE_CURSOR; 1315 1316 dri2_img->dri_image = 1317 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 1318 attrs.Width, attrs.Height, 1319 format, dri_use, dri2_img); 1320 if (dri2_img->dri_image == NULL) { 1321 err = EGL_BAD_ALLOC; 1322 goto cleanup_img; 1323 } 1324 1325 return &dri2_img->base; 1326 1327 cleanup_img: 1328 free(dri2_img); 1329 _eglError(err, "dri2_create_drm_image_mesa"); 1330 1331 return EGL_NO_IMAGE_KHR; 1332} 1333 1334static EGLBoolean 1335dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 1336 EGLint *name, EGLint *handle, EGLint *stride) 1337{ 1338 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1339 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 1340 1341 (void) drv; 1342 1343 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 1344 __DRI_IMAGE_ATTRIB_NAME, name)) { 1345 _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 1346 return EGL_FALSE; 1347 } 1348 1349 if (handle) 1350 dri2_dpy->image->queryImage(dri2_img->dri_image, 1351 __DRI_IMAGE_ATTRIB_HANDLE, handle); 1352 1353 if (stride) 1354 dri2_dpy->image->queryImage(dri2_img->dri_image, 1355 __DRI_IMAGE_ATTRIB_STRIDE, stride); 1356 1357 return EGL_TRUE; 1358} 1359 1360#ifdef HAVE_WAYLAND_PLATFORM 1361 1362static void 1363dri2_wl_reference_buffer(void *user_data, uint32_t name, 1364 struct wl_drm_buffer *buffer) 1365{ 1366 _EGLDisplay *disp = user_data; 1367 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1368 __DRIimage *img; 1369 int i, dri_components = 0; 1370 1371 img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, 1372 buffer->buffer.width, 1373 buffer->buffer.height, 1374 buffer->format, (int*)&name, 1, 1375 buffer->stride, 1376 buffer->offset, 1377 NULL); 1378 1379 if (img == NULL) 1380 return; 1381 1382 dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components); 1383 1384 buffer->driver_format = NULL; 1385 for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++) 1386 if (wl_drm_components[i].dri_components == dri_components) 1387 buffer->driver_format = &wl_drm_components[i]; 1388 1389 if (buffer->driver_format == NULL) 1390 dri2_dpy->image->destroyImage(img); 1391 else 1392 buffer->driver_buffer = img; 1393} 1394 1395static void 1396dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) 1397{ 1398 _EGLDisplay *disp = user_data; 1399 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1400 1401 dri2_dpy->image->destroyImage(buffer->driver_buffer); 1402} 1403 1404static struct wayland_drm_callbacks wl_drm_callbacks = { 1405 .authenticate = NULL, 1406 .reference_buffer = dri2_wl_reference_buffer, 1407 .release_buffer = dri2_wl_release_buffer 1408}; 1409 1410static EGLBoolean 1411dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1412 struct wl_display *wl_dpy) 1413{ 1414 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1415 1416 (void) drv; 1417 1418 if (dri2_dpy->wl_server_drm) 1419 return EGL_FALSE; 1420 1421 wl_drm_callbacks.authenticate = 1422 (int(*)(void *, uint32_t)) dri2_dpy->authenticate; 1423 1424 dri2_dpy->wl_server_drm = 1425 wayland_drm_init(wl_dpy, dri2_dpy->device_name, 1426 &wl_drm_callbacks, disp); 1427 1428 if (!dri2_dpy->wl_server_drm) 1429 return EGL_FALSE; 1430 1431 return EGL_TRUE; 1432} 1433 1434static EGLBoolean 1435dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1436 struct wl_display *wl_dpy) 1437{ 1438 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1439 1440 (void) drv; 1441 1442 if (!dri2_dpy->wl_server_drm) 1443 return EGL_FALSE; 1444 1445 wayland_drm_uninit(dri2_dpy->wl_server_drm); 1446 dri2_dpy->wl_server_drm = NULL; 1447 1448 return EGL_TRUE; 1449} 1450 1451static EGLBoolean 1452dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp, 1453 struct wl_buffer *_buffer, 1454 EGLint attribute, EGLint *value) 1455{ 1456 struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; 1457 const struct wl_drm_components_descriptor *format; 1458 1459 if (!wayland_buffer_is_drm(&buffer->buffer)) 1460 return EGL_FALSE; 1461 1462 format = buffer->driver_format; 1463 switch (attribute) { 1464 case EGL_TEXTURE_FORMAT: 1465 *value = format->components; 1466 return EGL_TRUE; 1467 case EGL_WIDTH: 1468 *value = buffer->buffer.width; 1469 break; 1470 case EGL_HEIGHT: 1471 *value = buffer->buffer.height; 1472 break; 1473 } 1474 1475 return EGL_FALSE; 1476} 1477#endif 1478 1479static void 1480dri2_unload(_EGLDriver *drv) 1481{ 1482 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1483 1484 if (dri2_drv->handle) 1485 dlclose(dri2_drv->handle); 1486 free(dri2_drv); 1487} 1488 1489static EGLBoolean 1490dri2_load(_EGLDriver *drv) 1491{ 1492 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1493#ifdef HAVE_SHARED_GLAPI 1494#ifdef HAVE_ANDROID_PLATFORM 1495 const char *libname = "libglapi.so"; 1496#else 1497 const char *libname = "libglapi.so.0"; 1498#endif 1499#else 1500 /* 1501 * Both libGL.so and libglapi.so are glapi providers. There is no way to 1502 * tell which one to load. 1503 */ 1504 const char *libname = NULL; 1505#endif 1506 void *handle; 1507 1508 /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */ 1509 handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); 1510 if (handle) { 1511 dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) 1512 dlsym(handle, "_glapi_get_proc_address"); 1513 if (!dri2_drv->get_proc_address || !libname) { 1514 /* no need to keep a reference */ 1515 dlclose(handle); 1516 handle = NULL; 1517 } 1518 } 1519 1520 /* if glapi is not available, loading DRI drivers will fail */ 1521 if (!dri2_drv->get_proc_address) { 1522 _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); 1523 return EGL_FALSE; 1524 } 1525 1526 dri2_drv->glFlush = (void (*)(void)) 1527 dri2_drv->get_proc_address("glFlush"); 1528 1529 dri2_drv->handle = handle; 1530 1531 return EGL_TRUE; 1532} 1533 1534/** 1535 * This is the main entrypoint into the driver, called by libEGL. 1536 * Create a new _EGLDriver object and init its dispatch table. 1537 */ 1538_EGLDriver * 1539_eglBuiltInDriverDRI2(const char *args) 1540{ 1541 struct dri2_egl_driver *dri2_drv; 1542 1543 (void) args; 1544 1545 dri2_drv = malloc(sizeof *dri2_drv); 1546 if (!dri2_drv) 1547 return NULL; 1548 1549 memset(dri2_drv, 0, sizeof *dri2_drv); 1550 1551 if (!dri2_load(&dri2_drv->base)) { 1552 free(dri2_drv); 1553 return NULL; 1554 } 1555 1556 _eglInitDriverFallbacks(&dri2_drv->base); 1557 dri2_drv->base.API.Initialize = dri2_initialize; 1558 dri2_drv->base.API.Terminate = dri2_terminate; 1559 dri2_drv->base.API.CreateContext = dri2_create_context; 1560 dri2_drv->base.API.DestroyContext = dri2_destroy_context; 1561 dri2_drv->base.API.MakeCurrent = dri2_make_current; 1562 dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; 1563 dri2_drv->base.API.WaitClient = dri2_wait_client; 1564 dri2_drv->base.API.WaitNative = dri2_wait_native; 1565 dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; 1566 dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; 1567 dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; 1568 dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; 1569 dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; 1570 dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; 1571#ifdef HAVE_WAYLAND_PLATFORM 1572 dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; 1573 dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; 1574 dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; 1575#endif 1576 1577 dri2_drv->base.Name = "DRI2"; 1578 dri2_drv->base.Unload = dri2_unload; 1579 1580 return &dri2_drv->base; 1581} 1582