egl_dri2.c revision dbecb413008c19e1864de93d9a8a9123bfee46e7
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->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/** 644 * Called via eglCreateContext(), drv->API.CreateContext(). 645 */ 646static _EGLContext * 647dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 648 _EGLContext *share_list, const EGLint *attrib_list) 649{ 650 struct dri2_egl_context *dri2_ctx; 651 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 652 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 653 __DRIcontext *shared = 654 dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; 655 struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 656 const __DRIconfig *dri_config; 657 int api; 658 659 (void) drv; 660 661 dri2_ctx = malloc(sizeof *dri2_ctx); 662 if (!dri2_ctx) { 663 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 664 return NULL; 665 } 666 667 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 668 goto cleanup; 669 670 switch (dri2_ctx->base.ClientAPI) { 671 case EGL_OPENGL_ES_API: 672 switch (dri2_ctx->base.ClientMajorVersion) { 673 case 1: 674 api = __DRI_API_GLES; 675 break; 676 case 2: 677 case 3: 678 api = __DRI_API_GLES2; 679 break; 680 default: 681 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 682 return NULL; 683 } 684 break; 685 case EGL_OPENGL_API: 686 if ((dri2_ctx->base.ClientMajorVersion >= 4 687 || (dri2_ctx->base.ClientMajorVersion == 3 688 && dri2_ctx->base.ClientMinorVersion >= 2)) 689 && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) 690 api = __DRI_API_OPENGL_CORE; 691 else 692 api = __DRI_API_OPENGL; 693 break; 694 default: 695 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 696 return NULL; 697 } 698 699 if (conf != NULL) { 700 /* The config chosen here isn't necessarily 701 * used for surfaces later. 702 * A pixmap surface will use the single config. 703 * This opportunity depends on disabling the 704 * doubleBufferMode check in 705 * src/mesa/main/context.c:check_compatible() 706 */ 707 if (dri2_config->dri_double_config) 708 dri_config = dri2_config->dri_double_config; 709 else 710 dri_config = dri2_config->dri_single_config; 711 712 /* EGL_WINDOW_BIT is set only when there is a dri_double_config. This 713 * makes sure the back buffer will always be used. 714 */ 715 if (conf->SurfaceType & EGL_WINDOW_BIT) 716 dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER; 717 } 718 else 719 dri_config = NULL; 720 721 if (dri2_dpy->dri2) { 722 if (dri2_dpy->dri2->base.version >= 3) { 723 unsigned error; 724 unsigned num_attribs = 0; 725 uint32_t ctx_attribs[8]; 726 727 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 728 ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion; 729 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 730 ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion; 731 732 if (dri2_ctx->base.Flags != 0) { 733 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 734 * extension, don't even try to send it the robust-access flag. 735 * It may explode. Instead, generate the required EGL error here. 736 */ 737 if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0 738 && !dri2_dpy->robustness) { 739 _eglError(EGL_BAD_MATCH, "eglCreateContext"); 740 goto cleanup; 741 } 742 743 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS; 744 ctx_attribs[num_attribs++] = dri2_ctx->base.Flags; 745 } 746 747 if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) { 748 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 749 * extension, don't even try to send it a reset strategy. It may 750 * explode. Instead, generate the required EGL error here. 751 */ 752 if (!dri2_dpy->robustness) { 753 _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 754 goto cleanup; 755 } 756 757 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 758 ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT; 759 } 760 761 assert(num_attribs <= ARRAY_SIZE(ctx_attribs)); 762 763 dri2_ctx->dri_context = 764 dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen, 765 api, 766 dri_config, 767 shared, 768 num_attribs / 2, 769 ctx_attribs, 770 & error, 771 dri2_ctx); 772 } else { 773 dri2_ctx->dri_context = 774 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 775 api, 776 dri_config, 777 shared, 778 dri2_ctx); 779 } 780 } else { 781 assert(dri2_dpy->swrast); 782 dri2_ctx->dri_context = 783 dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 784 api, 785 dri_config, 786 shared, 787 dri2_ctx); 788 } 789 790 if (!dri2_ctx->dri_context) 791 goto cleanup; 792 793 return &dri2_ctx->base; 794 795 cleanup: 796 free(dri2_ctx); 797 return NULL; 798} 799 800/** 801 * Called via eglDestroyContext(), drv->API.DestroyContext(). 802 */ 803static EGLBoolean 804dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 805{ 806 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 807 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 808 809 if (_eglPutContext(ctx)) { 810 dri2_dpy->core->destroyContext(dri2_ctx->dri_context); 811 free(dri2_ctx); 812 } 813 814 return EGL_TRUE; 815} 816 817/** 818 * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 819 */ 820static EGLBoolean 821dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 822 _EGLSurface *rsurf, _EGLContext *ctx) 823{ 824 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 825 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 826 struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); 827 struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); 828 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 829 _EGLContext *old_ctx; 830 _EGLSurface *old_dsurf, *old_rsurf; 831 __DRIdrawable *ddraw, *rdraw; 832 __DRIcontext *cctx; 833 834 /* make new bindings */ 835 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 836 return EGL_FALSE; 837 838 /* flush before context switch */ 839 if (old_ctx && dri2_drv->glFlush) 840 dri2_drv->glFlush(); 841 842 ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; 843 rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; 844 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 845 846 if (old_ctx) { 847 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 848 dri2_dpy->core->unbindContext(old_cctx); 849 } 850 851 if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || 852 dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 853 if (old_dsurf) 854 drv->API.DestroySurface(drv, disp, old_dsurf); 855 if (old_rsurf) 856 drv->API.DestroySurface(drv, disp, old_rsurf); 857 if (old_ctx) 858 drv->API.DestroyContext(drv, disp, old_ctx); 859 860 return EGL_TRUE; 861 } else { 862 /* undo the previous _eglBindContext */ 863 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); 864 assert(&dri2_ctx->base == ctx && 865 &dri2_dsurf->base == dsurf && 866 &dri2_rsurf->base == rsurf); 867 868 _eglPutSurface(dsurf); 869 _eglPutSurface(rsurf); 870 _eglPutContext(ctx); 871 872 _eglPutSurface(old_dsurf); 873 _eglPutSurface(old_rsurf); 874 _eglPutContext(old_ctx); 875 876 return EGL_FALSE; 877 } 878} 879 880/* 881 * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 882 */ 883static _EGLProc 884dri2_get_proc_address(_EGLDriver *drv, const char *procname) 885{ 886 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 887 888 return dri2_drv->get_proc_address(procname); 889} 890 891static EGLBoolean 892dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 893{ 894 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 895 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); 896 897 (void) drv; 898 899 /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 900 * we need to copy fake to real here.*/ 901 902 (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable); 903 904 return EGL_TRUE; 905} 906 907static EGLBoolean 908dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) 909{ 910 (void) drv; 911 (void) disp; 912 913 if (engine != EGL_CORE_NATIVE_ENGINE) 914 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 915 /* glXWaitX(); */ 916 917 return EGL_TRUE; 918} 919 920static EGLBoolean 921dri2_bind_tex_image(_EGLDriver *drv, 922 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 923{ 924 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 925 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 926 struct dri2_egl_context *dri2_ctx; 927 _EGLContext *ctx; 928 GLint format, target; 929 930 ctx = _eglGetCurrentContext(); 931 dri2_ctx = dri2_egl_context(ctx); 932 933 if (!_eglBindTexImage(drv, disp, surf, buffer)) 934 return EGL_FALSE; 935 936 switch (dri2_surf->base.TextureFormat) { 937 case EGL_TEXTURE_RGB: 938 format = __DRI_TEXTURE_FORMAT_RGB; 939 break; 940 case EGL_TEXTURE_RGBA: 941 format = __DRI_TEXTURE_FORMAT_RGBA; 942 break; 943 default: 944 assert(0); 945 } 946 947 switch (dri2_surf->base.TextureTarget) { 948 case EGL_TEXTURE_2D: 949 target = GL_TEXTURE_2D; 950 break; 951 default: 952 assert(0); 953 } 954 955 (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context, 956 target, format, 957 dri2_surf->dri_drawable); 958 959 return EGL_TRUE; 960} 961 962static EGLBoolean 963dri2_release_tex_image(_EGLDriver *drv, 964 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 965{ 966#if __DRI_TEX_BUFFER_VERSION >= 3 967 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 968 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 969 struct dri2_egl_context *dri2_ctx; 970 _EGLContext *ctx; 971 GLint target; 972 973 ctx = _eglGetCurrentContext(); 974 dri2_ctx = dri2_egl_context(ctx); 975 976 if (!_eglReleaseTexImage(drv, disp, surf, buffer)) 977 return EGL_FALSE; 978 979 switch (dri2_surf->base.TextureTarget) { 980 case EGL_TEXTURE_2D: 981 target = GL_TEXTURE_2D; 982 break; 983 default: 984 assert(0); 985 } 986 if (dri2_dpy->tex_buffer->releaseTexBuffer!=NULL) 987 (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context, 988 target, 989 dri2_surf->dri_drawable); 990#endif 991 992 return EGL_TRUE; 993} 994 995static _EGLImage * 996dri2_create_image(_EGLDisplay *disp, __DRIimage *dri_image) 997{ 998 struct dri2_egl_image *dri2_img; 999 1000 if (dri_image == NULL) { 1001 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1002 return NULL; 1003 } 1004 1005 dri2_img = malloc(sizeof *dri2_img); 1006 if (!dri2_img) { 1007 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1008 return NULL; 1009 } 1010 1011 if (!_eglInitImage(&dri2_img->base, disp)) { 1012 free(dri2_img); 1013 return NULL; 1014 } 1015 1016 dri2_img->dri_image = dri_image; 1017 1018 return &dri2_img->base; 1019} 1020 1021static _EGLImage * 1022dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 1023 EGLClientBuffer buffer, 1024 const EGLint *attr_list) 1025{ 1026 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1027 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1028 GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 1029 __DRIimage *dri_image; 1030 1031 if (renderbuffer == 0) { 1032 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1033 return EGL_NO_IMAGE_KHR; 1034 } 1035 1036 dri_image = 1037 dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, 1038 renderbuffer, NULL); 1039 1040 return dri2_create_image(disp, dri_image); 1041} 1042 1043static _EGLImage * 1044dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1045 EGLClientBuffer buffer, const EGLint *attr_list) 1046{ 1047 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1048 EGLint format, name, pitch, err; 1049 _EGLImageAttribs attrs; 1050 __DRIimage *dri_image; 1051 1052 name = (EGLint) (uintptr_t) buffer; 1053 1054 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1055 if (err != EGL_SUCCESS) 1056 return NULL; 1057 1058 if (attrs.Width <= 0 || attrs.Height <= 0 || 1059 attrs.DRMBufferStrideMESA <= 0) { 1060 _eglError(EGL_BAD_PARAMETER, 1061 "bad width, height or stride"); 1062 return NULL; 1063 } 1064 1065 switch (attrs.DRMBufferFormatMESA) { 1066 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1067 format = __DRI_IMAGE_FORMAT_ARGB8888; 1068 pitch = attrs.DRMBufferStrideMESA; 1069 break; 1070 default: 1071 _eglError(EGL_BAD_PARAMETER, 1072 "dri2_create_image_khr: unsupported pixmap depth"); 1073 return NULL; 1074 } 1075 1076 dri_image = 1077 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1078 attrs.Width, 1079 attrs.Height, 1080 format, 1081 name, 1082 pitch, 1083 NULL); 1084 1085 return dri2_create_image(disp, dri_image); 1086} 1087 1088#ifdef HAVE_WAYLAND_PLATFORM 1089 1090/* This structure describes how a wl_buffer maps to one or more 1091 * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the 1092 * offsets and strides of the planes in the buffer. This table maps a 1093 * wl_drm format code to a description of the planes in the buffer 1094 * that lets us create a __DRIimage for each of the planes. */ 1095 1096static const struct wl_drm_format_descriptor { 1097 uint32_t wl_format; 1098 EGLint components; 1099 int nplanes; 1100 struct { 1101 int buffer_index; 1102 int width_shift; 1103 int height_shift; 1104 uint32_t dri_format; 1105 int cpp; 1106 } planes[3]; 1107} wl_drm_formats[] = { 1108 { WL_DRM_FORMAT_ARGB8888, EGL_TEXTURE_RGBA, 1, 1109 { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 }, } }, 1110 1111 { WL_DRM_FORMAT_XRGB8888, EGL_TEXTURE_RGB, 1, 1112 { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } }, 1113 1114 { WL_DRM_FORMAT_YUV410, EGL_TEXTURE_Y_U_V_WL, 3, 1115 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1116 { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 }, 1117 { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1118 1119 { WL_DRM_FORMAT_YUV411, EGL_TEXTURE_Y_U_V_WL, 3, 1120 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1121 { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1122 { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1123 1124 { WL_DRM_FORMAT_YUV420, EGL_TEXTURE_Y_U_V_WL, 3, 1125 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1126 { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 }, 1127 { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1128 1129 { WL_DRM_FORMAT_YUV422, EGL_TEXTURE_Y_U_V_WL, 3, 1130 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1131 { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1132 { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1133 1134 { WL_DRM_FORMAT_YUV444, EGL_TEXTURE_Y_U_V_WL, 3, 1135 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1136 { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1137 { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } }, 1138 1139 { WL_DRM_FORMAT_NV12, EGL_TEXTURE_Y_UV_WL, 2, 1140 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1141 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } }, 1142 1143 { WL_DRM_FORMAT_NV16, EGL_TEXTURE_Y_UV_WL, 2, 1144 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, 1145 { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } }, 1146 1147 /* For YUYV buffers, we set up two overlapping DRI images and treat 1148 * them as planar buffers in the compositors. Plane 0 is GR88 and 1149 * samples YU or YV pairs and places Y into the R component, while 1150 * plane 1 is ARGB and samples YUYV clusters and places pairs and 1151 * places U into the G component and V into A. This lets the 1152 * texture sampler interpolate the Y components correctly when 1153 * sampling from plane 0, and interpolate U and V correctly when 1154 * sampling from plane 1. */ 1155 { WL_DRM_FORMAT_YUYV, EGL_TEXTURE_Y_XUXV_WL, 2, 1156 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, 1157 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } } 1158}; 1159 1160static _EGLImage * 1161dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1162 EGLClientBuffer _buffer, 1163 const EGLint *attr_list) 1164{ 1165 struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; 1166 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1167 __DRIimage *dri_image; 1168 _EGLImageAttribs attrs; 1169 EGLint err; 1170 uint32_t format; 1171 int32_t offset, stride, plane, width, height; 1172 int cpp, index; 1173 const struct wl_drm_format_descriptor *f; 1174 1175 if (!wayland_buffer_is_drm(&buffer->buffer)) 1176 return NULL; 1177 1178 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1179 plane = attrs.PlaneWL; 1180 if (err != EGL_SUCCESS) { 1181 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 1182 return NULL; 1183 } 1184 1185 f = buffer->driver_format; 1186 if (plane < 0 || plane >= f->nplanes) { 1187 _eglError(EGL_BAD_PARAMETER, 1188 "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); 1189 return NULL; 1190 } 1191 1192 width = buffer->buffer.width >> f->planes[plane].width_shift; 1193 height = buffer->buffer.height >> f->planes[plane].height_shift; 1194 format = f->planes[plane].dri_format; 1195 cpp = f->planes[plane].cpp; 1196 index = f->planes[plane].buffer_index; 1197 offset = buffer->offset[index]; 1198 stride = buffer->stride[index]; 1199 1200 dri_image = dri2_dpy->image->createSubImage(buffer->driver_buffer, 1201 width, height, format, 1202 offset, stride / cpp, NULL); 1203 1204 return dri2_create_image(disp, dri_image); 1205} 1206#endif 1207 1208_EGLImage * 1209dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 1210 _EGLContext *ctx, EGLenum target, 1211 EGLClientBuffer buffer, const EGLint *attr_list) 1212{ 1213 (void) drv; 1214 1215 switch (target) { 1216 case EGL_GL_RENDERBUFFER_KHR: 1217 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 1218 case EGL_DRM_BUFFER_MESA: 1219 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 1220#ifdef HAVE_WAYLAND_PLATFORM 1221 case EGL_WAYLAND_BUFFER_WL: 1222 return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 1223#endif 1224 default: 1225 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1226 return EGL_NO_IMAGE_KHR; 1227 } 1228} 1229 1230static EGLBoolean 1231dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) 1232{ 1233 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1234 struct dri2_egl_image *dri2_img = dri2_egl_image(image); 1235 1236 (void) drv; 1237 1238 dri2_dpy->image->destroyImage(dri2_img->dri_image); 1239 free(dri2_img); 1240 1241 return EGL_TRUE; 1242} 1243 1244static _EGLImage * 1245dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, 1246 const EGLint *attr_list) 1247{ 1248 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1249 struct dri2_egl_image *dri2_img; 1250 _EGLImageAttribs attrs; 1251 unsigned int dri_use, valid_mask; 1252 int format; 1253 EGLint err = EGL_SUCCESS; 1254 1255 (void) drv; 1256 1257 dri2_img = malloc(sizeof *dri2_img); 1258 if (!dri2_img) { 1259 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1260 return EGL_NO_IMAGE_KHR; 1261 } 1262 1263 if (!attr_list) { 1264 err = EGL_BAD_PARAMETER; 1265 goto cleanup_img; 1266 } 1267 1268 if (!_eglInitImage(&dri2_img->base, disp)) { 1269 err = EGL_BAD_PARAMETER; 1270 goto cleanup_img; 1271 } 1272 1273 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1274 if (err != EGL_SUCCESS) 1275 goto cleanup_img; 1276 1277 if (attrs.Width <= 0 || attrs.Height <= 0) { 1278 _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", 1279 attrs.Width, attrs.Height); 1280 goto cleanup_img; 1281 } 1282 1283 switch (attrs.DRMBufferFormatMESA) { 1284 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1285 format = __DRI_IMAGE_FORMAT_ARGB8888; 1286 break; 1287 default: 1288 _eglLog(_EGL_WARNING, "bad image format value 0x%04x", 1289 attrs.DRMBufferFormatMESA); 1290 goto cleanup_img; 1291 } 1292 1293 valid_mask = 1294 EGL_DRM_BUFFER_USE_SCANOUT_MESA | 1295 EGL_DRM_BUFFER_USE_SHARE_MESA | 1296 EGL_DRM_BUFFER_USE_CURSOR_MESA; 1297 if (attrs.DRMBufferUseMESA & ~valid_mask) { 1298 _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", 1299 attrs.DRMBufferUseMESA & ~valid_mask); 1300 goto cleanup_img; 1301 } 1302 1303 dri_use = 0; 1304 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 1305 dri_use |= __DRI_IMAGE_USE_SHARE; 1306 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 1307 dri_use |= __DRI_IMAGE_USE_SCANOUT; 1308 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 1309 dri_use |= __DRI_IMAGE_USE_CURSOR; 1310 1311 dri2_img->dri_image = 1312 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 1313 attrs.Width, attrs.Height, 1314 format, dri_use, dri2_img); 1315 if (dri2_img->dri_image == NULL) { 1316 err = EGL_BAD_ALLOC; 1317 goto cleanup_img; 1318 } 1319 1320 return &dri2_img->base; 1321 1322 cleanup_img: 1323 free(dri2_img); 1324 _eglError(err, "dri2_create_drm_image_mesa"); 1325 1326 return EGL_NO_IMAGE_KHR; 1327} 1328 1329static EGLBoolean 1330dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 1331 EGLint *name, EGLint *handle, EGLint *stride) 1332{ 1333 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1334 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 1335 1336 (void) drv; 1337 1338 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 1339 __DRI_IMAGE_ATTRIB_NAME, name)) { 1340 _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 1341 return EGL_FALSE; 1342 } 1343 1344 if (handle) 1345 dri2_dpy->image->queryImage(dri2_img->dri_image, 1346 __DRI_IMAGE_ATTRIB_HANDLE, handle); 1347 1348 if (stride) 1349 dri2_dpy->image->queryImage(dri2_img->dri_image, 1350 __DRI_IMAGE_ATTRIB_STRIDE, stride); 1351 1352 return EGL_TRUE; 1353} 1354 1355#ifdef HAVE_WAYLAND_PLATFORM 1356 1357static void 1358dri2_wl_reference_buffer(void *user_data, uint32_t name, 1359 struct wl_drm_buffer *buffer) 1360{ 1361 _EGLDisplay *disp = user_data; 1362 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1363 int i; 1364 1365 for (i = 0; i < ARRAY_SIZE(wl_drm_formats); i++) 1366 if (wl_drm_formats[i].wl_format == buffer->format) { 1367 buffer->driver_format = &wl_drm_formats[i]; 1368 break; 1369 } 1370 1371 if (buffer->driver_format == NULL) 1372 return; 1373 1374 buffer->driver_buffer = 1375 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1376 buffer->buffer.width, 1377 buffer->buffer.height, 1378 __DRI_IMAGE_FORMAT_NONE, name, 1379 buffer->stride[0] / 4, 1380 NULL); 1381} 1382 1383static void 1384dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) 1385{ 1386 _EGLDisplay *disp = user_data; 1387 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1388 1389 dri2_dpy->image->destroyImage(buffer->driver_buffer); 1390} 1391 1392static struct wayland_drm_callbacks wl_drm_callbacks = { 1393 .authenticate = NULL, 1394 .reference_buffer = dri2_wl_reference_buffer, 1395 .release_buffer = dri2_wl_release_buffer 1396}; 1397 1398static EGLBoolean 1399dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1400 struct wl_display *wl_dpy) 1401{ 1402 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1403 1404 (void) drv; 1405 1406 if (dri2_dpy->wl_server_drm) 1407 return EGL_FALSE; 1408 1409 wl_drm_callbacks.authenticate = 1410 (int(*)(void *, uint32_t)) dri2_dpy->authenticate; 1411 1412 dri2_dpy->wl_server_drm = 1413 wayland_drm_init(wl_dpy, dri2_dpy->device_name, 1414 &wl_drm_callbacks, disp); 1415 1416 if (!dri2_dpy->wl_server_drm) 1417 return EGL_FALSE; 1418 1419 return EGL_TRUE; 1420} 1421 1422static EGLBoolean 1423dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1424 struct wl_display *wl_dpy) 1425{ 1426 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1427 1428 (void) drv; 1429 1430 if (!dri2_dpy->wl_server_drm) 1431 return EGL_FALSE; 1432 1433 wayland_drm_uninit(dri2_dpy->wl_server_drm); 1434 dri2_dpy->wl_server_drm = NULL; 1435 1436 return EGL_TRUE; 1437} 1438 1439static EGLBoolean 1440dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp, 1441 struct wl_buffer *_buffer, 1442 EGLint attribute, EGLint *value) 1443{ 1444 struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; 1445 const struct wl_drm_format_descriptor *format; 1446 1447 if (!wayland_buffer_is_drm(&buffer->buffer)) 1448 return EGL_FALSE; 1449 1450 format = buffer->driver_format; 1451 switch (attribute) { 1452 case EGL_TEXTURE_FORMAT: 1453 *value = format->components; 1454 return EGL_TRUE; 1455 case EGL_WIDTH: 1456 *value = buffer->buffer.width; 1457 break; 1458 case EGL_HEIGHT: 1459 *value = buffer->buffer.height; 1460 break; 1461 } 1462 1463 return EGL_FALSE; 1464} 1465#endif 1466 1467static void 1468dri2_unload(_EGLDriver *drv) 1469{ 1470 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1471 1472 if (dri2_drv->handle) 1473 dlclose(dri2_drv->handle); 1474 free(dri2_drv); 1475} 1476 1477static EGLBoolean 1478dri2_load(_EGLDriver *drv) 1479{ 1480 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1481#ifdef HAVE_SHARED_GLAPI 1482#ifdef HAVE_ANDROID_PLATFORM 1483 const char *libname = "libglapi.so"; 1484#else 1485 const char *libname = "libglapi.so.0"; 1486#endif 1487#else 1488 /* 1489 * Both libGL.so and libglapi.so are glapi providers. There is no way to 1490 * tell which one to load. 1491 */ 1492 const char *libname = NULL; 1493#endif 1494 void *handle; 1495 1496 /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */ 1497 handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); 1498 if (handle) { 1499 dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) 1500 dlsym(handle, "_glapi_get_proc_address"); 1501 if (!dri2_drv->get_proc_address || !libname) { 1502 /* no need to keep a reference */ 1503 dlclose(handle); 1504 handle = NULL; 1505 } 1506 } 1507 1508 /* if glapi is not available, loading DRI drivers will fail */ 1509 if (!dri2_drv->get_proc_address) { 1510 _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); 1511 return EGL_FALSE; 1512 } 1513 1514 dri2_drv->glFlush = (void (*)(void)) 1515 dri2_drv->get_proc_address("glFlush"); 1516 1517 dri2_drv->handle = handle; 1518 1519 return EGL_TRUE; 1520} 1521 1522/** 1523 * This is the main entrypoint into the driver, called by libEGL. 1524 * Create a new _EGLDriver object and init its dispatch table. 1525 */ 1526_EGLDriver * 1527_eglBuiltInDriverDRI2(const char *args) 1528{ 1529 struct dri2_egl_driver *dri2_drv; 1530 1531 (void) args; 1532 1533 dri2_drv = malloc(sizeof *dri2_drv); 1534 if (!dri2_drv) 1535 return NULL; 1536 1537 memset(dri2_drv, 0, sizeof *dri2_drv); 1538 1539 if (!dri2_load(&dri2_drv->base)) { 1540 free(dri2_drv); 1541 return NULL; 1542 } 1543 1544 _eglInitDriverFallbacks(&dri2_drv->base); 1545 dri2_drv->base.API.Initialize = dri2_initialize; 1546 dri2_drv->base.API.Terminate = dri2_terminate; 1547 dri2_drv->base.API.CreateContext = dri2_create_context; 1548 dri2_drv->base.API.DestroyContext = dri2_destroy_context; 1549 dri2_drv->base.API.MakeCurrent = dri2_make_current; 1550 dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; 1551 dri2_drv->base.API.WaitClient = dri2_wait_client; 1552 dri2_drv->base.API.WaitNative = dri2_wait_native; 1553 dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; 1554 dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; 1555 dri2_drv->base.API.CreateImageKHR = dri2_create_image_khr; 1556 dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; 1557 dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; 1558 dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; 1559#ifdef HAVE_WAYLAND_PLATFORM 1560 dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; 1561 dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; 1562 dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; 1563#endif 1564 1565 dri2_drv->base.Name = "DRI2"; 1566 dri2_drv->base.Unload = dri2_unload; 1567 1568 return &dri2_drv->base; 1569} 1570