egl_dri2.c revision 848b8605
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#define WL_HIDE_DEPRECATED 29 30#include <stdlib.h> 31#include <string.h> 32#include <stdio.h> 33#include <limits.h> 34#include <dlfcn.h> 35#include <fcntl.h> 36#include <errno.h> 37#include <unistd.h> 38#ifdef HAVE_LIBDRM 39#include <xf86drm.h> 40#include <drm_fourcc.h> 41#endif 42#include <GL/gl.h> 43#include <GL/internal/dri_interface.h> 44#include <sys/types.h> 45#include <sys/stat.h> 46 47#ifdef HAVE_WAYLAND_PLATFORM 48#include "wayland-drm.h" 49#include "wayland-drm-client-protocol.h" 50#endif 51 52#include "egl_dri2.h" 53 54const __DRIuseInvalidateExtension use_invalidate = { 55 .base = { __DRI_USE_INVALIDATE, 1 } 56}; 57 58EGLint dri2_to_egl_attribute_map[] = { 59 0, 60 EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */ 61 EGL_LEVEL, /* __DRI_ATTRIB_LEVEL */ 62 EGL_RED_SIZE, /* __DRI_ATTRIB_RED_SIZE */ 63 EGL_GREEN_SIZE, /* __DRI_ATTRIB_GREEN_SIZE */ 64 EGL_BLUE_SIZE, /* __DRI_ATTRIB_BLUE_SIZE */ 65 EGL_LUMINANCE_SIZE, /* __DRI_ATTRIB_LUMINANCE_SIZE */ 66 EGL_ALPHA_SIZE, /* __DRI_ATTRIB_ALPHA_SIZE */ 67 0, /* __DRI_ATTRIB_ALPHA_MASK_SIZE */ 68 EGL_DEPTH_SIZE, /* __DRI_ATTRIB_DEPTH_SIZE */ 69 EGL_STENCIL_SIZE, /* __DRI_ATTRIB_STENCIL_SIZE */ 70 0, /* __DRI_ATTRIB_ACCUM_RED_SIZE */ 71 0, /* __DRI_ATTRIB_ACCUM_GREEN_SIZE */ 72 0, /* __DRI_ATTRIB_ACCUM_BLUE_SIZE */ 73 0, /* __DRI_ATTRIB_ACCUM_ALPHA_SIZE */ 74 EGL_SAMPLE_BUFFERS, /* __DRI_ATTRIB_SAMPLE_BUFFERS */ 75 EGL_SAMPLES, /* __DRI_ATTRIB_SAMPLES */ 76 0, /* __DRI_ATTRIB_RENDER_TYPE, */ 77 0, /* __DRI_ATTRIB_CONFIG_CAVEAT */ 78 0, /* __DRI_ATTRIB_CONFORMANT */ 79 0, /* __DRI_ATTRIB_DOUBLE_BUFFER */ 80 0, /* __DRI_ATTRIB_STEREO */ 81 0, /* __DRI_ATTRIB_AUX_BUFFERS */ 82 0, /* __DRI_ATTRIB_TRANSPARENT_TYPE */ 83 0, /* __DRI_ATTRIB_TRANSPARENT_INDEX_VALUE */ 84 0, /* __DRI_ATTRIB_TRANSPARENT_RED_VALUE */ 85 0, /* __DRI_ATTRIB_TRANSPARENT_GREEN_VALUE */ 86 0, /* __DRI_ATTRIB_TRANSPARENT_BLUE_VALUE */ 87 0, /* __DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE */ 88 0, /* __DRI_ATTRIB_FLOAT_MODE (deprecated) */ 89 0, /* __DRI_ATTRIB_RED_MASK */ 90 0, /* __DRI_ATTRIB_GREEN_MASK */ 91 0, /* __DRI_ATTRIB_BLUE_MASK */ 92 0, /* __DRI_ATTRIB_ALPHA_MASK */ 93 EGL_MAX_PBUFFER_WIDTH, /* __DRI_ATTRIB_MAX_PBUFFER_WIDTH */ 94 EGL_MAX_PBUFFER_HEIGHT, /* __DRI_ATTRIB_MAX_PBUFFER_HEIGHT */ 95 EGL_MAX_PBUFFER_PIXELS, /* __DRI_ATTRIB_MAX_PBUFFER_PIXELS */ 96 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH */ 97 0, /* __DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT */ 98 0, /* __DRI_ATTRIB_VISUAL_SELECT_GROUP */ 99 0, /* __DRI_ATTRIB_SWAP_METHOD */ 100 EGL_MAX_SWAP_INTERVAL, /* __DRI_ATTRIB_MAX_SWAP_INTERVAL */ 101 EGL_MIN_SWAP_INTERVAL, /* __DRI_ATTRIB_MIN_SWAP_INTERVAL */ 102 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGB */ 103 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */ 104 0, /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */ 105 0, /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */ 106 EGL_Y_INVERTED_NOK, /* __DRI_ATTRIB_YINVERTED */ 107 0, /* __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE */ 108}; 109 110static EGLBoolean 111dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) 112{ 113 if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0) 114 return EGL_FALSE; 115 116 if (!_eglMatchConfig(conf, criteria)) 117 return EGL_FALSE; 118 119 return EGL_TRUE; 120} 121 122struct dri2_egl_config * 123dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 124 EGLint surface_type, const EGLint *attr_list, 125 const unsigned int *rgba_masks) 126{ 127 struct dri2_egl_config *conf; 128 struct dri2_egl_display *dri2_dpy; 129 _EGLConfig base; 130 unsigned int attrib, value, double_buffer; 131 EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; 132 unsigned int dri_masks[4] = { 0, 0, 0, 0 }; 133 _EGLConfig *matching_config; 134 EGLint num_configs = 0; 135 EGLint config_id; 136 int i; 137 138 dri2_dpy = disp->DriverData; 139 _eglInitConfig(&base, disp, id); 140 141 i = 0; 142 double_buffer = 0; 143 bind_to_texture_rgb = 0; 144 bind_to_texture_rgba = 0; 145 146 while (dri2_dpy->core->indexConfigAttrib(dri_config, i++, &attrib, &value)) { 147 switch (attrib) { 148 case __DRI_ATTRIB_RENDER_TYPE: 149 if (value & __DRI_ATTRIB_RGBA_BIT) 150 value = EGL_RGB_BUFFER; 151 else if (value & __DRI_ATTRIB_LUMINANCE_BIT) 152 value = EGL_LUMINANCE_BUFFER; 153 else 154 return NULL; 155 _eglSetConfigKey(&base, EGL_COLOR_BUFFER_TYPE, value); 156 break; 157 158 case __DRI_ATTRIB_CONFIG_CAVEAT: 159 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 160 value = EGL_NON_CONFORMANT_CONFIG; 161 else if (value & __DRI_ATTRIB_SLOW_BIT) 162 value = EGL_SLOW_CONFIG; 163 else 164 value = EGL_NONE; 165 _eglSetConfigKey(&base, EGL_CONFIG_CAVEAT, value); 166 break; 167 168 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 169 bind_to_texture_rgb = value; 170 break; 171 172 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 173 bind_to_texture_rgba = value; 174 break; 175 176 case __DRI_ATTRIB_DOUBLE_BUFFER: 177 double_buffer = value; 178 break; 179 180 case __DRI_ATTRIB_RED_MASK: 181 dri_masks[0] = value; 182 break; 183 184 case __DRI_ATTRIB_GREEN_MASK: 185 dri_masks[1] = value; 186 break; 187 188 case __DRI_ATTRIB_BLUE_MASK: 189 dri_masks[2] = value; 190 break; 191 192 case __DRI_ATTRIB_ALPHA_MASK: 193 dri_masks[3] = value; 194 break; 195 196 default: 197 key = dri2_to_egl_attribute_map[attrib]; 198 if (key != 0) 199 _eglSetConfigKey(&base, key, value); 200 break; 201 } 202 } 203 204 if (attr_list) 205 for (i = 0; attr_list[i] != EGL_NONE; i += 2) 206 _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); 207 208 if (rgba_masks && memcmp(rgba_masks, dri_masks, sizeof(dri_masks))) 209 return NULL; 210 211 base.NativeRenderable = EGL_TRUE; 212 213 base.SurfaceType = surface_type; 214 if (surface_type & (EGL_PBUFFER_BIT | 215 (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { 216 base.BindToTextureRGB = bind_to_texture_rgb; 217 if (base.AlphaSize > 0) 218 base.BindToTextureRGBA = bind_to_texture_rgba; 219 } 220 221 base.RenderableType = disp->ClientAPIs; 222 base.Conformant = disp->ClientAPIs; 223 224 base.MinSwapInterval = dri2_dpy->min_swap_interval; 225 base.MaxSwapInterval = dri2_dpy->max_swap_interval; 226 227 if (!_eglValidateConfig(&base, EGL_FALSE)) { 228 _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); 229 return NULL; 230 } 231 232 config_id = base.ConfigID; 233 base.ConfigID = EGL_DONT_CARE; 234 base.SurfaceType = EGL_DONT_CARE; 235 num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, 236 (_EGLArrayForEach) dri2_match_config, &base); 237 238 if (num_configs == 1) { 239 conf = (struct dri2_egl_config *) matching_config; 240 241 if (double_buffer && !conf->dri_double_config) 242 conf->dri_double_config = dri_config; 243 else if (!double_buffer && !conf->dri_single_config) 244 conf->dri_single_config = dri_config; 245 else 246 /* a similar config type is already added (unlikely) => discard */ 247 return NULL; 248 } 249 else if (num_configs == 0) { 250 conf = malloc(sizeof *conf); 251 if (conf == NULL) 252 return NULL; 253 254 memcpy(&conf->base, &base, sizeof base); 255 if (double_buffer) { 256 conf->dri_double_config = dri_config; 257 conf->dri_single_config = NULL; 258 } else { 259 conf->dri_single_config = dri_config; 260 conf->dri_double_config = NULL; 261 } 262 conf->base.SurfaceType = 0; 263 conf->base.ConfigID = config_id; 264 265 _eglLinkConfig(&conf->base); 266 } 267 else { 268 assert(0); 269 return NULL; 270 } 271 272 if (double_buffer) { 273 surface_type &= ~EGL_PIXMAP_BIT; 274 } 275 276 conf->base.SurfaceType |= surface_type; 277 278 return conf; 279} 280 281__DRIimage * 282dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 283{ 284 _EGLDisplay *disp = data; 285 struct dri2_egl_image *dri2_img; 286 _EGLImage *img; 287 288 (void) screen; 289 290 img = _eglLookupImage(image, disp); 291 if (img == NULL) { 292 _eglError(EGL_BAD_PARAMETER, "dri2_lookup_egl_image"); 293 return NULL; 294 } 295 296 dri2_img = dri2_egl_image(image); 297 298 return dri2_img->dri_image; 299} 300 301const __DRIimageLookupExtension image_lookup_extension = { 302 .base = { __DRI_IMAGE_LOOKUP, 1 }, 303 304 .lookupEGLImage = dri2_lookup_egl_image 305}; 306 307struct dri2_extension_match { 308 const char *name; 309 int version; 310 int offset; 311}; 312 313static struct dri2_extension_match dri2_driver_extensions[] = { 314 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 315 { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) }, 316 { NULL, 0, 0 } 317}; 318 319static struct dri2_extension_match dri2_core_extensions[] = { 320 { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, 321 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 322 { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 323 { NULL, 0, 0 } 324}; 325 326static struct dri2_extension_match swrast_driver_extensions[] = { 327 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 328 { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, 329 { NULL, 0, 0 } 330}; 331 332static struct dri2_extension_match swrast_core_extensions[] = { 333 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 334 { NULL, 0, 0 } 335}; 336 337static EGLBoolean 338dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, 339 struct dri2_extension_match *matches, 340 const __DRIextension **extensions) 341{ 342 int i, j, ret = EGL_TRUE; 343 void *field; 344 345 for (i = 0; extensions[i]; i++) { 346 _eglLog(_EGL_DEBUG, "DRI2: found extension `%s'", extensions[i]->name); 347 for (j = 0; matches[j].name; j++) { 348 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 349 extensions[i]->version >= matches[j].version) { 350 field = ((char *) dri2_dpy + matches[j].offset); 351 *(const __DRIextension **) field = extensions[i]; 352 _eglLog(_EGL_INFO, "DRI2: found extension %s version %d", 353 extensions[i]->name, extensions[i]->version); 354 } 355 } 356 } 357 358 for (j = 0; matches[j].name; j++) { 359 field = ((char *) dri2_dpy + matches[j].offset); 360 if (*(const __DRIextension **) field == NULL) { 361 _eglLog(_EGL_WARNING, "DRI2: did not find extension %s version %d", 362 matches[j].name, matches[j].version); 363 ret = EGL_FALSE; 364 } 365 } 366 367 return ret; 368} 369 370static const __DRIextension ** 371dri2_open_driver(_EGLDisplay *disp) 372{ 373 struct dri2_egl_display *dri2_dpy = disp->DriverData; 374 const __DRIextension **extensions = NULL; 375 char path[PATH_MAX], *search_paths, *p, *next, *end; 376 char *get_extensions_name; 377 const __DRIextension **(*get_extensions)(void); 378 379 search_paths = NULL; 380 if (geteuid() == getuid()) { 381 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH */ 382 search_paths = getenv("LIBGL_DRIVERS_PATH"); 383 } 384 if (search_paths == NULL) 385 search_paths = DEFAULT_DRIVER_DIR; 386 387 dri2_dpy->driver = NULL; 388 end = search_paths + strlen(search_paths); 389 for (p = search_paths; p < end && dri2_dpy->driver == NULL; p = next + 1) { 390 int len; 391 next = strchr(p, ':'); 392 if (next == NULL) 393 next = end; 394 395 len = next - p; 396#if GLX_USE_TLS 397 snprintf(path, sizeof path, 398 "%.*s/tls/%s_dri.so", len, p, dri2_dpy->driver_name); 399 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 400#endif 401 if (dri2_dpy->driver == NULL) { 402 snprintf(path, sizeof path, 403 "%.*s/%s_dri.so", len, p, dri2_dpy->driver_name); 404 dri2_dpy->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 405 if (dri2_dpy->driver == NULL) 406 _eglLog(_EGL_DEBUG, "failed to open %s: %s\n", path, dlerror()); 407 } 408 /* not need continue to loop all paths once the driver is found */ 409 if (dri2_dpy->driver != NULL) 410 break; 411 } 412 413 if (dri2_dpy->driver == NULL) { 414 _eglLog(_EGL_WARNING, 415 "DRI2: failed to open %s (search paths %s)", 416 dri2_dpy->driver_name, search_paths); 417 return NULL; 418 } 419 420 _eglLog(_EGL_DEBUG, "DRI2: dlopen(%s)", path); 421 422 if (asprintf(&get_extensions_name, "%s_%s", 423 __DRI_DRIVER_GET_EXTENSIONS, dri2_dpy->driver_name) != -1) { 424 get_extensions = dlsym(dri2_dpy->driver, get_extensions_name); 425 if (get_extensions) { 426 extensions = get_extensions(); 427 } else { 428 _eglLog(_EGL_DEBUG, "driver does not expose %s(): %s\n", 429 get_extensions_name, dlerror()); 430 } 431 free(get_extensions_name); 432 } 433 434 if (!extensions) 435 extensions = dlsym(dri2_dpy->driver, __DRI_DRIVER_EXTENSIONS); 436 if (extensions == NULL) { 437 _eglLog(_EGL_WARNING, 438 "DRI2: driver exports no extensions (%s)", dlerror()); 439 dlclose(dri2_dpy->driver); 440 } 441 442 return extensions; 443} 444 445EGLBoolean 446dri2_load_driver(_EGLDisplay *disp) 447{ 448 struct dri2_egl_display *dri2_dpy = disp->DriverData; 449 const __DRIextension **extensions; 450 451 extensions = dri2_open_driver(disp); 452 if (!extensions) 453 return EGL_FALSE; 454 455 if (!dri2_bind_extensions(dri2_dpy, dri2_driver_extensions, extensions)) { 456 dlclose(dri2_dpy->driver); 457 return EGL_FALSE; 458 } 459 dri2_dpy->driver_extensions = extensions; 460 461 return EGL_TRUE; 462} 463 464EGLBoolean 465dri2_load_driver_swrast(_EGLDisplay *disp) 466{ 467 struct dri2_egl_display *dri2_dpy = disp->DriverData; 468 const __DRIextension **extensions; 469 470 extensions = dri2_open_driver(disp); 471 if (!extensions) 472 return EGL_FALSE; 473 474 if (!dri2_bind_extensions(dri2_dpy, swrast_driver_extensions, extensions)) { 475 dlclose(dri2_dpy->driver); 476 return EGL_FALSE; 477 } 478 dri2_dpy->driver_extensions = extensions; 479 480 return EGL_TRUE; 481} 482 483void 484dri2_setup_screen(_EGLDisplay *disp) 485{ 486 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 487 unsigned int api_mask; 488 489 if (dri2_dpy->dri2) { 490 api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 491 } else { 492 assert(dri2_dpy->swrast); 493 api_mask = 1 << __DRI_API_OPENGL | 494 1 << __DRI_API_GLES | 495 1 << __DRI_API_GLES2 | 496 1 << __DRI_API_GLES3; 497 } 498 499 disp->ClientAPIs = 0; 500 if (api_mask & (1 <<__DRI_API_OPENGL)) 501 disp->ClientAPIs |= EGL_OPENGL_BIT; 502 if (api_mask & (1 <<__DRI_API_GLES)) 503 disp->ClientAPIs |= EGL_OPENGL_ES_BIT; 504 if (api_mask & (1 << __DRI_API_GLES2)) 505 disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; 506 if (api_mask & (1 << __DRI_API_GLES3)) 507 disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR; 508 509 assert(dri2_dpy->dri2 || dri2_dpy->swrast); 510 disp->Extensions.KHR_surfaceless_context = EGL_TRUE; 511 disp->Extensions.MESA_configless_context = EGL_TRUE; 512 513 if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) { 514 disp->Extensions.KHR_create_context = EGL_TRUE; 515 516 if (dri2_dpy->robustness) 517 disp->Extensions.EXT_create_context_robustness = EGL_TRUE; 518 } 519 520 if (dri2_dpy->image) { 521 if (dri2_dpy->image->base.version >= 10 && 522 dri2_dpy->image->getCapabilities != NULL) { 523 int capabilities; 524 525 capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); 526 disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; 527 } else 528 disp->Extensions.MESA_drm_image = EGL_TRUE; 529 530 disp->Extensions.KHR_image_base = EGL_TRUE; 531 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 532 if (dri2_dpy->image->base.version >= 5 && 533 dri2_dpy->image->createImageFromTexture) { 534 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; 535 disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE; 536 } 537#ifdef HAVE_DRM_PLATFORM 538 if (dri2_dpy->image->base.version >= 8 && 539 dri2_dpy->image->createImageFromDmaBufs) { 540 disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE; 541 } 542#endif 543 } 544} 545 546EGLBoolean 547dri2_create_screen(_EGLDisplay *disp) 548{ 549 const __DRIextension **extensions; 550 struct dri2_egl_display *dri2_dpy; 551 552 dri2_dpy = disp->DriverData; 553 554 if (dri2_dpy->dri2) { 555 if (dri2_dpy->dri2->base.version >= 4) { 556 dri2_dpy->dri_screen = 557 dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd, 558 dri2_dpy->extensions, 559 dri2_dpy->driver_extensions, 560 &dri2_dpy->driver_configs, disp); 561 } else { 562 dri2_dpy->dri_screen = 563 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, 564 dri2_dpy->extensions, 565 &dri2_dpy->driver_configs, disp); 566 } 567 } else { 568 assert(dri2_dpy->swrast); 569 if (dri2_dpy->swrast->base.version >= 4) { 570 dri2_dpy->dri_screen = 571 dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->extensions, 572 dri2_dpy->driver_extensions, 573 &dri2_dpy->driver_configs, disp); 574 } else { 575 dri2_dpy->dri_screen = 576 dri2_dpy->swrast->createNewScreen(0, dri2_dpy->extensions, 577 &dri2_dpy->driver_configs, disp); 578 } 579 } 580 581 if (dri2_dpy->dri_screen == NULL) { 582 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 583 return EGL_FALSE; 584 } 585 586 dri2_dpy->own_dri_screen = 1; 587 588 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 589 590 if (dri2_dpy->dri2) { 591 unsigned i; 592 593 if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions)) 594 goto cleanup_dri_screen; 595 596 for (i = 0; extensions[i]; i++) { 597 if (strcmp(extensions[i]->name, __DRI2_ROBUSTNESS) == 0) { 598 dri2_dpy->robustness = (__DRIrobustnessExtension *) extensions[i]; 599 } 600 if (strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0) { 601 dri2_dpy->config = (__DRI2configQueryExtension *) extensions[i]; 602 } 603 } 604 } else { 605 assert(dri2_dpy->swrast); 606 if (!dri2_bind_extensions(dri2_dpy, swrast_core_extensions, extensions)) 607 goto cleanup_dri_screen; 608 } 609 610 dri2_setup_screen(disp); 611 612 return EGL_TRUE; 613 614 cleanup_dri_screen: 615 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 616 617 return EGL_FALSE; 618} 619 620/** 621 * Called via eglInitialize(), GLX_drv->API.Initialize(). 622 */ 623static EGLBoolean 624dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp) 625{ 626 /* not until swrast_dri is supported */ 627 if (disp->Options.UseFallback) 628 return EGL_FALSE; 629 630 switch (disp->Platform) { 631#ifdef HAVE_X11_PLATFORM 632 case _EGL_PLATFORM_X11: 633 if (disp->Options.TestOnly) 634 return EGL_TRUE; 635 return dri2_initialize_x11(drv, disp); 636#endif 637 638#ifdef HAVE_DRM_PLATFORM 639 case _EGL_PLATFORM_DRM: 640 if (disp->Options.TestOnly) 641 return EGL_TRUE; 642 return dri2_initialize_drm(drv, disp); 643#endif 644#ifdef HAVE_WAYLAND_PLATFORM 645 case _EGL_PLATFORM_WAYLAND: 646 if (disp->Options.TestOnly) 647 return EGL_TRUE; 648 return dri2_initialize_wayland(drv, disp); 649#endif 650#ifdef HAVE_ANDROID_PLATFORM 651 case _EGL_PLATFORM_ANDROID: 652 if (disp->Options.TestOnly) 653 return EGL_TRUE; 654 return dri2_initialize_android(drv, disp); 655#endif 656 657 default: 658 return EGL_FALSE; 659 } 660} 661 662/** 663 * Called via eglTerminate(), drv->API.Terminate(). 664 */ 665static EGLBoolean 666dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp) 667{ 668 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 669 670 _eglReleaseDisplayResources(drv, disp); 671 _eglCleanupDisplay(disp); 672 673 if (dri2_dpy->own_dri_screen) 674 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 675 if (dri2_dpy->fd) 676 close(dri2_dpy->fd); 677 if (dri2_dpy->driver) 678 dlclose(dri2_dpy->driver); 679 free(dri2_dpy->device_name); 680 free(dri2_dpy->driver_name); 681 682 switch (disp->Platform) { 683#ifdef HAVE_X11_PLATFORM 684 case _EGL_PLATFORM_X11: 685 if (dri2_dpy->own_device) { 686 xcb_disconnect(dri2_dpy->conn); 687 } 688 break; 689#endif 690#ifdef HAVE_DRM_PLATFORM 691 case _EGL_PLATFORM_DRM: 692 if (dri2_dpy->own_device) { 693 gbm_device_destroy(&dri2_dpy->gbm_dri->base.base); 694 } 695 break; 696#endif 697#ifdef HAVE_WAYLAND_PLATFORM 698 case _EGL_PLATFORM_WAYLAND: 699 wl_drm_destroy(dri2_dpy->wl_drm); 700 if (dri2_dpy->own_device) { 701 wl_display_disconnect(dri2_dpy->wl_dpy); 702 } 703 break; 704#endif 705 default: 706 break; 707 } 708 709 free(dri2_dpy); 710 disp->DriverData = NULL; 711 712 return EGL_TRUE; 713} 714 715/** 716 * Set the error code after a call to 717 * dri2_egl_display::dri2::createContextAttribs. 718 */ 719static void 720dri2_create_context_attribs_error(int dri_error) 721{ 722 EGLint egl_error; 723 724 switch (dri_error) { 725 case __DRI_CTX_ERROR_SUCCESS: 726 return; 727 728 case __DRI_CTX_ERROR_NO_MEMORY: 729 egl_error = EGL_BAD_ALLOC; 730 break; 731 732 /* From the EGL_KHR_create_context spec, section "Errors": 733 * 734 * * If <config> does not support a client API context compatible 735 * with the requested API major and minor version, [...] context flags, 736 * and context reset notification behavior (for client API types where 737 * these attributes are supported), then an EGL_BAD_MATCH error is 738 * generated. 739 * 740 * * If an OpenGL ES context is requested and the values for 741 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 742 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 743 * is not defined, than an EGL_BAD_MATCH error is generated. 744 * 745 * * If an OpenGL context is requested, the requested version is 746 * greater than 3.2, and the value for attribute 747 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any 748 * bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and 749 * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than 750 * one of these bits set; or if the implementation does not support 751 * the requested profile, then an EGL_BAD_MATCH error is generated. 752 */ 753 case __DRI_CTX_ERROR_BAD_API: 754 case __DRI_CTX_ERROR_BAD_VERSION: 755 case __DRI_CTX_ERROR_BAD_FLAG: 756 egl_error = EGL_BAD_MATCH; 757 break; 758 759 /* From the EGL_KHR_create_context spec, section "Errors": 760 * 761 * * If an attribute name or attribute value in <attrib_list> is not 762 * recognized (including unrecognized bits in bitmask attributes), 763 * then an EGL_BAD_ATTRIBUTE error is generated." 764 */ 765 case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE: 766 case __DRI_CTX_ERROR_UNKNOWN_FLAG: 767 egl_error = EGL_BAD_ATTRIBUTE; 768 break; 769 770 default: 771 assert(0); 772 egl_error = EGL_BAD_MATCH; 773 break; 774 } 775 776 _eglError(egl_error, "dri2_create_context"); 777} 778 779/** 780 * Called via eglCreateContext(), drv->API.CreateContext(). 781 */ 782static _EGLContext * 783dri2_create_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, 784 _EGLContext *share_list, const EGLint *attrib_list) 785{ 786 struct dri2_egl_context *dri2_ctx; 787 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 788 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 789 __DRIcontext *shared = 790 dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; 791 struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 792 const __DRIconfig *dri_config; 793 int api; 794 795 (void) drv; 796 797 dri2_ctx = malloc(sizeof *dri2_ctx); 798 if (!dri2_ctx) { 799 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 800 return NULL; 801 } 802 803 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 804 goto cleanup; 805 806 switch (dri2_ctx->base.ClientAPI) { 807 case EGL_OPENGL_ES_API: 808 switch (dri2_ctx->base.ClientMajorVersion) { 809 case 1: 810 api = __DRI_API_GLES; 811 break; 812 case 2: 813 api = __DRI_API_GLES2; 814 break; 815 case 3: 816 api = __DRI_API_GLES3; 817 break; 818 default: 819 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 820 free(dri2_ctx); 821 return NULL; 822 } 823 break; 824 case EGL_OPENGL_API: 825 if ((dri2_ctx->base.ClientMajorVersion >= 4 826 || (dri2_ctx->base.ClientMajorVersion == 3 827 && dri2_ctx->base.ClientMinorVersion >= 2)) 828 && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) 829 api = __DRI_API_OPENGL_CORE; 830 else 831 api = __DRI_API_OPENGL; 832 break; 833 default: 834 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 835 free(dri2_ctx); 836 return NULL; 837 } 838 839 if (conf != NULL) { 840 /* The config chosen here isn't necessarily 841 * used for surfaces later. 842 * A pixmap surface will use the single config. 843 * This opportunity depends on disabling the 844 * doubleBufferMode check in 845 * src/mesa/main/context.c:check_compatible() 846 */ 847 if (dri2_config->dri_double_config) 848 dri_config = dri2_config->dri_double_config; 849 else 850 dri_config = dri2_config->dri_single_config; 851 852 /* EGL_WINDOW_BIT is set only when there is a dri_double_config. This 853 * makes sure the back buffer will always be used. 854 */ 855 if (conf->SurfaceType & EGL_WINDOW_BIT) 856 dri2_ctx->base.WindowRenderBuffer = EGL_BACK_BUFFER; 857 } 858 else 859 dri_config = NULL; 860 861 if (dri2_dpy->dri2) { 862 if (dri2_dpy->dri2->base.version >= 3) { 863 unsigned error; 864 unsigned num_attribs = 0; 865 uint32_t ctx_attribs[8]; 866 867 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 868 ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMajorVersion; 869 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 870 ctx_attribs[num_attribs++] = dri2_ctx->base.ClientMinorVersion; 871 872 if (dri2_ctx->base.Flags != 0) { 873 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 874 * extension, don't even try to send it the robust-access flag. 875 * It may explode. Instead, generate the required EGL error here. 876 */ 877 if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0 878 && !dri2_dpy->robustness) { 879 _eglError(EGL_BAD_MATCH, "eglCreateContext"); 880 goto cleanup; 881 } 882 883 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_FLAGS; 884 ctx_attribs[num_attribs++] = dri2_ctx->base.Flags; 885 } 886 887 if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) { 888 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 889 * extension, don't even try to send it a reset strategy. It may 890 * explode. Instead, generate the required EGL error here. 891 */ 892 if (!dri2_dpy->robustness) { 893 _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 894 goto cleanup; 895 } 896 897 ctx_attribs[num_attribs++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 898 ctx_attribs[num_attribs++] = __DRI_CTX_RESET_LOSE_CONTEXT; 899 } 900 901 assert(num_attribs <= ARRAY_SIZE(ctx_attribs)); 902 903 dri2_ctx->dri_context = 904 dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen, 905 api, 906 dri_config, 907 shared, 908 num_attribs / 2, 909 ctx_attribs, 910 & error, 911 dri2_ctx); 912 dri2_create_context_attribs_error(error); 913 } else { 914 dri2_ctx->dri_context = 915 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 916 api, 917 dri_config, 918 shared, 919 dri2_ctx); 920 } 921 } else { 922 assert(dri2_dpy->swrast); 923 dri2_ctx->dri_context = 924 dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 925 api, 926 dri_config, 927 shared, 928 dri2_ctx); 929 } 930 931 if (!dri2_ctx->dri_context) 932 goto cleanup; 933 934 return &dri2_ctx->base; 935 936 cleanup: 937 free(dri2_ctx); 938 return NULL; 939} 940 941/** 942 * Called via eglDestroyContext(), drv->API.DestroyContext(). 943 */ 944static EGLBoolean 945dri2_destroy_context(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 946{ 947 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 948 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 949 950 if (_eglPutContext(ctx)) { 951 dri2_dpy->core->destroyContext(dri2_ctx->dri_context); 952 free(dri2_ctx); 953 } 954 955 return EGL_TRUE; 956} 957 958/** 959 * Called via eglMakeCurrent(), drv->API.MakeCurrent(). 960 */ 961static EGLBoolean 962dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, 963 _EGLSurface *rsurf, _EGLContext *ctx) 964{ 965 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 966 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 967 struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf); 968 struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf); 969 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 970 _EGLContext *old_ctx; 971 _EGLSurface *old_dsurf, *old_rsurf; 972 __DRIdrawable *ddraw, *rdraw; 973 __DRIcontext *cctx; 974 975 /* make new bindings */ 976 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 977 return EGL_FALSE; 978 979 /* flush before context switch */ 980 if (old_ctx && dri2_drv->glFlush) 981 dri2_drv->glFlush(); 982 983 ddraw = (dri2_dsurf) ? dri2_dsurf->dri_drawable : NULL; 984 rdraw = (dri2_rsurf) ? dri2_rsurf->dri_drawable : NULL; 985 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 986 987 if (old_ctx) { 988 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 989 dri2_dpy->core->unbindContext(old_cctx); 990 } 991 992 if ((cctx == NULL && ddraw == NULL && rdraw == NULL) || 993 dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 994 if (old_dsurf) 995 drv->API.DestroySurface(drv, disp, old_dsurf); 996 if (old_rsurf) 997 drv->API.DestroySurface(drv, disp, old_rsurf); 998 if (old_ctx) 999 drv->API.DestroyContext(drv, disp, old_ctx); 1000 1001 return EGL_TRUE; 1002 } else { 1003 /* undo the previous _eglBindContext */ 1004 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf); 1005 assert(&dri2_ctx->base == ctx && 1006 &dri2_dsurf->base == dsurf && 1007 &dri2_rsurf->base == rsurf); 1008 1009 _eglPutSurface(dsurf); 1010 _eglPutSurface(rsurf); 1011 _eglPutContext(ctx); 1012 1013 _eglPutSurface(old_dsurf); 1014 _eglPutSurface(old_rsurf); 1015 _eglPutContext(old_ctx); 1016 1017 return EGL_FALSE; 1018 } 1019} 1020 1021/* 1022 * Called from eglGetProcAddress() via drv->API.GetProcAddress(). 1023 */ 1024static _EGLProc 1025dri2_get_proc_address(_EGLDriver *drv, const char *procname) 1026{ 1027 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 1028 1029 return dri2_drv->get_proc_address(procname); 1030} 1031 1032static _EGLSurface* 1033dri2_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, 1034 _EGLConfig *conf, void *native_window, 1035 const EGLint *attrib_list) 1036{ 1037 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1038 return dri2_dpy->vtbl->create_window_surface(drv, dpy, conf, native_window, 1039 attrib_list); 1040} 1041 1042static _EGLSurface* 1043dri2_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, 1044 _EGLConfig *conf, void *native_pixmap, 1045 const EGLint *attrib_list) 1046{ 1047 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1048 return dri2_dpy->vtbl->create_pixmap_surface(drv, dpy, conf, native_pixmap, 1049 attrib_list); 1050} 1051 1052static _EGLSurface* 1053dri2_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, 1054 _EGLConfig *conf, const EGLint *attrib_list) 1055{ 1056 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1057 return dri2_dpy->vtbl->create_pbuffer_surface(drv, dpy, conf, attrib_list); 1058} 1059 1060static EGLBoolean 1061dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) 1062{ 1063 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1064 return dri2_dpy->vtbl->destroy_surface(drv, dpy, surf); 1065} 1066 1067static EGLBoolean 1068dri2_swap_interval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 1069 EGLint interval) 1070{ 1071 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1072 return dri2_dpy->vtbl->swap_interval(drv, dpy, surf, interval); 1073} 1074 1075static EGLBoolean 1076dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) 1077{ 1078 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1079 return dri2_dpy->vtbl->swap_buffers(drv, dpy, surf); 1080} 1081 1082static EGLBoolean 1083dri2_swap_buffers_with_damage(_EGLDriver *drv, _EGLDisplay *dpy, 1084 _EGLSurface *surf, 1085 const EGLint *rects, EGLint n_rects) 1086{ 1087 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1088 return dri2_dpy->vtbl->swap_buffers_with_damage(drv, dpy, surf, 1089 rects, n_rects); 1090} 1091 1092static EGLBoolean 1093dri2_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 1094 EGLint numRects, const EGLint *rects) 1095{ 1096 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1097 return dri2_dpy->vtbl->swap_buffers_region(drv, dpy, surf, numRects, rects); 1098} 1099 1100static EGLBoolean 1101dri2_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 1102 EGLint x, EGLint y, EGLint width, EGLint height) 1103{ 1104 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1105 return dri2_dpy->vtbl->post_sub_buffer(drv, dpy, surf, x, y, width, height); 1106} 1107 1108static EGLBoolean 1109dri2_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 1110 void *native_pixmap_target) 1111{ 1112 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1113 return dri2_dpy->vtbl->copy_buffers(drv, dpy, surf, native_pixmap_target); 1114} 1115 1116static EGLint 1117dri2_query_buffer_age(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) 1118{ 1119 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1120 return dri2_dpy->vtbl->query_buffer_age(drv, dpy, surf); 1121} 1122 1123static EGLBoolean 1124dri2_wait_client(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *ctx) 1125{ 1126 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1127 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(ctx->DrawSurface); 1128 1129 (void) drv; 1130 1131 /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 1132 * we need to copy fake to real here.*/ 1133 1134 if (dri2_dpy->flush != NULL) 1135 dri2_dpy->flush->flush(dri2_surf->dri_drawable); 1136 1137 return EGL_TRUE; 1138} 1139 1140static EGLBoolean 1141dri2_wait_native(_EGLDriver *drv, _EGLDisplay *disp, EGLint engine) 1142{ 1143 (void) drv; 1144 (void) disp; 1145 1146 if (engine != EGL_CORE_NATIVE_ENGINE) 1147 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 1148 /* glXWaitX(); */ 1149 1150 return EGL_TRUE; 1151} 1152 1153static EGLBoolean 1154dri2_bind_tex_image(_EGLDriver *drv, 1155 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 1156{ 1157 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1158 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1159 struct dri2_egl_context *dri2_ctx; 1160 _EGLContext *ctx; 1161 GLint format, target; 1162 1163 ctx = _eglGetCurrentContext(); 1164 dri2_ctx = dri2_egl_context(ctx); 1165 1166 if (!_eglBindTexImage(drv, disp, surf, buffer)) 1167 return EGL_FALSE; 1168 1169 switch (dri2_surf->base.TextureFormat) { 1170 case EGL_TEXTURE_RGB: 1171 format = __DRI_TEXTURE_FORMAT_RGB; 1172 break; 1173 case EGL_TEXTURE_RGBA: 1174 format = __DRI_TEXTURE_FORMAT_RGBA; 1175 break; 1176 default: 1177 assert(0); 1178 } 1179 1180 switch (dri2_surf->base.TextureTarget) { 1181 case EGL_TEXTURE_2D: 1182 target = GL_TEXTURE_2D; 1183 break; 1184 default: 1185 assert(0); 1186 } 1187 1188 (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context, 1189 target, format, 1190 dri2_surf->dri_drawable); 1191 1192 return EGL_TRUE; 1193} 1194 1195static EGLBoolean 1196dri2_release_tex_image(_EGLDriver *drv, 1197 _EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 1198{ 1199 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1200 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1201 struct dri2_egl_context *dri2_ctx; 1202 _EGLContext *ctx; 1203 GLint target; 1204 1205 ctx = _eglGetCurrentContext(); 1206 dri2_ctx = dri2_egl_context(ctx); 1207 1208 if (!_eglReleaseTexImage(drv, disp, surf, buffer)) 1209 return EGL_FALSE; 1210 1211 switch (dri2_surf->base.TextureTarget) { 1212 case EGL_TEXTURE_2D: 1213 target = GL_TEXTURE_2D; 1214 break; 1215 default: 1216 assert(0); 1217 } 1218 1219 if (dri2_dpy->tex_buffer->base.version >= 3 && 1220 dri2_dpy->tex_buffer->releaseTexBuffer != NULL) { 1221 (*dri2_dpy->tex_buffer->releaseTexBuffer)(dri2_ctx->dri_context, 1222 target, 1223 dri2_surf->dri_drawable); 1224 } 1225 1226 return EGL_TRUE; 1227} 1228 1229static _EGLImage* 1230dri2_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, 1231 EGLenum target, EGLClientBuffer buffer, 1232 const EGLint *attr_list) 1233{ 1234 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1235 return dri2_dpy->vtbl->create_image(drv, dpy, ctx, target, buffer, 1236 attr_list); 1237} 1238 1239static _EGLImage * 1240dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image) 1241{ 1242 struct dri2_egl_image *dri2_img; 1243 1244 if (dri_image == NULL) { 1245 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1246 return NULL; 1247 } 1248 1249 dri2_img = malloc(sizeof *dri2_img); 1250 if (!dri2_img) { 1251 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 1252 return NULL; 1253 } 1254 1255 if (!_eglInitImage(&dri2_img->base, disp)) { 1256 free(dri2_img); 1257 return NULL; 1258 } 1259 1260 dri2_img->dri_image = dri_image; 1261 1262 return &dri2_img->base; 1263} 1264 1265static _EGLImage * 1266dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 1267 EGLClientBuffer buffer, 1268 const EGLint *attr_list) 1269{ 1270 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1271 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1272 GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 1273 __DRIimage *dri_image; 1274 1275 if (renderbuffer == 0) { 1276 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1277 return EGL_NO_IMAGE_KHR; 1278 } 1279 1280 dri_image = 1281 dri2_dpy->image->createImageFromRenderbuffer(dri2_ctx->dri_context, 1282 renderbuffer, NULL); 1283 1284 return dri2_create_image_from_dri(disp, dri_image); 1285} 1286 1287#ifdef HAVE_DRM_PLATFORM 1288static _EGLImage * 1289dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1290 EGLClientBuffer buffer, const EGLint *attr_list) 1291{ 1292 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1293 EGLint format, name, pitch, err; 1294 _EGLImageAttribs attrs; 1295 __DRIimage *dri_image; 1296 1297 name = (EGLint) (uintptr_t) buffer; 1298 1299 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1300 if (err != EGL_SUCCESS) 1301 return NULL; 1302 1303 if (attrs.Width <= 0 || attrs.Height <= 0 || 1304 attrs.DRMBufferStrideMESA <= 0) { 1305 _eglError(EGL_BAD_PARAMETER, 1306 "bad width, height or stride"); 1307 return NULL; 1308 } 1309 1310 switch (attrs.DRMBufferFormatMESA) { 1311 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1312 format = __DRI_IMAGE_FORMAT_ARGB8888; 1313 pitch = attrs.DRMBufferStrideMESA; 1314 break; 1315 default: 1316 _eglError(EGL_BAD_PARAMETER, 1317 "dri2_create_image_khr: unsupported pixmap depth"); 1318 return NULL; 1319 } 1320 1321 dri_image = 1322 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 1323 attrs.Width, 1324 attrs.Height, 1325 format, 1326 name, 1327 pitch, 1328 NULL); 1329 1330 return dri2_create_image_from_dri(disp, dri_image); 1331} 1332#endif 1333 1334#ifdef HAVE_WAYLAND_PLATFORM 1335 1336/* This structure describes how a wl_buffer maps to one or more 1337 * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the 1338 * offsets and strides of the planes in the buffer. This table maps a 1339 * wl_drm format code to a description of the planes in the buffer 1340 * that lets us create a __DRIimage for each of the planes. */ 1341 1342static const struct wl_drm_components_descriptor { 1343 uint32_t dri_components; 1344 EGLint components; 1345 int nplanes; 1346} wl_drm_components[] = { 1347 { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 }, 1348 { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 }, 1349 { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 }, 1350 { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 }, 1351 { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 }, 1352}; 1353 1354static _EGLImage * 1355dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 1356 EGLClientBuffer _buffer, 1357 const EGLint *attr_list) 1358{ 1359 struct wl_drm_buffer *buffer; 1360 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1361 const struct wl_drm_components_descriptor *f; 1362 __DRIimage *dri_image; 1363 _EGLImageAttribs attrs; 1364 EGLint err; 1365 int32_t plane; 1366 1367 buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, 1368 (struct wl_resource *) _buffer); 1369 if (!buffer) 1370 return NULL; 1371 1372 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1373 plane = attrs.PlaneWL; 1374 if (err != EGL_SUCCESS) { 1375 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 1376 return NULL; 1377 } 1378 1379 f = buffer->driver_format; 1380 if (plane < 0 || plane >= f->nplanes) { 1381 _eglError(EGL_BAD_PARAMETER, 1382 "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); 1383 return NULL; 1384 } 1385 1386 dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL); 1387 1388 if (dri_image == NULL) { 1389 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 1390 return NULL; 1391 } 1392 1393 return dri2_create_image_from_dri(disp, dri_image); 1394} 1395#endif 1396 1397static EGLBoolean 1398dri2_get_sync_values_chromium(_EGLDisplay *dpy, _EGLSurface *surf, 1399 EGLuint64KHR *ust, EGLuint64KHR *msc, 1400 EGLuint64KHR *sbc) 1401{ 1402 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1403 return dri2_dpy->vtbl->get_sync_values(dpy, surf, ust, msc, sbc); 1404} 1405 1406/** 1407 * Set the error code after a call to 1408 * dri2_egl_image::dri_image::createImageFromTexture. 1409 */ 1410static void 1411dri2_create_image_khr_texture_error(int dri_error) 1412{ 1413 EGLint egl_error; 1414 1415 switch (dri_error) { 1416 case __DRI_IMAGE_ERROR_SUCCESS: 1417 return; 1418 1419 case __DRI_IMAGE_ERROR_BAD_ALLOC: 1420 egl_error = EGL_BAD_ALLOC; 1421 break; 1422 1423 case __DRI_IMAGE_ERROR_BAD_MATCH: 1424 egl_error = EGL_BAD_MATCH; 1425 break; 1426 1427 case __DRI_IMAGE_ERROR_BAD_PARAMETER: 1428 egl_error = EGL_BAD_PARAMETER; 1429 break; 1430 1431 default: 1432 assert(0); 1433 egl_error = EGL_BAD_MATCH; 1434 break; 1435 } 1436 1437 _eglError(egl_error, "dri2_create_image_khr_texture"); 1438} 1439 1440static _EGLImage * 1441dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx, 1442 EGLenum target, 1443 EGLClientBuffer buffer, 1444 const EGLint *attr_list) 1445{ 1446 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1447 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1448 struct dri2_egl_image *dri2_img; 1449 GLuint texture = (GLuint) (uintptr_t) buffer; 1450 _EGLImageAttribs attrs; 1451 GLuint depth; 1452 GLenum gl_target; 1453 unsigned error; 1454 1455 if (texture == 0) { 1456 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1457 return EGL_NO_IMAGE_KHR; 1458 } 1459 1460 if (_eglParseImageAttribList(&attrs, disp, attr_list) != EGL_SUCCESS) 1461 return EGL_NO_IMAGE_KHR; 1462 1463 switch (target) { 1464 case EGL_GL_TEXTURE_2D_KHR: 1465 depth = 0; 1466 gl_target = GL_TEXTURE_2D; 1467 break; 1468 case EGL_GL_TEXTURE_3D_KHR: 1469 depth = attrs.GLTextureZOffset; 1470 gl_target = GL_TEXTURE_3D; 1471 break; 1472 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 1473 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 1474 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 1475 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 1476 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 1477 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 1478 depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR; 1479 gl_target = GL_TEXTURE_CUBE_MAP; 1480 break; 1481 default: 1482 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1483 return EGL_NO_IMAGE_KHR; 1484 } 1485 1486 dri2_img = malloc(sizeof *dri2_img); 1487 if (!dri2_img) { 1488 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1489 return EGL_NO_IMAGE_KHR; 1490 } 1491 1492 if (!_eglInitImage(&dri2_img->base, disp)) { 1493 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1494 free(dri2_img); 1495 return EGL_NO_IMAGE_KHR; 1496 } 1497 1498 dri2_img->dri_image = 1499 dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context, 1500 gl_target, 1501 texture, 1502 depth, 1503 attrs.GLTextureLevel, 1504 &error, 1505 dri2_img); 1506 dri2_create_image_khr_texture_error(error); 1507 1508 if (!dri2_img->dri_image) { 1509 free(dri2_img); 1510 return EGL_NO_IMAGE_KHR; 1511 } 1512 return &dri2_img->base; 1513} 1514 1515static struct wl_buffer* 1516dri2_create_wayland_buffer_from_image(_EGLDriver *drv, _EGLDisplay *dpy, 1517 _EGLImage *img) 1518{ 1519 struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy); 1520 return dri2_dpy->vtbl->create_wayland_buffer_from_image(drv, dpy, img); 1521} 1522 1523#ifdef HAVE_DRM_PLATFORM 1524static EGLBoolean 1525dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs) 1526{ 1527 unsigned i; 1528 1529 /** 1530 * The spec says: 1531 * 1532 * "Required attributes and their values are as follows: 1533 * 1534 * * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels 1535 * 1536 * * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified 1537 * by drm_fourcc.h and used as the pixel_format parameter of the 1538 * drm_mode_fb_cmd2 ioctl." 1539 * 1540 * and 1541 * 1542 * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 1543 * incomplete, EGL_BAD_PARAMETER is generated." 1544 */ 1545 if (attrs->Width <= 0 || attrs->Height <= 0 || 1546 !attrs->DMABufFourCC.IsPresent) { 1547 _eglError(EGL_BAD_PARAMETER, "attribute(s) missing"); 1548 return EGL_FALSE; 1549 } 1550 1551 /** 1552 * Also: 1553 * 1554 * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values 1555 * specified for a plane's pitch or offset isn't supported by EGL, 1556 * EGL_BAD_ACCESS is generated." 1557 */ 1558 for (i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) { 1559 if (attrs->DMABufPlanePitches[i].IsPresent && 1560 attrs->DMABufPlanePitches[i].Value <= 0) { 1561 _eglError(EGL_BAD_ACCESS, "invalid pitch"); 1562 return EGL_FALSE; 1563 } 1564 } 1565 1566 return EGL_TRUE; 1567} 1568 1569/* Returns the total number of file descriptors. Zero indicates an error. */ 1570static unsigned 1571dri2_check_dma_buf_format(const _EGLImageAttribs *attrs) 1572{ 1573 unsigned i, plane_n; 1574 1575 switch (attrs->DMABufFourCC.Value) { 1576 case DRM_FORMAT_RGB332: 1577 case DRM_FORMAT_BGR233: 1578 case DRM_FORMAT_XRGB4444: 1579 case DRM_FORMAT_XBGR4444: 1580 case DRM_FORMAT_RGBX4444: 1581 case DRM_FORMAT_BGRX4444: 1582 case DRM_FORMAT_ARGB4444: 1583 case DRM_FORMAT_ABGR4444: 1584 case DRM_FORMAT_RGBA4444: 1585 case DRM_FORMAT_BGRA4444: 1586 case DRM_FORMAT_XRGB1555: 1587 case DRM_FORMAT_XBGR1555: 1588 case DRM_FORMAT_RGBX5551: 1589 case DRM_FORMAT_BGRX5551: 1590 case DRM_FORMAT_ARGB1555: 1591 case DRM_FORMAT_ABGR1555: 1592 case DRM_FORMAT_RGBA5551: 1593 case DRM_FORMAT_BGRA5551: 1594 case DRM_FORMAT_RGB565: 1595 case DRM_FORMAT_BGR565: 1596 case DRM_FORMAT_RGB888: 1597 case DRM_FORMAT_BGR888: 1598 case DRM_FORMAT_XRGB8888: 1599 case DRM_FORMAT_XBGR8888: 1600 case DRM_FORMAT_RGBX8888: 1601 case DRM_FORMAT_BGRX8888: 1602 case DRM_FORMAT_ARGB8888: 1603 case DRM_FORMAT_ABGR8888: 1604 case DRM_FORMAT_RGBA8888: 1605 case DRM_FORMAT_BGRA8888: 1606 case DRM_FORMAT_XRGB2101010: 1607 case DRM_FORMAT_XBGR2101010: 1608 case DRM_FORMAT_RGBX1010102: 1609 case DRM_FORMAT_BGRX1010102: 1610 case DRM_FORMAT_ARGB2101010: 1611 case DRM_FORMAT_ABGR2101010: 1612 case DRM_FORMAT_RGBA1010102: 1613 case DRM_FORMAT_BGRA1010102: 1614 case DRM_FORMAT_YUYV: 1615 case DRM_FORMAT_YVYU: 1616 case DRM_FORMAT_UYVY: 1617 case DRM_FORMAT_VYUY: 1618 plane_n = 1; 1619 break; 1620 case DRM_FORMAT_NV12: 1621 case DRM_FORMAT_NV21: 1622 case DRM_FORMAT_NV16: 1623 case DRM_FORMAT_NV61: 1624 plane_n = 2; 1625 break; 1626 case DRM_FORMAT_YUV410: 1627 case DRM_FORMAT_YVU410: 1628 case DRM_FORMAT_YUV411: 1629 case DRM_FORMAT_YVU411: 1630 case DRM_FORMAT_YUV420: 1631 case DRM_FORMAT_YVU420: 1632 case DRM_FORMAT_YUV422: 1633 case DRM_FORMAT_YVU422: 1634 case DRM_FORMAT_YUV444: 1635 case DRM_FORMAT_YVU444: 1636 plane_n = 3; 1637 break; 1638 default: 1639 _eglError(EGL_BAD_ATTRIBUTE, "invalid format"); 1640 return 0; 1641 } 1642 1643 /** 1644 * The spec says: 1645 * 1646 * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 1647 * incomplete, EGL_BAD_PARAMETER is generated." 1648 */ 1649 for (i = 0; i < plane_n; ++i) { 1650 if (!attrs->DMABufPlaneFds[i].IsPresent || 1651 !attrs->DMABufPlaneOffsets[i].IsPresent || 1652 !attrs->DMABufPlanePitches[i].IsPresent) { 1653 _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing"); 1654 return 0; 1655 } 1656 } 1657 1658 /** 1659 * The spec also says: 1660 * 1661 * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT 1662 * attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is 1663 * generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_* 1664 * attributes are specified." 1665 */ 1666 for (i = plane_n; i < 3; ++i) { 1667 if (attrs->DMABufPlaneFds[i].IsPresent || 1668 attrs->DMABufPlaneOffsets[i].IsPresent || 1669 attrs->DMABufPlanePitches[i].IsPresent) { 1670 _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes"); 1671 return 0; 1672 } 1673 } 1674 1675 return plane_n; 1676} 1677 1678/** 1679 * The spec says: 1680 * 1681 * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the 1682 * EGL will take a reference to the dma_buf(s) which it will release at any 1683 * time while the EGLDisplay is initialized. It is the responsibility of the 1684 * application to close the dma_buf file descriptors." 1685 * 1686 * Therefore we must never close or otherwise modify the file descriptors. 1687 */ 1688static _EGLImage * 1689dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, 1690 EGLClientBuffer buffer, const EGLint *attr_list) 1691{ 1692 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1693 _EGLImage *res; 1694 EGLint err; 1695 _EGLImageAttribs attrs; 1696 __DRIimage *dri_image; 1697 unsigned num_fds; 1698 unsigned i; 1699 int fds[3]; 1700 int pitches[3]; 1701 int offsets[3]; 1702 unsigned error; 1703 1704 /** 1705 * The spec says: 1706 * 1707 * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the 1708 * error EGL_BAD_PARAMETER is generated." 1709 */ 1710 if (buffer != NULL) { 1711 _eglError(EGL_BAD_PARAMETER, "buffer not NULL"); 1712 return NULL; 1713 } 1714 1715 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1716 if (err != EGL_SUCCESS) { 1717 _eglError(err, "bad attribute"); 1718 return NULL; 1719 } 1720 1721 if (!dri2_check_dma_buf_attribs(&attrs)) 1722 return NULL; 1723 1724 num_fds = dri2_check_dma_buf_format(&attrs); 1725 if (!num_fds) 1726 return NULL; 1727 1728 for (i = 0; i < num_fds; ++i) { 1729 fds[i] = attrs.DMABufPlaneFds[i].Value; 1730 pitches[i] = attrs.DMABufPlanePitches[i].Value; 1731 offsets[i] = attrs.DMABufPlaneOffsets[i].Value; 1732 } 1733 1734 dri_image = 1735 dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, 1736 attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 1737 fds, num_fds, pitches, offsets, 1738 attrs.DMABufYuvColorSpaceHint.Value, 1739 attrs.DMABufSampleRangeHint.Value, 1740 attrs.DMABufChromaHorizontalSiting.Value, 1741 attrs.DMABufChromaVerticalSiting.Value, 1742 &error, 1743 NULL); 1744 dri2_create_image_khr_texture_error(error); 1745 1746 if (!dri_image) 1747 return EGL_NO_IMAGE_KHR; 1748 1749 res = dri2_create_image_from_dri(disp, dri_image); 1750 1751 return res; 1752} 1753#endif 1754 1755_EGLImage * 1756dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp, 1757 _EGLContext *ctx, EGLenum target, 1758 EGLClientBuffer buffer, const EGLint *attr_list) 1759{ 1760 (void) drv; 1761 1762 switch (target) { 1763 case EGL_GL_TEXTURE_2D_KHR: 1764 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 1765 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 1766 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 1767 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 1768 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 1769 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 1770 return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list); 1771 case EGL_GL_RENDERBUFFER_KHR: 1772 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 1773#ifdef HAVE_DRM_PLATFORM 1774 case EGL_DRM_BUFFER_MESA: 1775 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 1776#endif 1777#ifdef HAVE_WAYLAND_PLATFORM 1778 case EGL_WAYLAND_BUFFER_WL: 1779 return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 1780#endif 1781#ifdef HAVE_DRM_PLATFORM 1782 case EGL_LINUX_DMA_BUF_EXT: 1783 return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list); 1784#endif 1785 default: 1786 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 1787 return EGL_NO_IMAGE_KHR; 1788 } 1789} 1790 1791static EGLBoolean 1792dri2_destroy_image_khr(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *image) 1793{ 1794 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1795 struct dri2_egl_image *dri2_img = dri2_egl_image(image); 1796 1797 (void) drv; 1798 1799 dri2_dpy->image->destroyImage(dri2_img->dri_image); 1800 free(dri2_img); 1801 1802 return EGL_TRUE; 1803} 1804 1805#ifdef HAVE_DRM_PLATFORM 1806static _EGLImage * 1807dri2_create_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, 1808 const EGLint *attr_list) 1809{ 1810 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1811 struct dri2_egl_image *dri2_img; 1812 _EGLImageAttribs attrs; 1813 unsigned int dri_use, valid_mask; 1814 int format; 1815 EGLint err = EGL_SUCCESS; 1816 1817 (void) drv; 1818 1819 dri2_img = malloc(sizeof *dri2_img); 1820 if (!dri2_img) { 1821 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 1822 return EGL_NO_IMAGE_KHR; 1823 } 1824 1825 if (!attr_list) { 1826 err = EGL_BAD_PARAMETER; 1827 goto cleanup_img; 1828 } 1829 1830 if (!_eglInitImage(&dri2_img->base, disp)) { 1831 err = EGL_BAD_PARAMETER; 1832 goto cleanup_img; 1833 } 1834 1835 err = _eglParseImageAttribList(&attrs, disp, attr_list); 1836 if (err != EGL_SUCCESS) 1837 goto cleanup_img; 1838 1839 if (attrs.Width <= 0 || attrs.Height <= 0) { 1840 _eglLog(_EGL_WARNING, "bad width or height (%dx%d)", 1841 attrs.Width, attrs.Height); 1842 goto cleanup_img; 1843 } 1844 1845 switch (attrs.DRMBufferFormatMESA) { 1846 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 1847 format = __DRI_IMAGE_FORMAT_ARGB8888; 1848 break; 1849 default: 1850 _eglLog(_EGL_WARNING, "bad image format value 0x%04x", 1851 attrs.DRMBufferFormatMESA); 1852 goto cleanup_img; 1853 } 1854 1855 valid_mask = 1856 EGL_DRM_BUFFER_USE_SCANOUT_MESA | 1857 EGL_DRM_BUFFER_USE_SHARE_MESA | 1858 EGL_DRM_BUFFER_USE_CURSOR_MESA; 1859 if (attrs.DRMBufferUseMESA & ~valid_mask) { 1860 _eglLog(_EGL_WARNING, "bad image use bit 0x%04x", 1861 attrs.DRMBufferUseMESA & ~valid_mask); 1862 goto cleanup_img; 1863 } 1864 1865 dri_use = 0; 1866 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 1867 dri_use |= __DRI_IMAGE_USE_SHARE; 1868 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 1869 dri_use |= __DRI_IMAGE_USE_SCANOUT; 1870 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 1871 dri_use |= __DRI_IMAGE_USE_CURSOR; 1872 1873 dri2_img->dri_image = 1874 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 1875 attrs.Width, attrs.Height, 1876 format, dri_use, dri2_img); 1877 if (dri2_img->dri_image == NULL) { 1878 err = EGL_BAD_ALLOC; 1879 goto cleanup_img; 1880 } 1881 1882 return &dri2_img->base; 1883 1884 cleanup_img: 1885 free(dri2_img); 1886 _eglError(err, "dri2_create_drm_image_mesa"); 1887 1888 return EGL_NO_IMAGE_KHR; 1889} 1890 1891static EGLBoolean 1892dri2_export_drm_image_mesa(_EGLDriver *drv, _EGLDisplay *disp, _EGLImage *img, 1893 EGLint *name, EGLint *handle, EGLint *stride) 1894{ 1895 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1896 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 1897 1898 (void) drv; 1899 1900 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 1901 __DRI_IMAGE_ATTRIB_NAME, name)) { 1902 _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 1903 return EGL_FALSE; 1904 } 1905 1906 if (handle) 1907 dri2_dpy->image->queryImage(dri2_img->dri_image, 1908 __DRI_IMAGE_ATTRIB_HANDLE, handle); 1909 1910 if (stride) 1911 dri2_dpy->image->queryImage(dri2_img->dri_image, 1912 __DRI_IMAGE_ATTRIB_STRIDE, stride); 1913 1914 return EGL_TRUE; 1915} 1916#endif 1917 1918#ifdef HAVE_WAYLAND_PLATFORM 1919 1920static void 1921dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd, 1922 struct wl_drm_buffer *buffer) 1923{ 1924 _EGLDisplay *disp = user_data; 1925 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1926 __DRIimage *img; 1927 int i, dri_components = 0; 1928 1929 if (fd == -1) 1930 img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, 1931 buffer->width, 1932 buffer->height, 1933 buffer->format, 1934 (int*)&name, 1, 1935 buffer->stride, 1936 buffer->offset, 1937 NULL); 1938 else 1939 img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, 1940 buffer->width, 1941 buffer->height, 1942 buffer->format, 1943 &fd, 1, 1944 buffer->stride, 1945 buffer->offset, 1946 NULL); 1947 1948 if (img == NULL) 1949 return; 1950 1951 dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components); 1952 1953 buffer->driver_format = NULL; 1954 for (i = 0; i < ARRAY_SIZE(wl_drm_components); i++) 1955 if (wl_drm_components[i].dri_components == dri_components) 1956 buffer->driver_format = &wl_drm_components[i]; 1957 1958 if (buffer->driver_format == NULL) 1959 dri2_dpy->image->destroyImage(img); 1960 else 1961 buffer->driver_buffer = img; 1962} 1963 1964static void 1965dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) 1966{ 1967 _EGLDisplay *disp = user_data; 1968 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1969 1970 dri2_dpy->image->destroyImage(buffer->driver_buffer); 1971} 1972 1973static struct wayland_drm_callbacks wl_drm_callbacks = { 1974 .authenticate = NULL, 1975 .reference_buffer = dri2_wl_reference_buffer, 1976 .release_buffer = dri2_wl_release_buffer 1977}; 1978 1979static EGLBoolean 1980dri2_bind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 1981 struct wl_display *wl_dpy) 1982{ 1983 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1984 int flags = 0; 1985 uint64_t cap; 1986 1987 (void) drv; 1988 1989 if (dri2_dpy->wl_server_drm) 1990 return EGL_FALSE; 1991 1992 wl_drm_callbacks.authenticate = 1993 (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate; 1994 1995#ifdef HAVE_LIBDRM 1996 if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 && 1997 cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) && 1998 dri2_dpy->image->base.version >= 7 && 1999 dri2_dpy->image->createImageFromFds != NULL) 2000 flags |= WAYLAND_DRM_PRIME; 2001#endif 2002 2003 dri2_dpy->wl_server_drm = 2004 wayland_drm_init(wl_dpy, dri2_dpy->device_name, 2005 &wl_drm_callbacks, disp, flags); 2006 2007 if (!dri2_dpy->wl_server_drm) 2008 return EGL_FALSE; 2009 2010#ifdef HAVE_DRM_PLATFORM 2011 /* We have to share the wl_drm instance with gbm, so gbm can convert 2012 * wl_buffers to gbm bos. */ 2013 if (dri2_dpy->gbm_dri) 2014 dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm; 2015#endif 2016 2017 return EGL_TRUE; 2018} 2019 2020static EGLBoolean 2021dri2_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *disp, 2022 struct wl_display *wl_dpy) 2023{ 2024 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2025 2026 (void) drv; 2027 2028 if (!dri2_dpy->wl_server_drm) 2029 return EGL_FALSE; 2030 2031 wayland_drm_uninit(dri2_dpy->wl_server_drm); 2032 dri2_dpy->wl_server_drm = NULL; 2033 2034 return EGL_TRUE; 2035} 2036 2037static EGLBoolean 2038dri2_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *disp, 2039 struct wl_resource *buffer_resource, 2040 EGLint attribute, EGLint *value) 2041{ 2042 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2043 struct wl_drm_buffer *buffer; 2044 const struct wl_drm_components_descriptor *format; 2045 2046 buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource); 2047 if (!buffer) 2048 return EGL_FALSE; 2049 2050 format = buffer->driver_format; 2051 switch (attribute) { 2052 case EGL_TEXTURE_FORMAT: 2053 *value = format->components; 2054 return EGL_TRUE; 2055 case EGL_WIDTH: 2056 *value = buffer->width; 2057 return EGL_TRUE; 2058 case EGL_HEIGHT: 2059 *value = buffer->height; 2060 return EGL_TRUE; 2061 } 2062 2063 return EGL_FALSE; 2064} 2065#endif 2066 2067static void 2068dri2_unload(_EGLDriver *drv) 2069{ 2070 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 2071 2072 if (dri2_drv->handle) 2073 dlclose(dri2_drv->handle); 2074 free(dri2_drv); 2075} 2076 2077static EGLBoolean 2078dri2_load(_EGLDriver *drv) 2079{ 2080 struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv); 2081#ifdef HAVE_SHARED_GLAPI 2082#ifdef HAVE_ANDROID_PLATFORM 2083 const char *libname = "libglapi.so"; 2084#else 2085 const char *libname = "libglapi.so.0"; 2086#endif 2087#else 2088 /* 2089 * Both libGL.so and libglapi.so are glapi providers. There is no way to 2090 * tell which one to load. 2091 */ 2092 const char *libname = NULL; 2093#endif 2094 void *handle; 2095 2096 /* RTLD_GLOBAL to make sure glapi symbols are visible to DRI drivers */ 2097 handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); 2098 if (handle) { 2099 dri2_drv->get_proc_address = (_EGLProc (*)(const char *)) 2100 dlsym(handle, "_glapi_get_proc_address"); 2101 if (!dri2_drv->get_proc_address || !libname) { 2102 /* no need to keep a reference */ 2103 dlclose(handle); 2104 handle = NULL; 2105 } 2106 } 2107 2108 /* if glapi is not available, loading DRI drivers will fail */ 2109 if (!dri2_drv->get_proc_address) { 2110 _eglLog(_EGL_WARNING, "DRI2: failed to find _glapi_get_proc_address"); 2111 return EGL_FALSE; 2112 } 2113 2114 dri2_drv->glFlush = (void (*)(void)) 2115 dri2_drv->get_proc_address("glFlush"); 2116 2117 dri2_drv->handle = handle; 2118 2119 return EGL_TRUE; 2120} 2121 2122/** 2123 * This is the main entrypoint into the driver, called by libEGL. 2124 * Create a new _EGLDriver object and init its dispatch table. 2125 */ 2126_EGLDriver * 2127_eglBuiltInDriverDRI2(const char *args) 2128{ 2129 struct dri2_egl_driver *dri2_drv; 2130 2131 (void) args; 2132 2133 dri2_drv = calloc(1, sizeof *dri2_drv); 2134 if (!dri2_drv) 2135 return NULL; 2136 2137 if (!dri2_load(&dri2_drv->base)) { 2138 free(dri2_drv); 2139 return NULL; 2140 } 2141 2142 _eglInitDriverFallbacks(&dri2_drv->base); 2143 dri2_drv->base.API.Initialize = dri2_initialize; 2144 dri2_drv->base.API.Terminate = dri2_terminate; 2145 dri2_drv->base.API.CreateContext = dri2_create_context; 2146 dri2_drv->base.API.DestroyContext = dri2_destroy_context; 2147 dri2_drv->base.API.MakeCurrent = dri2_make_current; 2148 dri2_drv->base.API.CreateWindowSurface = dri2_create_window_surface; 2149 dri2_drv->base.API.CreatePixmapSurface = dri2_create_pixmap_surface; 2150 dri2_drv->base.API.CreatePbufferSurface = dri2_create_pbuffer_surface; 2151 dri2_drv->base.API.DestroySurface = dri2_destroy_surface; 2152 dri2_drv->base.API.GetProcAddress = dri2_get_proc_address; 2153 dri2_drv->base.API.WaitClient = dri2_wait_client; 2154 dri2_drv->base.API.WaitNative = dri2_wait_native; 2155 dri2_drv->base.API.BindTexImage = dri2_bind_tex_image; 2156 dri2_drv->base.API.ReleaseTexImage = dri2_release_tex_image; 2157 dri2_drv->base.API.SwapInterval = dri2_swap_interval; 2158 dri2_drv->base.API.SwapBuffers = dri2_swap_buffers; 2159 dri2_drv->base.API.SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage; 2160 dri2_drv->base.API.SwapBuffersRegionNOK = dri2_swap_buffers_region; 2161 dri2_drv->base.API.PostSubBufferNV = dri2_post_sub_buffer; 2162 dri2_drv->base.API.CopyBuffers = dri2_copy_buffers, 2163 dri2_drv->base.API.QueryBufferAge = dri2_query_buffer_age; 2164 dri2_drv->base.API.CreateImageKHR = dri2_create_image; 2165 dri2_drv->base.API.DestroyImageKHR = dri2_destroy_image_khr; 2166 dri2_drv->base.API.CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image; 2167#ifdef HAVE_DRM_PLATFORM 2168 dri2_drv->base.API.CreateDRMImageMESA = dri2_create_drm_image_mesa; 2169 dri2_drv->base.API.ExportDRMImageMESA = dri2_export_drm_image_mesa; 2170#endif 2171#ifdef HAVE_WAYLAND_PLATFORM 2172 dri2_drv->base.API.BindWaylandDisplayWL = dri2_bind_wayland_display_wl; 2173 dri2_drv->base.API.UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl; 2174 dri2_drv->base.API.QueryWaylandBufferWL = dri2_query_wayland_buffer_wl; 2175#endif 2176 dri2_drv->base.API.GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium; 2177 2178 dri2_drv->base.Name = "DRI2"; 2179 dri2_drv->base.Unload = dri2_unload; 2180 2181 return &dri2_drv->base; 2182} 2183