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 <stdbool.h> 29#include <stdint.h> 30#include <stdbool.h> 31#include <stdlib.h> 32#include <string.h> 33#include <stdio.h> 34#include <limits.h> 35#include <dlfcn.h> 36#include <fcntl.h> 37#include <errno.h> 38#include <unistd.h> 39#include <c11/threads.h> 40#include <time.h> 41#ifdef HAVE_LIBDRM 42#include <xf86drm.h> 43#include "drm-uapi/drm_fourcc.h" 44#endif 45#include <GL/gl.h> 46#include <GL/internal/dri_interface.h> 47#include <sys/types.h> 48#include <sys/stat.h> 49 50#ifdef HAVE_WAYLAND_PLATFORM 51#include <wayland-client.h> 52#include "wayland-drm.h" 53#include "wayland-drm-client-protocol.h" 54#include "linux-dmabuf-unstable-v1-client-protocol.h" 55#endif 56 57#ifdef HAVE_X11_PLATFORM 58#include "X11/Xlibint.h" 59#endif 60 61#include "egldefines.h" 62#include "egl_dri2.h" 63#include "GL/mesa_glinterop.h" 64#include "loader/loader.h" 65#include "util/libsync.h" 66#include "util/os_file.h" 67#include "util/u_atomic.h" 68#include "util/u_vector.h" 69#include "mapi/glapi/glapi.h" 70#include "util/bitscan.h" 71#include "util/u_math.h" 72 73#define NUM_ATTRIBS 12 74 75static const struct dri2_pbuffer_visual { 76 const char *format_name; 77 unsigned int dri_image_format; 78 int rgba_shifts[4]; 79 unsigned int rgba_sizes[4]; 80} dri2_pbuffer_visuals[] = { 81 { 82 "ABGR16F", 83 __DRI_IMAGE_FORMAT_ABGR16161616F, 84 { 0, 16, 32, 48 }, 85 { 16, 16, 16, 16 } 86 }, 87 { 88 "XBGR16F", 89 __DRI_IMAGE_FORMAT_XBGR16161616F, 90 { 0, 16, 32, -1 }, 91 { 16, 16, 16, 0 } 92 }, 93 { 94 "A2RGB10", 95 __DRI_IMAGE_FORMAT_ARGB2101010, 96 { 20, 10, 0, 30 }, 97 { 10, 10, 10, 2 } 98 }, 99 { 100 "X2RGB10", 101 __DRI_IMAGE_FORMAT_XRGB2101010, 102 { 20, 10, 0, -1 }, 103 { 10, 10, 10, 0 } 104 }, 105 { 106 "ARGB8888", 107 __DRI_IMAGE_FORMAT_ARGB8888, 108 { 16, 8, 0, 24 }, 109 { 8, 8, 8, 8 } 110 }, 111 { 112 "RGB888", 113 __DRI_IMAGE_FORMAT_XRGB8888, 114 { 16, 8, 0, -1 }, 115 { 8, 8, 8, 0 } 116 }, 117 { 118 "RGB565", 119 __DRI_IMAGE_FORMAT_RGB565, 120 { 11, 5, 0, -1 }, 121 { 5, 6, 5, 0 } 122 }, 123}; 124 125static void 126dri_set_background_context(void *loaderPrivate) 127{ 128 _EGLContext *ctx = _eglGetCurrentContext(); 129 _EGLThreadInfo *t = _eglGetCurrentThread(); 130 131 _eglBindContextToThread(ctx, t); 132} 133 134static void 135dri2_gl_flush() 136{ 137 static void (*glFlush)(void); 138 static mtx_t glFlushMutex = _MTX_INITIALIZER_NP; 139 140 mtx_lock(&glFlushMutex); 141 if (!glFlush) 142 glFlush = _glapi_get_proc_address("glFlush"); 143 mtx_unlock(&glFlushMutex); 144 145 /* if glFlush is not available things are horribly broken */ 146 if (!glFlush) { 147 _eglLog(_EGL_WARNING, "DRI2: failed to find glFlush entry point"); 148 return; 149 } 150 151 glFlush(); 152} 153 154static GLboolean 155dri_is_thread_safe(void *loaderPrivate) 156{ 157 struct dri2_egl_surface *dri2_surf = loaderPrivate; 158 UNUSED _EGLDisplay *display = dri2_surf->base.Resource.Display; 159 160#ifdef HAVE_X11_PLATFORM 161 Display *xdpy = (Display*)display->PlatformDisplay; 162 163 /* Check Xlib is running in thread safe mode when running on EGL/X11-xlib 164 * platform 165 * 166 * 'lock_fns' is the XLockDisplay function pointer of the X11 display 'dpy'. 167 * It wll be NULL if XInitThreads wasn't called. 168 */ 169 if (display->Platform == _EGL_PLATFORM_X11 && xdpy && !xdpy->lock_fns) 170 return false; 171#endif 172 173 return true; 174} 175 176const __DRIbackgroundCallableExtension background_callable_extension = { 177 .base = { __DRI_BACKGROUND_CALLABLE, 2 }, 178 179 .setBackgroundContext = dri_set_background_context, 180 .isThreadSafe = dri_is_thread_safe, 181}; 182 183const __DRIuseInvalidateExtension use_invalidate = { 184 .base = { __DRI_USE_INVALIDATE, 1 } 185}; 186 187static void 188dri2_get_pbuffer_drawable_info(__DRIdrawable * draw, 189 int *x, int *y, int *w, int *h, 190 void *loaderPrivate) 191{ 192 struct dri2_egl_surface *dri2_surf = loaderPrivate; 193 194 *x = *y = 0; 195 *w = dri2_surf->base.Width; 196 *h = dri2_surf->base.Height; 197} 198 199static int 200dri2_get_bytes_per_pixel(struct dri2_egl_surface *dri2_surf) 201{ 202 const int depth = dri2_surf->base.Config->BufferSize; 203 return depth ? util_next_power_of_two(depth / 8) : 0; 204} 205 206static void 207dri2_put_image(__DRIdrawable * draw, int op, 208 int x, int y, int w, int h, 209 char *data, void *loaderPrivate) 210{ 211 struct dri2_egl_surface *dri2_surf = loaderPrivate; 212 const int bpp = dri2_get_bytes_per_pixel(dri2_surf); 213 const int width = dri2_surf->base.Width; 214 const int height = dri2_surf->base.Height; 215 const int dst_stride = width*bpp; 216 const int src_stride = w*bpp; 217 const int x_offset = x*bpp; 218 int copy_width = src_stride; 219 220 if (!dri2_surf->swrast_device_buffer) 221 dri2_surf->swrast_device_buffer = malloc(height*dst_stride); 222 223 if (dri2_surf->swrast_device_buffer) { 224 const char *src = data; 225 char *dst = dri2_surf->swrast_device_buffer; 226 227 dst += x_offset; 228 dst += y*dst_stride; 229 230 /* Drivers are allowed to submit OOB PutImage requests, so clip here. */ 231 if (copy_width > dst_stride - x_offset) 232 copy_width = dst_stride - x_offset; 233 if (h > height - y) 234 h = height - y; 235 236 for (; 0 < h; --h) { 237 memcpy(dst, src, copy_width); 238 dst += dst_stride; 239 src += src_stride; 240 } 241 } 242} 243 244static void 245dri2_get_image(__DRIdrawable * read, 246 int x, int y, int w, int h, 247 char *data, void *loaderPrivate) 248{ 249 struct dri2_egl_surface *dri2_surf = loaderPrivate; 250 const int bpp = dri2_get_bytes_per_pixel(dri2_surf); 251 const int width = dri2_surf->base.Width; 252 const int height = dri2_surf->base.Height; 253 const int src_stride = width*bpp; 254 const int dst_stride = w*bpp; 255 const int x_offset = x*bpp; 256 int copy_width = dst_stride; 257 const char *src = dri2_surf->swrast_device_buffer; 258 char *dst = data; 259 260 if (!src) { 261 memset(data, 0, copy_width * h); 262 return; 263 } 264 265 src += x_offset; 266 src += y*src_stride; 267 268 /* Drivers are allowed to submit OOB GetImage requests, so clip here. */ 269 if (copy_width > src_stride - x_offset) 270 copy_width = src_stride - x_offset; 271 if (h > height - y) 272 h = height - y; 273 274 for (; 0 < h; --h) { 275 memcpy(dst, src, copy_width); 276 src += src_stride; 277 dst += dst_stride; 278 } 279 280} 281 282/* HACK: technically we should have swrast_null, instead of these. 283 */ 284const __DRIswrastLoaderExtension swrast_pbuffer_loader_extension = { 285 .base = { __DRI_SWRAST_LOADER, 1 }, 286 .getDrawableInfo = dri2_get_pbuffer_drawable_info, 287 .putImage = dri2_put_image, 288 .getImage = dri2_get_image, 289}; 290 291static const EGLint dri2_to_egl_attribute_map[__DRI_ATTRIB_MAX] = { 292 [__DRI_ATTRIB_BUFFER_SIZE ] = EGL_BUFFER_SIZE, 293 [__DRI_ATTRIB_LEVEL] = EGL_LEVEL, 294 [__DRI_ATTRIB_LUMINANCE_SIZE] = EGL_LUMINANCE_SIZE, 295 [__DRI_ATTRIB_DEPTH_SIZE] = EGL_DEPTH_SIZE, 296 [__DRI_ATTRIB_STENCIL_SIZE] = EGL_STENCIL_SIZE, 297 [__DRI_ATTRIB_SAMPLE_BUFFERS] = EGL_SAMPLE_BUFFERS, 298 [__DRI_ATTRIB_SAMPLES] = EGL_SAMPLES, 299 [__DRI_ATTRIB_MAX_PBUFFER_WIDTH] = EGL_MAX_PBUFFER_WIDTH, 300 [__DRI_ATTRIB_MAX_PBUFFER_HEIGHT] = EGL_MAX_PBUFFER_HEIGHT, 301 [__DRI_ATTRIB_MAX_PBUFFER_PIXELS] = EGL_MAX_PBUFFER_PIXELS, 302 [__DRI_ATTRIB_MAX_SWAP_INTERVAL] = EGL_MAX_SWAP_INTERVAL, 303 [__DRI_ATTRIB_MIN_SWAP_INTERVAL] = EGL_MIN_SWAP_INTERVAL, 304 [__DRI_ATTRIB_YINVERTED] = EGL_Y_INVERTED_NOK, 305}; 306 307const __DRIconfig * 308dri2_get_dri_config(struct dri2_egl_config *conf, EGLint surface_type, 309 EGLenum colorspace) 310{ 311 const bool double_buffer = surface_type == EGL_WINDOW_BIT; 312 const bool srgb = colorspace == EGL_GL_COLORSPACE_SRGB_KHR; 313 314 return conf->dri_config[double_buffer][srgb]; 315} 316 317static EGLBoolean 318dri2_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) 319{ 320 if (_eglCompareConfigs(conf, criteria, NULL, EGL_FALSE) != 0) 321 return EGL_FALSE; 322 323 if (!_eglMatchConfig(conf, criteria)) 324 return EGL_FALSE; 325 326 return EGL_TRUE; 327} 328 329void 330dri2_get_shifts_and_sizes(const __DRIcoreExtension *core, 331 const __DRIconfig *config, int *shifts, 332 unsigned int *sizes) 333{ 334 unsigned int mask; 335 336 if (core->getConfigAttrib(config, __DRI_ATTRIB_RED_SHIFT, (unsigned int *)&shifts[0])) { 337 core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SHIFT, (unsigned int *)&shifts[1]); 338 core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SHIFT, (unsigned int *)&shifts[2]); 339 core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SHIFT, (unsigned int *)&shifts[3]); 340 } else { 341 /* Driver isn't exposing shifts, so convert masks to shifts */ 342 core->getConfigAttrib(config, __DRI_ATTRIB_RED_MASK, &mask); 343 shifts[0] = ffs(mask) - 1; 344 core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_MASK, &mask); 345 shifts[1] = ffs(mask) - 1; 346 core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_MASK, &mask); 347 shifts[2] = ffs(mask) - 1; 348 core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_MASK, &mask); 349 shifts[3] = ffs(mask) - 1; 350 } 351 352 core->getConfigAttrib(config, __DRI_ATTRIB_RED_SIZE, &sizes[0]); 353 core->getConfigAttrib(config, __DRI_ATTRIB_GREEN_SIZE, &sizes[1]); 354 core->getConfigAttrib(config, __DRI_ATTRIB_BLUE_SIZE, &sizes[2]); 355 core->getConfigAttrib(config, __DRI_ATTRIB_ALPHA_SIZE, &sizes[3]); 356} 357 358void 359dri2_get_render_type_float(const __DRIcoreExtension *core, 360 const __DRIconfig *config, 361 bool *is_float) 362{ 363 unsigned int render_type; 364 365 core->getConfigAttrib(config, __DRI_ATTRIB_RENDER_TYPE, &render_type); 366 *is_float = (render_type & __DRI_ATTRIB_FLOAT_BIT) ? true : false; 367} 368 369unsigned int 370dri2_image_format_for_pbuffer_config(struct dri2_egl_display *dri2_dpy, 371 const __DRIconfig *config) 372{ 373 int shifts[4]; 374 unsigned int sizes[4]; 375 376 dri2_get_shifts_and_sizes(dri2_dpy->core, config, shifts, sizes); 377 378 for (unsigned i = 0; i < ARRAY_SIZE(dri2_pbuffer_visuals); ++i) { 379 const struct dri2_pbuffer_visual *visual = &dri2_pbuffer_visuals[i]; 380 381 if (shifts[0] == visual->rgba_shifts[0] && 382 shifts[1] == visual->rgba_shifts[1] && 383 shifts[2] == visual->rgba_shifts[2] && 384 shifts[3] == visual->rgba_shifts[3] && 385 sizes[0] == visual->rgba_sizes[0] && 386 sizes[1] == visual->rgba_sizes[1] && 387 sizes[2] == visual->rgba_sizes[2] && 388 sizes[3] == visual->rgba_sizes[3]) { 389 return visual->dri_image_format; 390 } 391 } 392 393 return __DRI_IMAGE_FORMAT_NONE; 394} 395 396struct dri2_egl_config * 397dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id, 398 EGLint surface_type, const EGLint *attr_list, 399 const int *rgba_shifts, const unsigned int *rgba_sizes) 400{ 401 struct dri2_egl_config *conf; 402 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 403 _EGLConfig base; 404 unsigned int attrib, value, double_buffer; 405 bool srgb = false; 406 EGLint key, bind_to_texture_rgb, bind_to_texture_rgba; 407 int dri_shifts[4] = { -1, -1, -1, -1 }; 408 unsigned int dri_sizes[4] = { 0, 0, 0, 0 }; 409 _EGLConfig *matching_config; 410 EGLint num_configs = 0; 411 EGLint config_id; 412 413 _eglInitConfig(&base, disp, id); 414 415 double_buffer = 0; 416 bind_to_texture_rgb = 0; 417 bind_to_texture_rgba = 0; 418 419 for (int i = 0; i < __DRI_ATTRIB_MAX; ++i) { 420 if (!dri2_dpy->core->indexConfigAttrib(dri_config, i, &attrib, &value)) 421 break; 422 423 switch (attrib) { 424 case __DRI_ATTRIB_RENDER_TYPE: 425 if (value & __DRI_ATTRIB_FLOAT_BIT) 426 base.ComponentType = EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT; 427 if (value & __DRI_ATTRIB_RGBA_BIT) 428 value = EGL_RGB_BUFFER; 429 else if (value & __DRI_ATTRIB_LUMINANCE_BIT) 430 value = EGL_LUMINANCE_BUFFER; 431 else 432 return NULL; 433 base.ColorBufferType = value; 434 break; 435 436 case __DRI_ATTRIB_CONFIG_CAVEAT: 437 if (value & __DRI_ATTRIB_NON_CONFORMANT_CONFIG) 438 value = EGL_NON_CONFORMANT_CONFIG; 439 else if (value & __DRI_ATTRIB_SLOW_BIT) 440 value = EGL_SLOW_CONFIG; 441 else 442 value = EGL_NONE; 443 base.ConfigCaveat = value; 444 break; 445 446 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGB: 447 bind_to_texture_rgb = value; 448 break; 449 450 case __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA: 451 bind_to_texture_rgba = value; 452 break; 453 454 case __DRI_ATTRIB_DOUBLE_BUFFER: 455 double_buffer = value; 456 break; 457 458 case __DRI_ATTRIB_RED_SIZE: 459 dri_sizes[0] = value; 460 base.RedSize = value; 461 break; 462 463 case __DRI_ATTRIB_RED_MASK: 464 dri_shifts[0] = ffs(value) - 1; 465 break; 466 467 case __DRI_ATTRIB_RED_SHIFT: 468 dri_shifts[0] = value; 469 break; 470 471 case __DRI_ATTRIB_GREEN_SIZE: 472 dri_sizes[1] = value; 473 base.GreenSize = value; 474 break; 475 476 case __DRI_ATTRIB_GREEN_MASK: 477 dri_shifts[1] = ffs(value) - 1; 478 break; 479 480 case __DRI_ATTRIB_GREEN_SHIFT: 481 dri_shifts[1] = value; 482 break; 483 484 case __DRI_ATTRIB_BLUE_SIZE: 485 dri_sizes[2] = value; 486 base.BlueSize = value; 487 break; 488 489 case __DRI_ATTRIB_BLUE_MASK: 490 dri_shifts[2] = ffs(value) - 1; 491 break; 492 493 case __DRI_ATTRIB_BLUE_SHIFT: 494 dri_shifts[2] = value; 495 break; 496 497 case __DRI_ATTRIB_ALPHA_SIZE: 498 dri_sizes[3] = value; 499 base.AlphaSize = value; 500 break; 501 502 case __DRI_ATTRIB_ALPHA_MASK: 503 dri_shifts[3] = ffs(value) - 1; 504 break; 505 506 case __DRI_ATTRIB_ALPHA_SHIFT: 507 dri_shifts[3] = value; 508 break; 509 510 case __DRI_ATTRIB_ACCUM_RED_SIZE: 511 case __DRI_ATTRIB_ACCUM_GREEN_SIZE: 512 case __DRI_ATTRIB_ACCUM_BLUE_SIZE: 513 case __DRI_ATTRIB_ACCUM_ALPHA_SIZE: 514 /* Don't expose visuals with the accumulation buffer. */ 515 if (value > 0) 516 return NULL; 517 break; 518 519 case __DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE: 520 srgb = value != 0; 521 if (!disp->Extensions.KHR_gl_colorspace && srgb) 522 return NULL; 523 break; 524 525 case __DRI_ATTRIB_MAX_PBUFFER_WIDTH: 526 base.MaxPbufferWidth = _EGL_MAX_PBUFFER_WIDTH; 527 break; 528 case __DRI_ATTRIB_MAX_PBUFFER_HEIGHT: 529 base.MaxPbufferHeight = _EGL_MAX_PBUFFER_HEIGHT; 530 break; 531 case __DRI_ATTRIB_MUTABLE_RENDER_BUFFER: 532 if (disp->Extensions.KHR_mutable_render_buffer) 533 surface_type |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR; 534 break; 535 default: 536 key = dri2_to_egl_attribute_map[attrib]; 537 if (key != 0) 538 _eglSetConfigKey(&base, key, value); 539 break; 540 } 541 } 542 543 if (attr_list) 544 for (int i = 0; attr_list[i] != EGL_NONE; i += 2) 545 _eglSetConfigKey(&base, attr_list[i], attr_list[i+1]); 546 547 if (rgba_shifts && memcmp(rgba_shifts, dri_shifts, sizeof(dri_shifts))) 548 return NULL; 549 550 if (rgba_sizes && memcmp(rgba_sizes, dri_sizes, sizeof(dri_sizes))) 551 return NULL; 552 553 base.NativeRenderable = EGL_TRUE; 554 555 base.SurfaceType = surface_type; 556 if (surface_type & (EGL_PBUFFER_BIT | 557 (disp->Extensions.NOK_texture_from_pixmap ? EGL_PIXMAP_BIT : 0))) { 558 base.BindToTextureRGB = bind_to_texture_rgb; 559 if (base.AlphaSize > 0) 560 base.BindToTextureRGBA = bind_to_texture_rgba; 561 } 562 563 if (double_buffer) { 564 surface_type &= ~EGL_PIXMAP_BIT; 565 } 566 567 if (!surface_type) 568 return NULL; 569 570 base.RenderableType = disp->ClientAPIs; 571 base.Conformant = disp->ClientAPIs; 572 573 base.MinSwapInterval = dri2_dpy->min_swap_interval; 574 base.MaxSwapInterval = dri2_dpy->max_swap_interval; 575 576 if (!_eglValidateConfig(&base, EGL_FALSE)) { 577 _eglLog(_EGL_DEBUG, "DRI2: failed to validate config %d", id); 578 return NULL; 579 } 580 581 config_id = base.ConfigID; 582 base.ConfigID = EGL_DONT_CARE; 583 base.SurfaceType = EGL_DONT_CARE; 584 num_configs = _eglFilterArray(disp->Configs, (void **) &matching_config, 1, 585 (_EGLArrayForEach) dri2_match_config, &base); 586 587 if (num_configs == 1) { 588 conf = (struct dri2_egl_config *) matching_config; 589 590 if (!conf->dri_config[double_buffer][srgb]) 591 conf->dri_config[double_buffer][srgb] = dri_config; 592 else 593 /* a similar config type is already added (unlikely) => discard */ 594 return NULL; 595 } 596 else if (num_configs == 0) { 597 conf = calloc(1, sizeof *conf); 598 if (conf == NULL) 599 return NULL; 600 601 conf->dri_config[double_buffer][srgb] = dri_config; 602 603 memcpy(&conf->base, &base, sizeof base); 604 conf->base.SurfaceType = 0; 605 conf->base.ConfigID = config_id; 606 607 _eglLinkConfig(&conf->base); 608 } 609 else { 610 unreachable("duplicates should not be possible"); 611 return NULL; 612 } 613 614 conf->base.SurfaceType |= surface_type; 615 616 return conf; 617} 618 619EGLBoolean 620dri2_add_pbuffer_configs_for_visuals(_EGLDisplay *disp) 621{ 622 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 623 unsigned int format_count[ARRAY_SIZE(dri2_pbuffer_visuals)] = { 0 }; 624 unsigned int config_count = 0; 625 626 for (unsigned i = 0; dri2_dpy->driver_configs[i] != NULL; i++) { 627 for (unsigned j = 0; j < ARRAY_SIZE(dri2_pbuffer_visuals); j++) { 628 struct dri2_egl_config *dri2_conf; 629 630 dri2_conf = dri2_add_config(disp, dri2_dpy->driver_configs[i], 631 config_count + 1, EGL_PBUFFER_BIT, NULL, 632 dri2_pbuffer_visuals[j].rgba_shifts, dri2_pbuffer_visuals[j].rgba_sizes); 633 634 if (dri2_conf) { 635 if (dri2_conf->base.ConfigID == config_count + 1) 636 config_count++; 637 format_count[j]++; 638 } 639 } 640 } 641 642 for (unsigned i = 0; i < ARRAY_SIZE(format_count); i++) { 643 if (!format_count[i]) { 644 _eglLog(_EGL_DEBUG, "No DRI config supports native format %s", 645 dri2_pbuffer_visuals[i].format_name); 646 } 647 } 648 649 return (config_count != 0); 650} 651 652GLboolean 653dri2_validate_egl_image(void *image, void *data) 654{ 655 _EGLDisplay *disp = data; 656 _EGLImage *img; 657 658 mtx_lock(&disp->Mutex); 659 img = _eglLookupImage(image, disp); 660 mtx_unlock(&disp->Mutex); 661 662 if (img == NULL) { 663 _eglError(EGL_BAD_PARAMETER, "dri2_validate_egl_image"); 664 return false; 665 } 666 667 return true; 668} 669 670__DRIimage * 671dri2_lookup_egl_image_validated(void *image, void *data) 672{ 673 struct dri2_egl_image *dri2_img; 674 675 (void)data; 676 677 dri2_img = dri2_egl_image(image); 678 679 return dri2_img->dri_image; 680} 681 682__DRIimage * 683dri2_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 684{ 685 (void) screen; 686 687 if (!dri2_validate_egl_image(image, data)) 688 return NULL; 689 690 return dri2_lookup_egl_image_validated(image, data); 691} 692 693const __DRIimageLookupExtension image_lookup_extension = { 694 .base = { __DRI_IMAGE_LOOKUP, 2 }, 695 696 .lookupEGLImage = dri2_lookup_egl_image, 697 .validateEGLImage = dri2_validate_egl_image, 698 .lookupEGLImageValidated = dri2_lookup_egl_image_validated, 699}; 700 701struct dri2_extension_match { 702 const char *name; 703 int version; 704 int offset; 705}; 706 707static const struct dri2_extension_match dri3_driver_extensions[] = { 708 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 709 { __DRI_IMAGE_DRIVER, 1, offsetof(struct dri2_egl_display, image_driver) }, 710 { NULL, 0, 0 } 711}; 712 713static const struct dri2_extension_match dri2_driver_extensions[] = { 714 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 715 { __DRI_DRI2, 2, offsetof(struct dri2_egl_display, dri2) }, 716 { NULL, 0, 0 } 717}; 718 719static const struct dri2_extension_match dri2_core_extensions[] = { 720 { __DRI2_FLUSH, 1, offsetof(struct dri2_egl_display, flush) }, 721 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 722 { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 723 { NULL, 0, 0 } 724}; 725 726static const struct dri2_extension_match swrast_driver_extensions[] = { 727 { __DRI_CORE, 1, offsetof(struct dri2_egl_display, core) }, 728 { __DRI_SWRAST, 2, offsetof(struct dri2_egl_display, swrast) }, 729 { NULL, 0, 0 } 730}; 731 732static const struct dri2_extension_match swrast_core_extensions[] = { 733 { __DRI_TEX_BUFFER, 2, offsetof(struct dri2_egl_display, tex_buffer) }, 734 { NULL, 0, 0 } 735}; 736 737static const struct dri2_extension_match optional_driver_extensions[] = { 738 { __DRI_CONFIG_OPTIONS, 1, offsetof(struct dri2_egl_display, configOptions) }, 739 { NULL, 0, 0 } 740}; 741 742static const struct dri2_extension_match optional_core_extensions[] = { 743 { __DRI2_ROBUSTNESS, 1, offsetof(struct dri2_egl_display, robustness) }, 744 { __DRI2_NO_ERROR, 1, offsetof(struct dri2_egl_display, no_error) }, 745 { __DRI2_CONFIG_QUERY, 1, offsetof(struct dri2_egl_display, config) }, 746 { __DRI2_FENCE, 1, offsetof(struct dri2_egl_display, fence) }, 747 { __DRI2_BUFFER_DAMAGE, 1, offsetof(struct dri2_egl_display, buffer_damage) }, 748 { __DRI2_RENDERER_QUERY, 1, offsetof(struct dri2_egl_display, rendererQuery) }, 749 { __DRI2_INTEROP, 1, offsetof(struct dri2_egl_display, interop) }, 750 { __DRI_IMAGE, 1, offsetof(struct dri2_egl_display, image) }, 751 { __DRI2_FLUSH_CONTROL, 1, offsetof(struct dri2_egl_display, flush_control) }, 752 { __DRI2_BLOB, 1, offsetof(struct dri2_egl_display, blob) }, 753 { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1, offsetof(struct dri2_egl_display, mutable_render_buffer) }, 754 { NULL, 0, 0 } 755}; 756 757static EGLBoolean 758dri2_bind_extensions(struct dri2_egl_display *dri2_dpy, 759 const struct dri2_extension_match *matches, 760 const __DRIextension **extensions, 761 bool optional) 762{ 763 int ret = EGL_TRUE; 764 void *field; 765 766 for (int i = 0; extensions[i]; i++) { 767 _eglLog(_EGL_DEBUG, "found extension `%s'", extensions[i]->name); 768 for (int j = 0; matches[j].name; j++) { 769 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 770 extensions[i]->version >= matches[j].version) { 771 field = ((char *) dri2_dpy + matches[j].offset); 772 *(const __DRIextension **) field = extensions[i]; 773 _eglLog(_EGL_INFO, "found extension %s version %d", 774 extensions[i]->name, extensions[i]->version); 775 break; 776 } 777 } 778 } 779 780 for (int j = 0; matches[j].name; j++) { 781 field = ((char *) dri2_dpy + matches[j].offset); 782 if (*(const __DRIextension **) field == NULL) { 783 if (optional) { 784 _eglLog(_EGL_DEBUG, "did not find optional extension %s version %d", 785 matches[j].name, matches[j].version); 786 } else { 787 _eglLog(_EGL_WARNING, "did not find extension %s version %d", 788 matches[j].name, matches[j].version); 789 ret = EGL_FALSE; 790 } 791 } 792 } 793 794 return ret; 795} 796 797static const __DRIextension ** 798dri2_open_driver(_EGLDisplay *disp) 799{ 800 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 801 static const char *search_path_vars[] = { 802 "LIBGL_DRIVERS_PATH", 803 NULL, 804 }; 805 806 return loader_open_driver(dri2_dpy->driver_name, 807 &dri2_dpy->driver, 808 search_path_vars); 809} 810 811static EGLBoolean 812dri2_load_driver_common(_EGLDisplay *disp, 813 const struct dri2_extension_match *driver_extensions) 814{ 815 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 816 const __DRIextension **extensions; 817 818 extensions = dri2_open_driver(disp); 819 if (!extensions) 820 return EGL_FALSE; 821 822 if (!dri2_bind_extensions(dri2_dpy, driver_extensions, extensions, false)) { 823 dlclose(dri2_dpy->driver); 824 dri2_dpy->driver = NULL; 825 return EGL_FALSE; 826 } 827 dri2_dpy->driver_extensions = extensions; 828 829 dri2_bind_extensions(dri2_dpy, optional_driver_extensions, extensions, true); 830 831 return EGL_TRUE; 832} 833 834EGLBoolean 835dri2_load_driver(_EGLDisplay *disp) 836{ 837 return dri2_load_driver_common(disp, dri2_driver_extensions); 838} 839 840EGLBoolean 841dri2_load_driver_dri3(_EGLDisplay *disp) 842{ 843 return dri2_load_driver_common(disp, dri3_driver_extensions); 844} 845 846EGLBoolean 847dri2_load_driver_swrast(_EGLDisplay *disp) 848{ 849 return dri2_load_driver_common(disp, swrast_driver_extensions); 850} 851 852static unsigned 853dri2_renderer_query_integer(struct dri2_egl_display *dri2_dpy, int param) 854{ 855 const __DRI2rendererQueryExtension *rendererQuery = dri2_dpy->rendererQuery; 856 unsigned int value = 0; 857 858 if (!rendererQuery || 859 rendererQuery->queryInteger(dri2_dpy->dri_screen, param, &value) == -1) 860 return 0; 861 862 return value; 863} 864 865static const char * 866dri2_query_driver_name(_EGLDisplay *disp) 867{ 868 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 869 return dri2_dpy->driver_name; 870} 871 872static char * 873dri2_query_driver_config(_EGLDisplay *disp) 874{ 875 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 876 const __DRIconfigOptionsExtension *ext = dri2_dpy->configOptions; 877 878 if (ext->base.version >= 2) 879 return ext->getXml(dri2_dpy->driver_name); 880 881 return strdup(ext->xml); 882} 883 884 885void 886dri2_setup_screen(_EGLDisplay *disp) 887{ 888 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 889 unsigned int api_mask; 890 891 /* 892 * EGL 1.5 specification defines the default value to 1. Moreover, 893 * eglSwapInterval() is required to clamp requested value to the supported 894 * range. Since the default value is implicitly assumed to be supported, 895 * use it as both minimum and maximum for the platforms that do not allow 896 * changing the interval. Platforms, which allow it (e.g. x11, wayland) 897 * override these values already. 898 */ 899 dri2_dpy->min_swap_interval = 1; 900 dri2_dpy->max_swap_interval = 1; 901 dri2_dpy->default_swap_interval = 1; 902 903 if (dri2_dpy->image_driver) { 904 api_mask = dri2_dpy->image_driver->getAPIMask(dri2_dpy->dri_screen); 905 } else if (dri2_dpy->dri2) { 906 api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen); 907 } else { 908 assert(dri2_dpy->swrast); 909 api_mask = 1 << __DRI_API_OPENGL | 910 1 << __DRI_API_GLES | 911 1 << __DRI_API_GLES2 | 912 1 << __DRI_API_GLES3; 913 } 914 915 disp->ClientAPIs = 0; 916 if ((api_mask & (1 <<__DRI_API_OPENGL)) && _eglIsApiValid(EGL_OPENGL_API)) 917 disp->ClientAPIs |= EGL_OPENGL_BIT; 918 if ((api_mask & (1 << __DRI_API_GLES)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 919 disp->ClientAPIs |= EGL_OPENGL_ES_BIT; 920 if ((api_mask & (1 << __DRI_API_GLES2)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 921 disp->ClientAPIs |= EGL_OPENGL_ES2_BIT; 922 if ((api_mask & (1 << __DRI_API_GLES3)) && _eglIsApiValid(EGL_OPENGL_ES_API)) 923 disp->ClientAPIs |= EGL_OPENGL_ES3_BIT_KHR; 924 925 assert(dri2_dpy->image_driver || dri2_dpy->dri2 || dri2_dpy->swrast); 926 disp->Extensions.KHR_no_config_context = EGL_TRUE; 927 disp->Extensions.KHR_surfaceless_context = EGL_TRUE; 928 929 if (dri2_dpy->configOptions) { 930 disp->Extensions.MESA_query_driver = EGL_TRUE; 931 } 932 933 /* Report back to EGL the bitmask of priorities supported */ 934 disp->Extensions.IMG_context_priority = 935 dri2_renderer_query_integer(dri2_dpy, 936 __DRI2_RENDERER_HAS_CONTEXT_PRIORITY); 937 938 disp->Extensions.EXT_pixel_format_float = EGL_TRUE; 939 940 if (dri2_renderer_query_integer(dri2_dpy, 941 __DRI2_RENDERER_HAS_FRAMEBUFFER_SRGB)) 942 disp->Extensions.KHR_gl_colorspace = EGL_TRUE; 943 944 if (dri2_dpy->image_driver || 945 (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) || 946 (dri2_dpy->swrast && dri2_dpy->swrast->base.version >= 3)) { 947 disp->Extensions.KHR_create_context = EGL_TRUE; 948 949 if (dri2_dpy->robustness) 950 disp->Extensions.EXT_create_context_robustness = EGL_TRUE; 951 } 952 953 if (dri2_dpy->no_error) 954 disp->Extensions.KHR_create_context_no_error = EGL_TRUE; 955 956 if (dri2_dpy->fence) { 957 disp->Extensions.KHR_fence_sync = EGL_TRUE; 958 disp->Extensions.KHR_wait_sync = EGL_TRUE; 959 if (dri2_dpy->fence->get_fence_from_cl_event) 960 disp->Extensions.KHR_cl_event2 = EGL_TRUE; 961 if (dri2_dpy->fence->base.version >= 2 && 962 dri2_dpy->fence->get_capabilities) { 963 unsigned capabilities = 964 dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen); 965 disp->Extensions.ANDROID_native_fence_sync = 966 (capabilities & __DRI_FENCE_CAP_NATIVE_FD) != 0; 967 } 968 } 969 970 if (dri2_dpy->blob) 971 disp->Extensions.ANDROID_blob_cache = EGL_TRUE; 972 973 disp->Extensions.KHR_reusable_sync = EGL_TRUE; 974 975 if (dri2_dpy->image) { 976 if (dri2_dpy->image->base.version >= 10 && 977 dri2_dpy->image->getCapabilities != NULL) { 978 int capabilities; 979 980 capabilities = dri2_dpy->image->getCapabilities(dri2_dpy->dri_screen); 981 disp->Extensions.MESA_drm_image = (capabilities & __DRI_IMAGE_CAP_GLOBAL_NAMES) != 0; 982 983 if (dri2_dpy->image->base.version >= 11) 984 disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; 985 } else { 986 disp->Extensions.MESA_drm_image = EGL_TRUE; 987 if (dri2_dpy->image->base.version >= 11) 988 disp->Extensions.MESA_image_dma_buf_export = EGL_TRUE; 989 } 990 991 disp->Extensions.KHR_image_base = EGL_TRUE; 992 disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE; 993 if (dri2_dpy->image->base.version >= 5 && 994 dri2_dpy->image->createImageFromTexture) { 995 disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE; 996 disp->Extensions.KHR_gl_texture_cubemap_image = EGL_TRUE; 997 998 if (dri2_renderer_query_integer(dri2_dpy, 999 __DRI2_RENDERER_HAS_TEXTURE_3D)) 1000 disp->Extensions.KHR_gl_texture_3D_image = EGL_TRUE; 1001 } 1002#ifdef HAVE_LIBDRM 1003 if (dri2_dpy->image->base.version >= 8 && 1004 dri2_dpy->image->createImageFromDmaBufs) { 1005 disp->Extensions.EXT_image_dma_buf_import = EGL_TRUE; 1006 disp->Extensions.EXT_image_dma_buf_import_modifiers = EGL_TRUE; 1007 } 1008#endif 1009 } 1010 1011 if (dri2_dpy->flush_control) 1012 disp->Extensions.KHR_context_flush_control = EGL_TRUE; 1013 1014 if (dri2_dpy->buffer_damage && dri2_dpy->buffer_damage->set_damage_region) 1015 disp->Extensions.KHR_partial_update = EGL_TRUE; 1016 1017 disp->Extensions.EXT_protected_surface = 1018 dri2_renderer_query_integer(dri2_dpy, 1019 __DRI2_RENDERER_HAS_PROTECTED_CONTENT); 1020} 1021 1022void 1023dri2_setup_swap_interval(_EGLDisplay *disp, int max_swap_interval) 1024{ 1025 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1026 GLint vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1; 1027 1028 /* Allow driconf to override applications.*/ 1029 if (dri2_dpy->config) 1030 dri2_dpy->config->configQueryi(dri2_dpy->dri_screen, 1031 "vblank_mode", &vblank_mode); 1032 switch (vblank_mode) { 1033 case DRI_CONF_VBLANK_NEVER: 1034 dri2_dpy->min_swap_interval = 0; 1035 dri2_dpy->max_swap_interval = 0; 1036 dri2_dpy->default_swap_interval = 0; 1037 break; 1038 case DRI_CONF_VBLANK_ALWAYS_SYNC: 1039 dri2_dpy->min_swap_interval = 1; 1040 dri2_dpy->max_swap_interval = max_swap_interval; 1041 dri2_dpy->default_swap_interval = 1; 1042 break; 1043 case DRI_CONF_VBLANK_DEF_INTERVAL_0: 1044 dri2_dpy->min_swap_interval = 0; 1045 dri2_dpy->max_swap_interval = max_swap_interval; 1046 dri2_dpy->default_swap_interval = 0; 1047 break; 1048 default: 1049 case DRI_CONF_VBLANK_DEF_INTERVAL_1: 1050 dri2_dpy->min_swap_interval = 0; 1051 dri2_dpy->max_swap_interval = max_swap_interval; 1052 dri2_dpy->default_swap_interval = 1; 1053 break; 1054 } 1055} 1056 1057/* All platforms but DRM call this function to create the screen and populate 1058 * the driver_configs. DRM inherits that information from its display - GBM. 1059 */ 1060EGLBoolean 1061dri2_create_screen(_EGLDisplay *disp) 1062{ 1063 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1064 1065 if (dri2_dpy->image_driver) { 1066 dri2_dpy->dri_screen = 1067 dri2_dpy->image_driver->createNewScreen2(0, dri2_dpy->fd, 1068 dri2_dpy->loader_extensions, 1069 dri2_dpy->driver_extensions, 1070 &dri2_dpy->driver_configs, 1071 disp); 1072 } else if (dri2_dpy->dri2) { 1073 if (dri2_dpy->dri2->base.version >= 4) { 1074 dri2_dpy->dri_screen = 1075 dri2_dpy->dri2->createNewScreen2(0, dri2_dpy->fd, 1076 dri2_dpy->loader_extensions, 1077 dri2_dpy->driver_extensions, 1078 &dri2_dpy->driver_configs, disp); 1079 } else { 1080 dri2_dpy->dri_screen = 1081 dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, 1082 dri2_dpy->loader_extensions, 1083 &dri2_dpy->driver_configs, disp); 1084 } 1085 } else { 1086 assert(dri2_dpy->swrast); 1087 if (dri2_dpy->swrast->base.version >= 4) { 1088 dri2_dpy->dri_screen = 1089 dri2_dpy->swrast->createNewScreen2(0, dri2_dpy->loader_extensions, 1090 dri2_dpy->driver_extensions, 1091 &dri2_dpy->driver_configs, disp); 1092 } else { 1093 dri2_dpy->dri_screen = 1094 dri2_dpy->swrast->createNewScreen(0, dri2_dpy->loader_extensions, 1095 &dri2_dpy->driver_configs, disp); 1096 } 1097 } 1098 1099 if (dri2_dpy->dri_screen == NULL) { 1100 _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen"); 1101 return EGL_FALSE; 1102 } 1103 1104 dri2_dpy->own_dri_screen = true; 1105 return EGL_TRUE; 1106} 1107 1108EGLBoolean 1109dri2_setup_extensions(_EGLDisplay *disp) 1110{ 1111 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1112 const struct dri2_extension_match *mandatory_core_extensions; 1113 const __DRIextension **extensions; 1114 1115 extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen); 1116 1117 if (dri2_dpy->image_driver || dri2_dpy->dri2) 1118 mandatory_core_extensions = dri2_core_extensions; 1119 else 1120 mandatory_core_extensions = swrast_core_extensions; 1121 1122 if (!dri2_bind_extensions(dri2_dpy, mandatory_core_extensions, extensions, false)) 1123 return EGL_FALSE; 1124 1125#ifdef HAVE_DRI3_MODIFIERS 1126 dri2_dpy->multibuffers_available = 1127 (dri2_dpy->dri3_major_version > 1 || (dri2_dpy->dri3_major_version == 1 && 1128 dri2_dpy->dri3_minor_version >= 2)) && 1129 (dri2_dpy->present_major_version > 1 || (dri2_dpy->present_major_version == 1 && 1130 dri2_dpy->present_minor_version >= 2)) && 1131 (dri2_dpy->image && dri2_dpy->image->base.version >= 15); 1132#endif 1133 1134 dri2_bind_extensions(dri2_dpy, optional_core_extensions, extensions, true); 1135 return EGL_TRUE; 1136} 1137 1138/** 1139 * Called via eglInitialize(), drv->Initialize(). 1140 * 1141 * This must be guaranteed to be called exactly once, even if eglInitialize is 1142 * called many times (without a eglTerminate in between). 1143 */ 1144static EGLBoolean 1145dri2_initialize(_EGLDisplay *disp) 1146{ 1147 EGLBoolean ret = EGL_FALSE; 1148 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1149 1150 /* In the case where the application calls eglMakeCurrent(context1), 1151 * eglTerminate, then eglInitialize again (without a call to eglReleaseThread 1152 * or eglMakeCurrent(NULL) before that), dri2_dpy structure is still 1153 * initialized, as we need it to be able to free context1 correctly. 1154 * 1155 * It would probably be safest to forcibly release the display with 1156 * dri2_display_release, to make sure the display is reinitialized correctly. 1157 * However, the EGL spec states that we need to keep a reference to the 1158 * current context (so we cannot call dri2_make_current(NULL)), and therefore 1159 * we would leak context1 as we would be missing the old display connection 1160 * to free it up correctly. 1161 */ 1162 if (dri2_dpy) { 1163 dri2_dpy->ref_count++; 1164 return EGL_TRUE; 1165 } 1166 1167 loader_set_logger(_eglLog); 1168 1169 switch (disp->Platform) { 1170 case _EGL_PLATFORM_SURFACELESS: 1171 ret = dri2_initialize_surfaceless(disp); 1172 break; 1173 case _EGL_PLATFORM_DEVICE: 1174 ret = dri2_initialize_device(disp); 1175 break; 1176 case _EGL_PLATFORM_X11: 1177 case _EGL_PLATFORM_XCB: 1178 ret = dri2_initialize_x11(disp); 1179 break; 1180 case _EGL_PLATFORM_DRM: 1181 ret = dri2_initialize_drm(disp); 1182 break; 1183 case _EGL_PLATFORM_WAYLAND: 1184 ret = dri2_initialize_wayland(disp); 1185 break; 1186 case _EGL_PLATFORM_ANDROID: 1187 ret = dri2_initialize_android(disp); 1188 break; 1189 default: 1190 unreachable("Callers ensure we cannot get here."); 1191 return EGL_FALSE; 1192 } 1193 1194 if (!ret) 1195 return EGL_FALSE; 1196 1197 dri2_dpy = dri2_egl_display(disp); 1198 dri2_dpy->ref_count++; 1199 1200 return EGL_TRUE; 1201} 1202 1203/** 1204 * Decrement display reference count, and free up display if necessary. 1205 */ 1206static void 1207dri2_display_release(_EGLDisplay *disp) 1208{ 1209 struct dri2_egl_display *dri2_dpy; 1210 1211 if (!disp) 1212 return; 1213 1214 dri2_dpy = dri2_egl_display(disp); 1215 1216 assert(dri2_dpy->ref_count > 0); 1217 dri2_dpy->ref_count--; 1218 1219 if (dri2_dpy->ref_count > 0) 1220 return; 1221 1222 _eglCleanupDisplay(disp); 1223 dri2_display_destroy(disp); 1224} 1225 1226void 1227dri2_display_destroy(_EGLDisplay *disp) 1228{ 1229 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1230 1231 if (dri2_dpy->own_dri_screen) { 1232 if (dri2_dpy->vtbl && dri2_dpy->vtbl->close_screen_notify) 1233 dri2_dpy->vtbl->close_screen_notify(disp); 1234 dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen); 1235 } 1236 if (dri2_dpy->fd >= 0) 1237 close(dri2_dpy->fd); 1238 1239 /* Don't dlclose the driver when building with the address sanitizer, so you 1240 * get good symbols from the leak reports. 1241 */ 1242#if !BUILT_WITH_ASAN || defined(NDEBUG) 1243 if (dri2_dpy->driver) 1244 dlclose(dri2_dpy->driver); 1245#endif 1246 1247 free(dri2_dpy->driver_name); 1248 1249#ifdef HAVE_WAYLAND_PLATFORM 1250 free(dri2_dpy->device_name); 1251#endif 1252 1253 switch (disp->Platform) { 1254 case _EGL_PLATFORM_X11: 1255 dri2_teardown_x11(dri2_dpy); 1256 break; 1257 case _EGL_PLATFORM_DRM: 1258 dri2_teardown_drm(dri2_dpy); 1259 break; 1260 case _EGL_PLATFORM_WAYLAND: 1261 dri2_teardown_wayland(dri2_dpy); 1262 break; 1263 default: 1264 /* TODO: add teardown for other platforms */ 1265 break; 1266 } 1267 1268 /* The drm platform does not create the screen/driver_configs but reuses 1269 * the ones from the gbm device. As such the gbm itself is responsible 1270 * for the cleanup. 1271 */ 1272 if (disp->Platform != _EGL_PLATFORM_DRM && dri2_dpy->driver_configs) { 1273 for (unsigned i = 0; dri2_dpy->driver_configs[i]; i++) 1274 free((__DRIconfig *) dri2_dpy->driver_configs[i]); 1275 free(dri2_dpy->driver_configs); 1276 } 1277 free(dri2_dpy); 1278 disp->DriverData = NULL; 1279} 1280 1281__DRIbuffer * 1282dri2_egl_surface_alloc_local_buffer(struct dri2_egl_surface *dri2_surf, 1283 unsigned int att, unsigned int format) 1284{ 1285 struct dri2_egl_display *dri2_dpy = 1286 dri2_egl_display(dri2_surf->base.Resource.Display); 1287 1288 if (att >= ARRAY_SIZE(dri2_surf->local_buffers)) 1289 return NULL; 1290 1291 if (!dri2_surf->local_buffers[att]) { 1292 dri2_surf->local_buffers[att] = 1293 dri2_dpy->dri2->allocateBuffer(dri2_dpy->dri_screen, att, format, 1294 dri2_surf->base.Width, dri2_surf->base.Height); 1295 } 1296 1297 return dri2_surf->local_buffers[att]; 1298} 1299 1300void 1301dri2_egl_surface_free_local_buffers(struct dri2_egl_surface *dri2_surf) 1302{ 1303 struct dri2_egl_display *dri2_dpy = 1304 dri2_egl_display(dri2_surf->base.Resource.Display); 1305 1306 for (int i = 0; i < ARRAY_SIZE(dri2_surf->local_buffers); i++) { 1307 if (dri2_surf->local_buffers[i]) { 1308 dri2_dpy->dri2->releaseBuffer(dri2_dpy->dri_screen, 1309 dri2_surf->local_buffers[i]); 1310 dri2_surf->local_buffers[i] = NULL; 1311 } 1312 } 1313} 1314 1315/** 1316 * Called via eglTerminate(), drv->Terminate(). 1317 * 1318 * This must be guaranteed to be called exactly once, even if eglTerminate is 1319 * called many times (without a eglInitialize in between). 1320 */ 1321static EGLBoolean 1322dri2_terminate(_EGLDisplay *disp) 1323{ 1324 /* Release all non-current Context/Surfaces. */ 1325 _eglReleaseDisplayResources(disp); 1326 1327 dri2_display_release(disp); 1328 1329 return EGL_TRUE; 1330} 1331 1332/** 1333 * Set the error code after a call to 1334 * dri2_egl_display::dri2::createContextAttribs. 1335 */ 1336static void 1337dri2_create_context_attribs_error(int dri_error) 1338{ 1339 EGLint egl_error; 1340 1341 switch (dri_error) { 1342 case __DRI_CTX_ERROR_SUCCESS: 1343 return; 1344 1345 case __DRI_CTX_ERROR_NO_MEMORY: 1346 egl_error = EGL_BAD_ALLOC; 1347 break; 1348 1349 /* From the EGL_KHR_create_context spec, section "Errors": 1350 * 1351 * * If <config> does not support a client API context compatible 1352 * with the requested API major and minor version, [...] context flags, 1353 * and context reset notification behavior (for client API types where 1354 * these attributes are supported), then an EGL_BAD_MATCH error is 1355 * generated. 1356 * 1357 * * If an OpenGL ES context is requested and the values for 1358 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 1359 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 1360 * is not defined, than an EGL_BAD_MATCH error is generated. 1361 * 1362 * * If an OpenGL context is requested, the requested version is 1363 * greater than 3.2, and the value for attribute 1364 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has any 1365 * bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and 1366 * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than 1367 * one of these bits set; or if the implementation does not support 1368 * the requested profile, then an EGL_BAD_MATCH error is generated. 1369 */ 1370 case __DRI_CTX_ERROR_BAD_API: 1371 case __DRI_CTX_ERROR_BAD_VERSION: 1372 case __DRI_CTX_ERROR_BAD_FLAG: 1373 egl_error = EGL_BAD_MATCH; 1374 break; 1375 1376 /* From the EGL_KHR_create_context spec, section "Errors": 1377 * 1378 * * If an attribute name or attribute value in <attrib_list> is not 1379 * recognized (including unrecognized bits in bitmask attributes), 1380 * then an EGL_BAD_ATTRIBUTE error is generated." 1381 */ 1382 case __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE: 1383 case __DRI_CTX_ERROR_UNKNOWN_FLAG: 1384 egl_error = EGL_BAD_ATTRIBUTE; 1385 break; 1386 1387 default: 1388 assert(!"unknown dri_error code"); 1389 egl_error = EGL_BAD_MATCH; 1390 break; 1391 } 1392 1393 _eglError(egl_error, "dri2_create_context"); 1394} 1395 1396static bool 1397dri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx, 1398 struct dri2_egl_display *dri2_dpy, 1399 uint32_t *ctx_attribs, 1400 unsigned *num_attribs) 1401{ 1402 int pos = 0; 1403 1404 assert(*num_attribs >= NUM_ATTRIBS); 1405 1406 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MAJOR_VERSION; 1407 ctx_attribs[pos++] = dri2_ctx->base.ClientMajorVersion; 1408 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_MINOR_VERSION; 1409 ctx_attribs[pos++] = dri2_ctx->base.ClientMinorVersion; 1410 1411 if (dri2_ctx->base.Flags != 0 || dri2_ctx->base.NoError) { 1412 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 1413 * extension, don't even try to send it the robust-access flag. 1414 * It may explode. Instead, generate the required EGL error here. 1415 */ 1416 if ((dri2_ctx->base.Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0 1417 && !dri2_dpy->robustness) { 1418 _eglError(EGL_BAD_MATCH, "eglCreateContext"); 1419 return false; 1420 } 1421 1422 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_FLAGS; 1423 ctx_attribs[pos++] = dri2_ctx->base.Flags | 1424 (dri2_ctx->base.NoError ? __DRI_CTX_FLAG_NO_ERROR : 0); 1425 } 1426 1427 if (dri2_ctx->base.ResetNotificationStrategy != EGL_NO_RESET_NOTIFICATION_KHR) { 1428 /* If the implementation doesn't support the __DRI2_ROBUSTNESS 1429 * extension, don't even try to send it a reset strategy. It may 1430 * explode. Instead, generate the required EGL error here. 1431 */ 1432 if (!dri2_dpy->robustness) { 1433 _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 1434 return false; 1435 } 1436 1437 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RESET_STRATEGY; 1438 ctx_attribs[pos++] = __DRI_CTX_RESET_LOSE_CONTEXT; 1439 } 1440 1441 if (dri2_ctx->base.ContextPriority != EGL_CONTEXT_PRIORITY_MEDIUM_IMG) { 1442 unsigned val; 1443 1444 switch (dri2_ctx->base.ContextPriority) { 1445 case EGL_CONTEXT_PRIORITY_HIGH_IMG: 1446 val = __DRI_CTX_PRIORITY_HIGH; 1447 break; 1448 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: 1449 val = __DRI_CTX_PRIORITY_MEDIUM; 1450 break; 1451 case EGL_CONTEXT_PRIORITY_LOW_IMG: 1452 val = __DRI_CTX_PRIORITY_LOW; 1453 break; 1454 default: 1455 _eglError(EGL_BAD_CONFIG, "eglCreateContext"); 1456 return false; 1457 } 1458 1459 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_PRIORITY; 1460 ctx_attribs[pos++] = val; 1461 } 1462 1463 if (dri2_ctx->base.ReleaseBehavior == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR) { 1464 ctx_attribs[pos++] = __DRI_CTX_ATTRIB_RELEASE_BEHAVIOR; 1465 ctx_attribs[pos++] = __DRI_CTX_RELEASE_BEHAVIOR_NONE; 1466 } 1467 1468 *num_attribs = pos; 1469 1470 return true; 1471} 1472 1473/** 1474 * Called via eglCreateContext(), drv->CreateContext(). 1475 */ 1476static _EGLContext * 1477dri2_create_context(_EGLDisplay *disp, _EGLConfig *conf, 1478 _EGLContext *share_list, const EGLint *attrib_list) 1479{ 1480 struct dri2_egl_context *dri2_ctx; 1481 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1482 struct dri2_egl_context *dri2_ctx_shared = dri2_egl_context(share_list); 1483 __DRIcontext *shared = 1484 dri2_ctx_shared ? dri2_ctx_shared->dri_context : NULL; 1485 struct dri2_egl_config *dri2_config = dri2_egl_config(conf); 1486 const __DRIconfig *dri_config; 1487 int api; 1488 unsigned error; 1489 unsigned num_attribs = NUM_ATTRIBS; 1490 uint32_t ctx_attribs[NUM_ATTRIBS]; 1491 1492 dri2_ctx = malloc(sizeof *dri2_ctx); 1493 if (!dri2_ctx) { 1494 _eglError(EGL_BAD_ALLOC, "eglCreateContext"); 1495 return NULL; 1496 } 1497 1498 if (!_eglInitContext(&dri2_ctx->base, disp, conf, attrib_list)) 1499 goto cleanup; 1500 1501 /* The EGL_EXT_create_context_robustness spec says: 1502 * 1503 * "Add to the eglCreateContext context creation errors: [...] 1504 * 1505 * * If the reset notification behavior of <share_context> and the 1506 * newly created context are different then an EGL_BAD_MATCH error is 1507 * generated." 1508 */ 1509 if (share_list && share_list->ResetNotificationStrategy != 1510 dri2_ctx->base.ResetNotificationStrategy) { 1511 _eglError(EGL_BAD_MATCH, "eglCreateContext"); 1512 goto cleanup; 1513 } 1514 1515 /* The EGL_KHR_create_context_no_error spec says: 1516 * 1517 * "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR 1518 * used to create <share_context> does not match the value of 1519 * EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created." 1520 */ 1521 if (share_list && share_list->NoError != dri2_ctx->base.NoError) { 1522 _eglError(EGL_BAD_MATCH, "eglCreateContext"); 1523 goto cleanup; 1524 } 1525 1526 switch (dri2_ctx->base.ClientAPI) { 1527 case EGL_OPENGL_ES_API: 1528 switch (dri2_ctx->base.ClientMajorVersion) { 1529 case 1: 1530 api = __DRI_API_GLES; 1531 break; 1532 case 2: 1533 api = __DRI_API_GLES2; 1534 break; 1535 case 3: 1536 api = __DRI_API_GLES3; 1537 break; 1538 default: 1539 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1540 free(dri2_ctx); 1541 return NULL; 1542 } 1543 break; 1544 case EGL_OPENGL_API: 1545 if ((dri2_ctx->base.ClientMajorVersion >= 4 1546 || (dri2_ctx->base.ClientMajorVersion == 3 1547 && dri2_ctx->base.ClientMinorVersion >= 2)) 1548 && dri2_ctx->base.Profile == EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) 1549 api = __DRI_API_OPENGL_CORE; 1550 else if (dri2_ctx->base.ClientMajorVersion == 3 && 1551 dri2_ctx->base.ClientMinorVersion == 1) 1552 api = __DRI_API_OPENGL_CORE; 1553 else 1554 api = __DRI_API_OPENGL; 1555 break; 1556 default: 1557 _eglError(EGL_BAD_PARAMETER, "eglCreateContext"); 1558 free(dri2_ctx); 1559 return NULL; 1560 } 1561 1562 if (conf != NULL) { 1563 /* The config chosen here isn't necessarily 1564 * used for surfaces later. 1565 * A pixmap surface will use the single config. 1566 * This opportunity depends on disabling the 1567 * doubleBufferMode check in 1568 * src/mesa/main/context.c:check_compatible() 1569 */ 1570 if (dri2_config->dri_config[1][0]) 1571 dri_config = dri2_config->dri_config[1][0]; 1572 else 1573 dri_config = dri2_config->dri_config[0][0]; 1574 } 1575 else 1576 dri_config = NULL; 1577 1578 if (!dri2_fill_context_attribs(dri2_ctx, dri2_dpy, ctx_attribs, 1579 &num_attribs)) 1580 goto cleanup; 1581 1582 if (dri2_dpy->image_driver) { 1583 dri2_ctx->dri_context = 1584 dri2_dpy->image_driver->createContextAttribs(dri2_dpy->dri_screen, 1585 api, 1586 dri_config, 1587 shared, 1588 num_attribs / 2, 1589 ctx_attribs, 1590 & error, 1591 dri2_ctx); 1592 dri2_create_context_attribs_error(error); 1593 } else if (dri2_dpy->dri2) { 1594 if (dri2_dpy->dri2->base.version >= 3) { 1595 dri2_ctx->dri_context = 1596 dri2_dpy->dri2->createContextAttribs(dri2_dpy->dri_screen, 1597 api, 1598 dri_config, 1599 shared, 1600 num_attribs / 2, 1601 ctx_attribs, 1602 & error, 1603 dri2_ctx); 1604 dri2_create_context_attribs_error(error); 1605 } else { 1606 dri2_ctx->dri_context = 1607 dri2_dpy->dri2->createNewContextForAPI(dri2_dpy->dri_screen, 1608 api, 1609 dri_config, 1610 shared, 1611 dri2_ctx); 1612 } 1613 } else { 1614 assert(dri2_dpy->swrast); 1615 if (dri2_dpy->swrast->base.version >= 3) { 1616 dri2_ctx->dri_context = 1617 dri2_dpy->swrast->createContextAttribs(dri2_dpy->dri_screen, 1618 api, 1619 dri_config, 1620 shared, 1621 num_attribs / 2, 1622 ctx_attribs, 1623 & error, 1624 dri2_ctx); 1625 dri2_create_context_attribs_error(error); 1626 } else { 1627 dri2_ctx->dri_context = 1628 dri2_dpy->swrast->createNewContextForAPI(dri2_dpy->dri_screen, 1629 api, 1630 dri_config, 1631 shared, 1632 dri2_ctx); 1633 } 1634 } 1635 1636 if (!dri2_ctx->dri_context) 1637 goto cleanup; 1638 1639 return &dri2_ctx->base; 1640 1641 cleanup: 1642 free(dri2_ctx); 1643 return NULL; 1644} 1645 1646/** 1647 * Called via eglDestroyContext(), drv->DestroyContext(). 1648 */ 1649static EGLBoolean 1650dri2_destroy_context(_EGLDisplay *disp, _EGLContext *ctx) 1651{ 1652 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1653 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1654 1655 if (_eglPutContext(ctx)) { 1656 dri2_dpy->core->destroyContext(dri2_ctx->dri_context); 1657 free(dri2_ctx); 1658 } 1659 1660 return EGL_TRUE; 1661} 1662 1663EGLBoolean 1664dri2_init_surface(_EGLSurface *surf, _EGLDisplay *disp, EGLint type, 1665 _EGLConfig *conf, const EGLint *attrib_list, 1666 EGLBoolean enable_out_fence, void *native_surface) 1667{ 1668 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1669 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1670 1671 dri2_surf->out_fence_fd = -1; 1672 dri2_surf->enable_out_fence = false; 1673 if (dri2_dpy->fence && dri2_dpy->fence->base.version >= 2 && 1674 dri2_dpy->fence->get_capabilities && 1675 (dri2_dpy->fence->get_capabilities(dri2_dpy->dri_screen) & 1676 __DRI_FENCE_CAP_NATIVE_FD)) { 1677 dri2_surf->enable_out_fence = enable_out_fence; 1678 } 1679 1680 return _eglInitSurface(surf, disp, type, conf, attrib_list, native_surface); 1681} 1682 1683static void 1684dri2_surface_set_out_fence_fd( _EGLSurface *surf, int fence_fd) 1685{ 1686 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1687 1688 if (dri2_surf->out_fence_fd >= 0) 1689 close(dri2_surf->out_fence_fd); 1690 1691 dri2_surf->out_fence_fd = fence_fd; 1692} 1693 1694void 1695dri2_fini_surface(_EGLSurface *surf) 1696{ 1697 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1698 1699 dri2_surface_set_out_fence_fd(surf, -1); 1700 dri2_surf->enable_out_fence = false; 1701} 1702 1703static EGLBoolean 1704dri2_destroy_surface(_EGLDisplay *disp, _EGLSurface *surf) 1705{ 1706 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1707 1708 if (!_eglPutSurface(surf)) 1709 return EGL_TRUE; 1710 1711 return dri2_dpy->vtbl->destroy_surface(disp, surf); 1712} 1713 1714static void 1715dri2_surf_update_fence_fd(_EGLContext *ctx, 1716 _EGLDisplay *disp, _EGLSurface *surf) 1717{ 1718 __DRIcontext *dri_ctx = dri2_egl_context(ctx)->dri_context; 1719 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1720 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1721 int fence_fd = -1; 1722 void *fence; 1723 1724 if (!dri2_surf->enable_out_fence) 1725 return; 1726 1727 fence = dri2_dpy->fence->create_fence_fd(dri_ctx, -1); 1728 if (fence) { 1729 fence_fd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen, 1730 fence); 1731 dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, fence); 1732 } 1733 dri2_surface_set_out_fence_fd(surf, fence_fd); 1734} 1735 1736EGLBoolean 1737dri2_create_drawable(struct dri2_egl_display *dri2_dpy, 1738 const __DRIconfig *config, 1739 struct dri2_egl_surface *dri2_surf, 1740 void *loaderPrivate) 1741{ 1742 __DRIcreateNewDrawableFunc createNewDrawable; 1743 1744 if (dri2_dpy->image_driver) 1745 createNewDrawable = dri2_dpy->image_driver->createNewDrawable; 1746 else if (dri2_dpy->dri2) 1747 createNewDrawable = dri2_dpy->dri2->createNewDrawable; 1748 else if (dri2_dpy->swrast) 1749 createNewDrawable = dri2_dpy->swrast->createNewDrawable; 1750 else 1751 return _eglError(EGL_BAD_ALLOC, "no createNewDrawable"); 1752 1753 dri2_surf->dri_drawable = createNewDrawable(dri2_dpy->dri_screen, 1754 config, loaderPrivate); 1755 if (dri2_surf->dri_drawable == NULL) 1756 return _eglError(EGL_BAD_ALLOC, "createNewDrawable"); 1757 1758 return EGL_TRUE; 1759} 1760 1761/** 1762 * Called via eglMakeCurrent(), drv->MakeCurrent(). 1763 */ 1764static EGLBoolean 1765dri2_make_current(_EGLDisplay *disp, _EGLSurface *dsurf, 1766 _EGLSurface *rsurf, _EGLContext *ctx) 1767{ 1768 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1769 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1770 _EGLDisplay *old_disp = NULL; 1771 struct dri2_egl_display *old_dri2_dpy = NULL; 1772 _EGLContext *old_ctx; 1773 _EGLSurface *old_dsurf, *old_rsurf; 1774 _EGLSurface *tmp_dsurf, *tmp_rsurf; 1775 __DRIdrawable *ddraw, *rdraw; 1776 __DRIcontext *cctx; 1777 EGLint egl_error = EGL_SUCCESS; 1778 1779 if (!dri2_dpy) 1780 return _eglError(EGL_NOT_INITIALIZED, "eglMakeCurrent"); 1781 1782 /* make new bindings, set the EGL error otherwise */ 1783 if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf)) 1784 return EGL_FALSE; 1785 1786 if (old_ctx) { 1787 __DRIcontext *old_cctx = dri2_egl_context(old_ctx)->dri_context; 1788 old_disp = old_ctx->Resource.Display; 1789 old_dri2_dpy = dri2_egl_display(old_disp); 1790 1791 /* flush before context switch */ 1792 dri2_gl_flush(); 1793 1794 if (old_dsurf) 1795 dri2_surf_update_fence_fd(old_ctx, disp, old_dsurf); 1796 1797 /* Disable shared buffer mode */ 1798 if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && 1799 old_dri2_dpy->vtbl->set_shared_buffer_mode) { 1800 old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, false); 1801 } 1802 1803 dri2_dpy->core->unbindContext(old_cctx); 1804 } 1805 1806 ddraw = (dsurf) ? dri2_dpy->vtbl->get_dri_drawable(dsurf) : NULL; 1807 rdraw = (rsurf) ? dri2_dpy->vtbl->get_dri_drawable(rsurf) : NULL; 1808 cctx = (dri2_ctx) ? dri2_ctx->dri_context : NULL; 1809 1810 if (cctx || ddraw || rdraw) { 1811 if (!dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 1812 _EGLContext *tmp_ctx; 1813 1814 /* dri2_dpy->core->bindContext failed. We cannot tell for sure why, but 1815 * setting the error to EGL_BAD_MATCH is surely better than leaving it 1816 * as EGL_SUCCESS. 1817 */ 1818 egl_error = EGL_BAD_MATCH; 1819 1820 /* undo the previous _eglBindContext */ 1821 _eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &tmp_dsurf, &tmp_rsurf); 1822 assert(&dri2_ctx->base == ctx && 1823 tmp_dsurf == dsurf && 1824 tmp_rsurf == rsurf); 1825 1826 _eglPutSurface(dsurf); 1827 _eglPutSurface(rsurf); 1828 _eglPutContext(ctx); 1829 1830 _eglPutSurface(old_dsurf); 1831 _eglPutSurface(old_rsurf); 1832 _eglPutContext(old_ctx); 1833 1834 ddraw = (old_dsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_dsurf) : NULL; 1835 rdraw = (old_rsurf) ? dri2_dpy->vtbl->get_dri_drawable(old_rsurf) : NULL; 1836 cctx = (old_ctx) ? dri2_egl_context(old_ctx)->dri_context : NULL; 1837 1838 /* undo the previous dri2_dpy->core->unbindContext */ 1839 if (dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) { 1840 if (old_dsurf && _eglSurfaceInSharedBufferMode(old_dsurf) && 1841 old_dri2_dpy->vtbl->set_shared_buffer_mode) { 1842 old_dri2_dpy->vtbl->set_shared_buffer_mode(old_disp, old_dsurf, true); 1843 } 1844 1845 return _eglError(egl_error, "eglMakeCurrent"); 1846 } 1847 1848 /* We cannot restore the same state as it was before calling 1849 * eglMakeCurrent() and the spec isn't clear about what to do. We 1850 * can prevent EGL from calling into the DRI driver with no DRI 1851 * context bound. 1852 */ 1853 dsurf = rsurf = NULL; 1854 ctx = NULL; 1855 1856 _eglBindContext(ctx, dsurf, rsurf, &tmp_ctx, &tmp_dsurf, &tmp_rsurf); 1857 assert(tmp_ctx == old_ctx && tmp_dsurf == old_dsurf && 1858 tmp_rsurf == old_rsurf); 1859 1860 _eglLog(_EGL_WARNING, "DRI2: failed to rebind the previous context"); 1861 } else { 1862 /* dri2_dpy->core->bindContext succeeded, so take a reference on the 1863 * dri2_dpy. This prevents dri2_dpy from being reinitialized when a 1864 * EGLDisplay is terminated and then initialized again while a 1865 * context is still bound. See dri2_intitialize() for a more in depth 1866 * explanation. */ 1867 dri2_dpy->ref_count++; 1868 } 1869 } 1870 1871 dri2_destroy_surface(disp, old_dsurf); 1872 dri2_destroy_surface(disp, old_rsurf); 1873 1874 if (old_ctx) { 1875 dri2_destroy_context(disp, old_ctx); 1876 dri2_display_release(old_disp); 1877 } 1878 1879 if (egl_error != EGL_SUCCESS) 1880 return _eglError(egl_error, "eglMakeCurrent"); 1881 1882 if (dsurf && _eglSurfaceHasMutableRenderBuffer(dsurf) && 1883 dri2_dpy->vtbl->set_shared_buffer_mode) { 1884 /* Always update the shared buffer mode. This is obviously needed when 1885 * the active EGL_RENDER_BUFFER is EGL_SINGLE_BUFFER. When 1886 * EGL_RENDER_BUFFER is EGL_BACK_BUFFER, the update protects us in the 1887 * case where external non-EGL API may have changed window's shared 1888 * buffer mode since we last saw it. 1889 */ 1890 bool mode = (dsurf->ActiveRenderBuffer == EGL_SINGLE_BUFFER); 1891 dri2_dpy->vtbl->set_shared_buffer_mode(disp, dsurf, mode); 1892 } 1893 1894 return EGL_TRUE; 1895} 1896 1897__DRIdrawable * 1898dri2_surface_get_dri_drawable(_EGLSurface *surf) 1899{ 1900 struct dri2_egl_surface *dri2_surf = dri2_egl_surface(surf); 1901 1902 return dri2_surf->dri_drawable; 1903} 1904 1905/* 1906 * Called from eglGetProcAddress() via drv->GetProcAddress(). 1907 */ 1908static _EGLProc 1909dri2_get_proc_address(const char *procname) 1910{ 1911 return _glapi_get_proc_address(procname); 1912} 1913 1914static _EGLSurface* 1915dri2_create_window_surface(_EGLDisplay *disp, _EGLConfig *conf, 1916 void *native_window, const EGLint *attrib_list) 1917{ 1918 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1919 return dri2_dpy->vtbl->create_window_surface(disp, conf, native_window, 1920 attrib_list); 1921} 1922 1923static _EGLSurface* 1924dri2_create_pixmap_surface(_EGLDisplay *disp, _EGLConfig *conf, 1925 void *native_pixmap, const EGLint *attrib_list) 1926{ 1927 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1928 if (!dri2_dpy->vtbl->create_pixmap_surface) 1929 return NULL; 1930 return dri2_dpy->vtbl->create_pixmap_surface(disp, conf, native_pixmap, 1931 attrib_list); 1932} 1933 1934static _EGLSurface* 1935dri2_create_pbuffer_surface(_EGLDisplay *disp, _EGLConfig *conf, 1936 const EGLint *attrib_list) 1937{ 1938 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1939 if (!dri2_dpy->vtbl->create_pbuffer_surface) 1940 return NULL; 1941 return dri2_dpy->vtbl->create_pbuffer_surface(disp, conf, attrib_list); 1942} 1943 1944static EGLBoolean 1945dri2_swap_interval(_EGLDisplay *disp, _EGLSurface *surf, EGLint interval) 1946{ 1947 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1948 if (!dri2_dpy->vtbl->swap_interval) 1949 return EGL_TRUE; 1950 return dri2_dpy->vtbl->swap_interval(disp, surf, interval); 1951} 1952 1953/** 1954 * Asks the client API to flush any rendering to the drawable so that we can 1955 * do our swapbuffers. 1956 */ 1957void 1958dri2_flush_drawable_for_swapbuffers(_EGLDisplay *disp, _EGLSurface *draw) 1959{ 1960 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1961 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(draw); 1962 1963 if (dri2_dpy->flush) { 1964 if (dri2_dpy->flush->base.version >= 4) { 1965 /* We know there's a current context because: 1966 * 1967 * "If surface is not bound to the calling thread’s current 1968 * context, an EGL_BAD_SURFACE error is generated." 1969 */ 1970 _EGLContext *ctx = _eglGetCurrentContext(); 1971 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 1972 1973 /* From the EGL 1.4 spec (page 52): 1974 * 1975 * "The contents of ancillary buffers are always undefined 1976 * after calling eglSwapBuffers." 1977 */ 1978 dri2_dpy->flush->flush_with_flags(dri2_ctx->dri_context, 1979 dri_drawable, 1980 __DRI2_FLUSH_DRAWABLE | 1981 __DRI2_FLUSH_INVALIDATE_ANCILLARY, 1982 __DRI2_THROTTLE_SWAPBUFFER); 1983 } else { 1984 dri2_dpy->flush->flush(dri_drawable); 1985 } 1986 } 1987} 1988 1989static EGLBoolean 1990dri2_swap_buffers(_EGLDisplay *disp, _EGLSurface *surf) 1991{ 1992 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 1993 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 1994 _EGLContext *ctx = _eglGetCurrentContext(); 1995 EGLBoolean ret; 1996 1997 if (ctx && surf) 1998 dri2_surf_update_fence_fd(ctx, disp, surf); 1999 ret = dri2_dpy->vtbl->swap_buffers(disp, surf); 2000 2001 /* SwapBuffers marks the end of the frame; reset the damage region for 2002 * use again next time. 2003 */ 2004 if (ret && dri2_dpy->buffer_damage && 2005 dri2_dpy->buffer_damage->set_damage_region) 2006 dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); 2007 2008 return ret; 2009} 2010 2011static EGLBoolean 2012dri2_swap_buffers_with_damage(_EGLDisplay *disp, _EGLSurface *surf, 2013 const EGLint *rects, EGLint n_rects) 2014{ 2015 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2016 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2017 _EGLContext *ctx = _eglGetCurrentContext(); 2018 EGLBoolean ret; 2019 2020 if (ctx && surf) 2021 dri2_surf_update_fence_fd(ctx, disp, surf); 2022 if (dri2_dpy->vtbl->swap_buffers_with_damage) 2023 ret = dri2_dpy->vtbl->swap_buffers_with_damage(disp, surf, 2024 rects, n_rects); 2025 else 2026 ret = dri2_dpy->vtbl->swap_buffers(disp, surf); 2027 2028 /* SwapBuffers marks the end of the frame; reset the damage region for 2029 * use again next time. 2030 */ 2031 if (ret && dri2_dpy->buffer_damage && 2032 dri2_dpy->buffer_damage->set_damage_region) 2033 dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); 2034 2035 return ret; 2036} 2037 2038static EGLBoolean 2039dri2_swap_buffers_region(_EGLDisplay *disp, _EGLSurface *surf, 2040 EGLint numRects, const EGLint *rects) 2041{ 2042 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2043 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2044 EGLBoolean ret; 2045 2046 if (!dri2_dpy->vtbl->swap_buffers_region) 2047 return EGL_FALSE; 2048 ret = dri2_dpy->vtbl->swap_buffers_region(disp, surf, numRects, rects); 2049 2050 /* SwapBuffers marks the end of the frame; reset the damage region for 2051 * use again next time. 2052 */ 2053 if (ret && dri2_dpy->buffer_damage && 2054 dri2_dpy->buffer_damage->set_damage_region) 2055 dri2_dpy->buffer_damage->set_damage_region(dri_drawable, 0, NULL); 2056 2057 return ret; 2058} 2059 2060static EGLBoolean 2061dri2_set_damage_region(_EGLDisplay *disp, _EGLSurface *surf, 2062 EGLint *rects, EGLint n_rects) 2063{ 2064 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2065 __DRIdrawable *drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2066 2067 if (!dri2_dpy->buffer_damage || !dri2_dpy->buffer_damage->set_damage_region) 2068 return EGL_FALSE; 2069 2070 dri2_dpy->buffer_damage->set_damage_region(drawable, n_rects, rects); 2071 return EGL_TRUE; 2072} 2073 2074static EGLBoolean 2075dri2_post_sub_buffer(_EGLDisplay *disp, _EGLSurface *surf, 2076 EGLint x, EGLint y, EGLint width, EGLint height) 2077{ 2078 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2079 if (!dri2_dpy->vtbl->post_sub_buffer) 2080 return EGL_FALSE; 2081 return dri2_dpy->vtbl->post_sub_buffer(disp, surf, x, y, width, height); 2082} 2083 2084static EGLBoolean 2085dri2_copy_buffers(_EGLDisplay *disp, _EGLSurface *surf, void *native_pixmap_target) 2086{ 2087 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2088 if (!dri2_dpy->vtbl->copy_buffers) 2089 return _eglError(EGL_BAD_NATIVE_PIXMAP, "no support for native pixmaps"); 2090 return dri2_dpy->vtbl->copy_buffers(disp, surf, native_pixmap_target); 2091} 2092 2093static EGLint 2094dri2_query_buffer_age(_EGLDisplay *disp, _EGLSurface *surf) 2095{ 2096 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2097 if (!dri2_dpy->vtbl->query_buffer_age) 2098 return 0; 2099 return dri2_dpy->vtbl->query_buffer_age(disp, surf); 2100} 2101 2102static EGLBoolean 2103dri2_wait_client(_EGLDisplay *disp, _EGLContext *ctx) 2104{ 2105 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2106 _EGLSurface *surf = ctx->DrawSurface; 2107 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2108 2109 /* FIXME: If EGL allows frontbuffer rendering for window surfaces, 2110 * we need to copy fake to real here.*/ 2111 2112 if (dri2_dpy->flush != NULL) 2113 dri2_dpy->flush->flush(dri_drawable); 2114 2115 return EGL_TRUE; 2116} 2117 2118static EGLBoolean 2119dri2_wait_native(EGLint engine) 2120{ 2121 if (engine != EGL_CORE_NATIVE_ENGINE) 2122 return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); 2123 /* glXWaitX(); */ 2124 2125 return EGL_TRUE; 2126} 2127 2128static EGLBoolean 2129dri2_bind_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 2130{ 2131 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2132 struct dri2_egl_context *dri2_ctx; 2133 _EGLContext *ctx; 2134 GLint format, target; 2135 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2136 2137 ctx = _eglGetCurrentContext(); 2138 dri2_ctx = dri2_egl_context(ctx); 2139 2140 if (!_eglBindTexImage(disp, surf, buffer)) 2141 return EGL_FALSE; 2142 2143 switch (surf->TextureFormat) { 2144 case EGL_TEXTURE_RGB: 2145 format = __DRI_TEXTURE_FORMAT_RGB; 2146 break; 2147 case EGL_TEXTURE_RGBA: 2148 format = __DRI_TEXTURE_FORMAT_RGBA; 2149 break; 2150 default: 2151 assert(!"Unexpected texture format in dri2_bind_tex_image()"); 2152 format = __DRI_TEXTURE_FORMAT_RGBA; 2153 } 2154 2155 switch (surf->TextureTarget) { 2156 case EGL_TEXTURE_2D: 2157 target = GL_TEXTURE_2D; 2158 break; 2159 default: 2160 target = GL_TEXTURE_2D; 2161 assert(!"Unexpected texture target in dri2_bind_tex_image()"); 2162 } 2163 2164 dri2_dpy->tex_buffer->setTexBuffer2(dri2_ctx->dri_context, 2165 target, format, 2166 dri_drawable); 2167 2168 return EGL_TRUE; 2169} 2170 2171static EGLBoolean 2172dri2_release_tex_image(_EGLDisplay *disp, _EGLSurface *surf, EGLint buffer) 2173{ 2174 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2175 struct dri2_egl_context *dri2_ctx; 2176 _EGLContext *ctx; 2177 GLint target; 2178 __DRIdrawable *dri_drawable = dri2_dpy->vtbl->get_dri_drawable(surf); 2179 2180 ctx = _eglGetCurrentContext(); 2181 dri2_ctx = dri2_egl_context(ctx); 2182 2183 if (!_eglReleaseTexImage(disp, surf, buffer)) 2184 return EGL_FALSE; 2185 2186 switch (surf->TextureTarget) { 2187 case EGL_TEXTURE_2D: 2188 target = GL_TEXTURE_2D; 2189 break; 2190 default: 2191 assert(!"missing texture target"); 2192 } 2193 2194 if (dri2_dpy->tex_buffer->base.version >= 3 && 2195 dri2_dpy->tex_buffer->releaseTexBuffer != NULL) { 2196 dri2_dpy->tex_buffer->releaseTexBuffer(dri2_ctx->dri_context, 2197 target, dri_drawable); 2198 } 2199 2200 return EGL_TRUE; 2201} 2202 2203static _EGLImage* 2204dri2_create_image(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 2205 EGLClientBuffer buffer, const EGLint *attr_list) 2206{ 2207 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2208 return dri2_dpy->vtbl->create_image(disp, ctx, target, buffer, 2209 attr_list); 2210} 2211 2212_EGLImage * 2213dri2_create_image_from_dri(_EGLDisplay *disp, __DRIimage *dri_image) 2214{ 2215 struct dri2_egl_image *dri2_img; 2216 2217 if (dri_image == NULL) { 2218 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 2219 return NULL; 2220 } 2221 2222 dri2_img = malloc(sizeof *dri2_img); 2223 if (!dri2_img) { 2224 _eglError(EGL_BAD_ALLOC, "dri2_create_image"); 2225 return NULL; 2226 } 2227 2228 _eglInitImage(&dri2_img->base, disp); 2229 2230 dri2_img->dri_image = dri_image; 2231 2232 return &dri2_img->base; 2233} 2234 2235/** 2236 * Translate a DRI Image extension error code into an EGL error code. 2237 */ 2238static EGLint 2239egl_error_from_dri_image_error(int dri_error) 2240{ 2241 switch (dri_error) { 2242 case __DRI_IMAGE_ERROR_SUCCESS: 2243 return EGL_SUCCESS; 2244 case __DRI_IMAGE_ERROR_BAD_ALLOC: 2245 return EGL_BAD_ALLOC; 2246 case __DRI_IMAGE_ERROR_BAD_MATCH: 2247 return EGL_BAD_MATCH; 2248 case __DRI_IMAGE_ERROR_BAD_PARAMETER: 2249 return EGL_BAD_PARAMETER; 2250 case __DRI_IMAGE_ERROR_BAD_ACCESS: 2251 return EGL_BAD_ACCESS; 2252 default: 2253 assert(!"unknown dri_error code"); 2254 return EGL_BAD_ALLOC; 2255 } 2256} 2257 2258static _EGLImage * 2259dri2_create_image_khr_renderbuffer(_EGLDisplay *disp, _EGLContext *ctx, 2260 EGLClientBuffer buffer, 2261 const EGLint *attr_list) 2262{ 2263 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2264 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 2265 GLuint renderbuffer = (GLuint) (uintptr_t) buffer; 2266 __DRIimage *dri_image; 2267 2268 if (renderbuffer == 0) { 2269 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2270 return EGL_NO_IMAGE_KHR; 2271 } 2272 2273 if (!disp->Extensions.KHR_gl_renderbuffer_image) { 2274 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2275 return EGL_NO_IMAGE_KHR; 2276 } 2277 2278 if (dri2_dpy->image->base.version >= 17 && 2279 dri2_dpy->image->createImageFromRenderbuffer2) { 2280 unsigned error = ~0; 2281 2282 dri_image = dri2_dpy->image->createImageFromRenderbuffer2( 2283 dri2_ctx->dri_context, renderbuffer, NULL, &error); 2284 2285 assert(!!dri_image == (error == __DRI_IMAGE_ERROR_SUCCESS)); 2286 2287 if (!dri_image) { 2288 _eglError(egl_error_from_dri_image_error(error), "dri2_create_image_khr"); 2289 return EGL_NO_IMAGE_KHR; 2290 } 2291 } else { 2292 dri_image = dri2_dpy->image->createImageFromRenderbuffer( 2293 dri2_ctx->dri_context, renderbuffer, NULL); 2294 if (!dri_image) { 2295 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2296 return EGL_NO_IMAGE_KHR; 2297 } 2298 } 2299 2300 return dri2_create_image_from_dri(disp, dri_image); 2301} 2302 2303#ifdef HAVE_WAYLAND_PLATFORM 2304 2305/* This structure describes how a wl_buffer maps to one or more 2306 * __DRIimages. A wl_drm_buffer stores the wl_drm format code and the 2307 * offsets and strides of the planes in the buffer. This table maps a 2308 * wl_drm format code to a description of the planes in the buffer 2309 * that lets us create a __DRIimage for each of the planes. */ 2310 2311static const struct wl_drm_components_descriptor { 2312 uint32_t dri_components; 2313 EGLint components; 2314 int nplanes; 2315} wl_drm_components[] = { 2316 { __DRI_IMAGE_COMPONENTS_RGB, EGL_TEXTURE_RGB, 1 }, 2317 { __DRI_IMAGE_COMPONENTS_RGBA, EGL_TEXTURE_RGBA, 1 }, 2318 { __DRI_IMAGE_COMPONENTS_Y_U_V, EGL_TEXTURE_Y_U_V_WL, 3 }, 2319 { __DRI_IMAGE_COMPONENTS_Y_UV, EGL_TEXTURE_Y_UV_WL, 2 }, 2320 { __DRI_IMAGE_COMPONENTS_Y_XUXV, EGL_TEXTURE_Y_XUXV_WL, 2 }, 2321}; 2322 2323static _EGLImage * 2324dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx, 2325 EGLClientBuffer _buffer, 2326 const EGLint *attr_list) 2327{ 2328 struct wl_drm_buffer *buffer; 2329 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2330 const struct wl_drm_components_descriptor *f; 2331 __DRIimage *dri_image; 2332 _EGLImageAttribs attrs; 2333 int32_t plane; 2334 2335 buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, 2336 (struct wl_resource *) _buffer); 2337 if (!buffer) 2338 return NULL; 2339 2340 if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2341 return NULL; 2342 2343 plane = attrs.PlaneWL; 2344 f = buffer->driver_format; 2345 if (plane < 0 || plane >= f->nplanes) { 2346 _eglError(EGL_BAD_PARAMETER, 2347 "dri2_create_image_wayland_wl_buffer (plane out of bounds)"); 2348 return NULL; 2349 } 2350 2351 dri_image = dri2_dpy->image->fromPlanar(buffer->driver_buffer, plane, NULL); 2352 if (dri_image == NULL && plane == 0) 2353 dri_image = dri2_dpy->image->dupImage(buffer->driver_buffer, NULL); 2354 if (dri_image == NULL) { 2355 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_wayland_wl_buffer"); 2356 return NULL; 2357 } 2358 2359 return dri2_create_image_from_dri(disp, dri_image); 2360} 2361#endif 2362 2363static EGLBoolean 2364dri2_get_sync_values_chromium(_EGLDisplay *disp, _EGLSurface *surf, 2365 EGLuint64KHR *ust, EGLuint64KHR *msc, 2366 EGLuint64KHR *sbc) 2367{ 2368 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2369 if (!dri2_dpy->vtbl->get_sync_values) 2370 return EGL_FALSE; 2371 return dri2_dpy->vtbl->get_sync_values(disp, surf, ust, msc, sbc); 2372} 2373 2374/** 2375 * Set the error code after a call to 2376 * dri2_egl_image::dri_image::createImageFromTexture. 2377 */ 2378static void 2379dri2_create_image_khr_texture_error(int dri_error) 2380{ 2381 EGLint egl_error = egl_error_from_dri_image_error(dri_error); 2382 2383 if (egl_error != EGL_SUCCESS) 2384 _eglError(egl_error, "dri2_create_image_khr_texture"); 2385} 2386 2387static _EGLImage * 2388dri2_create_image_khr_texture(_EGLDisplay *disp, _EGLContext *ctx, 2389 EGLenum target, 2390 EGLClientBuffer buffer, 2391 const EGLint *attr_list) 2392{ 2393 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2394 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 2395 struct dri2_egl_image *dri2_img; 2396 GLuint texture = (GLuint) (uintptr_t) buffer; 2397 _EGLImageAttribs attrs; 2398 GLuint depth; 2399 GLenum gl_target; 2400 unsigned error; 2401 2402 if (texture == 0) { 2403 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2404 return EGL_NO_IMAGE_KHR; 2405 } 2406 2407 if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2408 return EGL_NO_IMAGE_KHR; 2409 2410 switch (target) { 2411 case EGL_GL_TEXTURE_2D_KHR: 2412 if (!disp->Extensions.KHR_gl_texture_2D_image) { 2413 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2414 return EGL_NO_IMAGE_KHR; 2415 } 2416 depth = 0; 2417 gl_target = GL_TEXTURE_2D; 2418 break; 2419 case EGL_GL_TEXTURE_3D_KHR: 2420 if (!disp->Extensions.KHR_gl_texture_3D_image) { 2421 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2422 return EGL_NO_IMAGE_KHR; 2423 } 2424 2425 depth = attrs.GLTextureZOffset; 2426 gl_target = GL_TEXTURE_3D; 2427 break; 2428 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 2429 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 2430 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 2431 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 2432 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 2433 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 2434 if (!disp->Extensions.KHR_gl_texture_cubemap_image) { 2435 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 2436 return EGL_NO_IMAGE_KHR; 2437 } 2438 2439 depth = target - EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR; 2440 gl_target = GL_TEXTURE_CUBE_MAP; 2441 break; 2442 default: 2443 unreachable("Unexpected target in dri2_create_image_khr_texture()"); 2444 return EGL_NO_IMAGE_KHR; 2445 } 2446 2447 dri2_img = malloc(sizeof *dri2_img); 2448 if (!dri2_img) { 2449 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2450 return EGL_NO_IMAGE_KHR; 2451 } 2452 2453 _eglInitImage(&dri2_img->base, disp); 2454 2455 dri2_img->dri_image = 2456 dri2_dpy->image->createImageFromTexture(dri2_ctx->dri_context, 2457 gl_target, 2458 texture, 2459 depth, 2460 attrs.GLTextureLevel, 2461 &error, 2462 NULL); 2463 dri2_create_image_khr_texture_error(error); 2464 2465 if (!dri2_img->dri_image) { 2466 free(dri2_img); 2467 return EGL_NO_IMAGE_KHR; 2468 } 2469 return &dri2_img->base; 2470} 2471 2472static EGLBoolean 2473dri2_query_surface(_EGLDisplay *disp, _EGLSurface *surf, 2474 EGLint attribute, EGLint *value) 2475{ 2476 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2477 if (!dri2_dpy->vtbl->query_surface) 2478 return _eglQuerySurface(disp, surf, attribute, value); 2479 return dri2_dpy->vtbl->query_surface(disp, surf, attribute, value); 2480} 2481 2482static struct wl_buffer* 2483dri2_create_wayland_buffer_from_image(_EGLDisplay *disp, _EGLImage *img) 2484{ 2485 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2486 if (!dri2_dpy->vtbl->create_wayland_buffer_from_image) 2487 return NULL; 2488 return dri2_dpy->vtbl->create_wayland_buffer_from_image(disp, img); 2489} 2490 2491#ifdef HAVE_LIBDRM 2492static _EGLImage * 2493dri2_create_image_mesa_drm_buffer(_EGLDisplay *disp, _EGLContext *ctx, 2494 EGLClientBuffer buffer, const EGLint *attr_list) 2495{ 2496 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2497 EGLint format, name, pitch; 2498 _EGLImageAttribs attrs; 2499 __DRIimage *dri_image; 2500 2501 name = (EGLint) (uintptr_t) buffer; 2502 2503 if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2504 return NULL; 2505 2506 if (attrs.Width <= 0 || attrs.Height <= 0 || 2507 attrs.DRMBufferStrideMESA <= 0) { 2508 _eglError(EGL_BAD_PARAMETER, 2509 "bad width, height or stride"); 2510 return NULL; 2511 } 2512 2513 switch (attrs.DRMBufferFormatMESA) { 2514 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 2515 format = __DRI_IMAGE_FORMAT_ARGB8888; 2516 pitch = attrs.DRMBufferStrideMESA; 2517 break; 2518 default: 2519 _eglError(EGL_BAD_PARAMETER, 2520 "dri2_create_image_khr: unsupported pixmap depth"); 2521 return NULL; 2522 } 2523 2524 dri_image = 2525 dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen, 2526 attrs.Width, 2527 attrs.Height, 2528 format, 2529 name, 2530 pitch, 2531 NULL); 2532 2533 return dri2_create_image_from_dri(disp, dri_image); 2534} 2535 2536static EGLBoolean 2537dri2_check_dma_buf_attribs(const _EGLImageAttribs *attrs) 2538{ 2539 /** 2540 * The spec says: 2541 * 2542 * "Required attributes and their values are as follows: 2543 * 2544 * * EGL_WIDTH & EGL_HEIGHT: The logical dimensions of the buffer in pixels 2545 * 2546 * * EGL_LINUX_DRM_FOURCC_EXT: The pixel format of the buffer, as specified 2547 * by drm_fourcc.h and used as the pixel_format parameter of the 2548 * drm_mode_fb_cmd2 ioctl." 2549 * 2550 * and 2551 * 2552 * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 2553 * incomplete, EGL_BAD_PARAMETER is generated." 2554 */ 2555 if (attrs->Width <= 0 || attrs->Height <= 0 || 2556 !attrs->DMABufFourCC.IsPresent) 2557 return _eglError(EGL_BAD_PARAMETER, "attribute(s) missing"); 2558 2559 /** 2560 * Also: 2561 * 2562 * "If <target> is EGL_LINUX_DMA_BUF_EXT and one or more of the values 2563 * specified for a plane's pitch or offset isn't supported by EGL, 2564 * EGL_BAD_ACCESS is generated." 2565 */ 2566 for (unsigned i = 0; i < ARRAY_SIZE(attrs->DMABufPlanePitches); ++i) { 2567 if (attrs->DMABufPlanePitches[i].IsPresent && 2568 attrs->DMABufPlanePitches[i].Value <= 0) 2569 return _eglError(EGL_BAD_ACCESS, "invalid pitch"); 2570 } 2571 2572 /** 2573 * If <target> is EGL_LINUX_DMA_BUF_EXT, both or neither of the following 2574 * attribute values may be given. 2575 * 2576 * This is referring to EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT and 2577 * EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, and the same for other planes. 2578 */ 2579 for (unsigned i = 0; i < DMA_BUF_MAX_PLANES; ++i) { 2580 if (attrs->DMABufPlaneModifiersLo[i].IsPresent != 2581 attrs->DMABufPlaneModifiersHi[i].IsPresent) 2582 return _eglError(EGL_BAD_PARAMETER, "modifier attribute lo or hi missing"); 2583 } 2584 2585 /* Although the EGL_EXT_image_dma_buf_import_modifiers spec doesn't 2586 * mandate it, we only accept the same modifier across all planes. */ 2587 for (unsigned i = 1; i < DMA_BUF_MAX_PLANES; ++i) { 2588 if (attrs->DMABufPlaneFds[i].IsPresent) { 2589 if ((attrs->DMABufPlaneModifiersLo[0].IsPresent != 2590 attrs->DMABufPlaneModifiersLo[i].IsPresent) || 2591 (attrs->DMABufPlaneModifiersLo[0].Value != 2592 attrs->DMABufPlaneModifiersLo[i].Value) || 2593 (attrs->DMABufPlaneModifiersHi[0].Value != 2594 attrs->DMABufPlaneModifiersHi[i].Value)) 2595 return _eglError(EGL_BAD_PARAMETER, "modifier attributes not equal"); 2596 } 2597 } 2598 2599 return EGL_TRUE; 2600} 2601 2602/* Returns the total number of planes for the format or zero if it isn't a 2603 * valid fourcc format. 2604 */ 2605static unsigned 2606dri2_num_fourcc_format_planes(EGLint format) 2607{ 2608 switch (format) { 2609 case DRM_FORMAT_R8: 2610 case DRM_FORMAT_RG88: 2611 case DRM_FORMAT_GR88: 2612 case DRM_FORMAT_R16: 2613 case DRM_FORMAT_GR1616: 2614 case DRM_FORMAT_RGB332: 2615 case DRM_FORMAT_BGR233: 2616 case DRM_FORMAT_XRGB4444: 2617 case DRM_FORMAT_XBGR4444: 2618 case DRM_FORMAT_RGBX4444: 2619 case DRM_FORMAT_BGRX4444: 2620 case DRM_FORMAT_ARGB4444: 2621 case DRM_FORMAT_ABGR4444: 2622 case DRM_FORMAT_RGBA4444: 2623 case DRM_FORMAT_BGRA4444: 2624 case DRM_FORMAT_XRGB1555: 2625 case DRM_FORMAT_XBGR1555: 2626 case DRM_FORMAT_RGBX5551: 2627 case DRM_FORMAT_BGRX5551: 2628 case DRM_FORMAT_ARGB1555: 2629 case DRM_FORMAT_ABGR1555: 2630 case DRM_FORMAT_RGBA5551: 2631 case DRM_FORMAT_BGRA5551: 2632 case DRM_FORMAT_RGB565: 2633 case DRM_FORMAT_BGR565: 2634 case DRM_FORMAT_RGB888: 2635 case DRM_FORMAT_BGR888: 2636 case DRM_FORMAT_XRGB8888: 2637 case DRM_FORMAT_XBGR8888: 2638 case DRM_FORMAT_RGBX8888: 2639 case DRM_FORMAT_BGRX8888: 2640 case DRM_FORMAT_ARGB8888: 2641 case DRM_FORMAT_ABGR8888: 2642 case DRM_FORMAT_RGBA8888: 2643 case DRM_FORMAT_BGRA8888: 2644 case DRM_FORMAT_XRGB2101010: 2645 case DRM_FORMAT_XBGR2101010: 2646 case DRM_FORMAT_RGBX1010102: 2647 case DRM_FORMAT_BGRX1010102: 2648 case DRM_FORMAT_ARGB2101010: 2649 case DRM_FORMAT_ABGR2101010: 2650 case DRM_FORMAT_RGBA1010102: 2651 case DRM_FORMAT_BGRA1010102: 2652 case DRM_FORMAT_XBGR16161616F: 2653 case DRM_FORMAT_ABGR16161616F: 2654 case DRM_FORMAT_YUYV: 2655 case DRM_FORMAT_YVYU: 2656 case DRM_FORMAT_UYVY: 2657 case DRM_FORMAT_VYUY: 2658 case DRM_FORMAT_AYUV: 2659 case DRM_FORMAT_XYUV8888: 2660 case DRM_FORMAT_Y210: 2661 case DRM_FORMAT_Y212: 2662 case DRM_FORMAT_Y216: 2663 case DRM_FORMAT_Y410: 2664 case DRM_FORMAT_Y412: 2665 case DRM_FORMAT_Y416: 2666 return 1; 2667 2668 case DRM_FORMAT_NV12: 2669 case DRM_FORMAT_NV21: 2670 case DRM_FORMAT_NV16: 2671 case DRM_FORMAT_NV61: 2672 case DRM_FORMAT_P010: 2673 case DRM_FORMAT_P012: 2674 case DRM_FORMAT_P016: 2675 return 2; 2676 2677 case DRM_FORMAT_YUV410: 2678 case DRM_FORMAT_YVU410: 2679 case DRM_FORMAT_YUV411: 2680 case DRM_FORMAT_YVU411: 2681 case DRM_FORMAT_YUV420: 2682 case DRM_FORMAT_YVU420: 2683 case DRM_FORMAT_YUV422: 2684 case DRM_FORMAT_YVU422: 2685 case DRM_FORMAT_YUV444: 2686 case DRM_FORMAT_YVU444: 2687 return 3; 2688 2689 default: 2690 return 0; 2691 } 2692} 2693 2694/* Returns the total number of file descriptors. Zero indicates an error. */ 2695static unsigned 2696dri2_check_dma_buf_format(const _EGLImageAttribs *attrs) 2697{ 2698 unsigned plane_n = dri2_num_fourcc_format_planes(attrs->DMABufFourCC.Value); 2699 if (plane_n == 0) { 2700 _eglError(EGL_BAD_MATCH, "unknown drm fourcc format"); 2701 return 0; 2702 } 2703 2704 for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; i++) { 2705 /** 2706 * The modifiers extension spec says: 2707 * 2708 * "Modifiers may modify any attribute of a buffer import, including 2709 * but not limited to adding extra planes to a format which 2710 * otherwise does not have those planes. As an example, a modifier 2711 * may add a plane for an external compression buffer to a 2712 * single-plane format. The exact meaning and effect of any 2713 * modifier is canonically defined by drm_fourcc.h, not as part of 2714 * this extension." 2715 */ 2716 if (attrs->DMABufPlaneModifiersLo[i].IsPresent && 2717 attrs->DMABufPlaneModifiersHi[i].IsPresent) { 2718 plane_n = i + 1; 2719 } 2720 } 2721 2722 /** 2723 * The spec says: 2724 * 2725 * "* If <target> is EGL_LINUX_DMA_BUF_EXT, and the list of attributes is 2726 * incomplete, EGL_BAD_PARAMETER is generated." 2727 */ 2728 for (unsigned i = 0; i < plane_n; ++i) { 2729 if (!attrs->DMABufPlaneFds[i].IsPresent || 2730 !attrs->DMABufPlaneOffsets[i].IsPresent || 2731 !attrs->DMABufPlanePitches[i].IsPresent) { 2732 _eglError(EGL_BAD_PARAMETER, "plane attribute(s) missing"); 2733 return 0; 2734 } 2735 } 2736 2737 /** 2738 * The spec also says: 2739 * 2740 * "If <target> is EGL_LINUX_DMA_BUF_EXT, and the EGL_LINUX_DRM_FOURCC_EXT 2741 * attribute indicates a single-plane format, EGL_BAD_ATTRIBUTE is 2742 * generated if any of the EGL_DMA_BUF_PLANE1_* or EGL_DMA_BUF_PLANE2_* 2743 * or EGL_DMA_BUF_PLANE3_* attributes are specified." 2744 */ 2745 for (unsigned i = plane_n; i < DMA_BUF_MAX_PLANES; ++i) { 2746 if (attrs->DMABufPlaneFds[i].IsPresent || 2747 attrs->DMABufPlaneOffsets[i].IsPresent || 2748 attrs->DMABufPlanePitches[i].IsPresent) { 2749 _eglError(EGL_BAD_ATTRIBUTE, "too many plane attributes"); 2750 return 0; 2751 } 2752 } 2753 2754 return plane_n; 2755} 2756 2757static EGLBoolean 2758dri2_query_dma_buf_formats(_EGLDisplay *disp, EGLint max, 2759 EGLint *formats, EGLint *count) 2760{ 2761 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2762 if (max < 0 || (max > 0 && formats == NULL)) 2763 return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats"); 2764 2765 if (dri2_dpy->image->base.version < 15 || 2766 dri2_dpy->image->queryDmaBufFormats == NULL) 2767 return EGL_FALSE; 2768 2769 if (!dri2_dpy->image->queryDmaBufFormats(dri2_dpy->dri_screen, max, 2770 formats, count)) 2771 return EGL_FALSE; 2772 2773 if (max > 0) { 2774 /* Assert that all of the formats returned are actually fourcc formats. 2775 * Some day, if we want the internal interface function to be able to 2776 * return the fake fourcc formats defined in dri_interface.h, we'll have 2777 * to do something more clever here to pair the list down to just real 2778 * fourcc formats so that we don't leak the fake internal ones. 2779 */ 2780 for (int i = 0; i < *count; i++) { 2781 assert(dri2_num_fourcc_format_planes(formats[i]) > 0); 2782 } 2783 } 2784 2785 return EGL_TRUE; 2786} 2787 2788static EGLBoolean 2789dri2_query_dma_buf_modifiers(_EGLDisplay *disp, EGLint format, 2790 EGLint max, EGLuint64KHR *modifiers, 2791 EGLBoolean *external_only, EGLint *count) 2792{ 2793 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2794 2795 if (dri2_num_fourcc_format_planes(format) == 0) 2796 return _eglError(EGL_BAD_PARAMETER, "invalid fourcc format"); 2797 2798 if (max < 0) 2799 return _eglError(EGL_BAD_PARAMETER, "invalid value for max count of formats"); 2800 2801 if (max > 0 && modifiers == NULL) 2802 return _eglError(EGL_BAD_PARAMETER, "invalid modifiers array"); 2803 2804 if (dri2_dpy->image->base.version < 15 || 2805 dri2_dpy->image->queryDmaBufModifiers == NULL) 2806 return EGL_FALSE; 2807 2808 if (dri2_dpy->image->queryDmaBufModifiers(dri2_dpy->dri_screen, format, 2809 max, modifiers, 2810 (unsigned int *) external_only, 2811 count) == false) 2812 return _eglError(EGL_BAD_PARAMETER, "invalid format"); 2813 2814 return EGL_TRUE; 2815} 2816 2817/** 2818 * The spec says: 2819 * 2820 * "If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT target, the 2821 * EGL will take a reference to the dma_buf(s) which it will release at any 2822 * time while the EGLDisplay is initialized. It is the responsibility of the 2823 * application to close the dma_buf file descriptors." 2824 * 2825 * Therefore we must never close or otherwise modify the file descriptors. 2826 */ 2827_EGLImage * 2828dri2_create_image_dma_buf(_EGLDisplay *disp, _EGLContext *ctx, 2829 EGLClientBuffer buffer, const EGLint *attr_list) 2830{ 2831 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2832 _EGLImage *res; 2833 _EGLImageAttribs attrs; 2834 __DRIimage *dri_image; 2835 unsigned num_fds; 2836 int fds[DMA_BUF_MAX_PLANES]; 2837 int pitches[DMA_BUF_MAX_PLANES]; 2838 int offsets[DMA_BUF_MAX_PLANES]; 2839 uint64_t modifier; 2840 bool has_modifier = false; 2841 unsigned error; 2842 2843 /** 2844 * The spec says: 2845 * 2846 * ""* If <target> is EGL_LINUX_DMA_BUF_EXT and <buffer> is not NULL, the 2847 * error EGL_BAD_PARAMETER is generated." 2848 */ 2849 if (buffer != NULL) { 2850 _eglError(EGL_BAD_PARAMETER, "buffer not NULL"); 2851 return NULL; 2852 } 2853 2854 if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2855 return NULL; 2856 2857 if (!dri2_check_dma_buf_attribs(&attrs)) 2858 return NULL; 2859 2860 num_fds = dri2_check_dma_buf_format(&attrs); 2861 if (!num_fds) 2862 return NULL; 2863 2864 for (unsigned i = 0; i < num_fds; ++i) { 2865 fds[i] = attrs.DMABufPlaneFds[i].Value; 2866 pitches[i] = attrs.DMABufPlanePitches[i].Value; 2867 offsets[i] = attrs.DMABufPlaneOffsets[i].Value; 2868 } 2869 2870 /* dri2_check_dma_buf_attribs ensures that the modifier, if available, 2871 * will be present in attrs.DMABufPlaneModifiersLo[0] and 2872 * attrs.DMABufPlaneModifiersHi[0] */ 2873 if (attrs.DMABufPlaneModifiersLo[0].IsPresent) { 2874 modifier = combine_u32_into_u64(attrs.DMABufPlaneModifiersHi[0].Value, 2875 attrs.DMABufPlaneModifiersLo[0].Value); 2876 has_modifier = true; 2877 } 2878 2879 if (attrs.ProtectedContent) { 2880 if (dri2_dpy->image->base.version < 18 || 2881 dri2_dpy->image->createImageFromDmaBufs3 == NULL) { 2882 _eglError(EGL_BAD_MATCH, "unsupported protected_content attribute"); 2883 return EGL_NO_IMAGE_KHR; 2884 } 2885 if (!has_modifier) 2886 modifier = DRM_FORMAT_MOD_INVALID; 2887 2888 dri_image = 2889 dri2_dpy->image->createImageFromDmaBufs3(dri2_dpy->dri_screen, 2890 attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 2891 modifier, fds, num_fds, pitches, offsets, 2892 attrs.DMABufYuvColorSpaceHint.Value, 2893 attrs.DMABufSampleRangeHint.Value, 2894 attrs.DMABufChromaHorizontalSiting.Value, 2895 attrs.DMABufChromaVerticalSiting.Value, 2896 attrs.ProtectedContent ? __DRI_IMAGE_PROTECTED_CONTENT_FLAG : 0, 2897 &error, 2898 NULL); 2899 } 2900 else if (has_modifier) { 2901 if (dri2_dpy->image->base.version < 15 || 2902 dri2_dpy->image->createImageFromDmaBufs2 == NULL) { 2903 _eglError(EGL_BAD_MATCH, "unsupported dma_buf format modifier"); 2904 return EGL_NO_IMAGE_KHR; 2905 } 2906 dri_image = 2907 dri2_dpy->image->createImageFromDmaBufs2(dri2_dpy->dri_screen, 2908 attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 2909 modifier, fds, num_fds, pitches, offsets, 2910 attrs.DMABufYuvColorSpaceHint.Value, 2911 attrs.DMABufSampleRangeHint.Value, 2912 attrs.DMABufChromaHorizontalSiting.Value, 2913 attrs.DMABufChromaVerticalSiting.Value, 2914 &error, 2915 NULL); 2916 } 2917 else { 2918 dri_image = 2919 dri2_dpy->image->createImageFromDmaBufs(dri2_dpy->dri_screen, 2920 attrs.Width, attrs.Height, attrs.DMABufFourCC.Value, 2921 fds, num_fds, pitches, offsets, 2922 attrs.DMABufYuvColorSpaceHint.Value, 2923 attrs.DMABufSampleRangeHint.Value, 2924 attrs.DMABufChromaHorizontalSiting.Value, 2925 attrs.DMABufChromaVerticalSiting.Value, 2926 &error, 2927 NULL); 2928 } 2929 dri2_create_image_khr_texture_error(error); 2930 2931 if (!dri_image) 2932 return EGL_NO_IMAGE_KHR; 2933 2934 res = dri2_create_image_from_dri(disp, dri_image); 2935 2936 return res; 2937} 2938static _EGLImage * 2939dri2_create_drm_image_mesa(_EGLDisplay *disp, const EGLint *attr_list) 2940{ 2941 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 2942 struct dri2_egl_image *dri2_img; 2943 _EGLImageAttribs attrs; 2944 unsigned int dri_use, valid_mask; 2945 int format; 2946 2947 if (!attr_list) { 2948 _eglError(EGL_BAD_PARAMETER, __func__); 2949 return EGL_NO_IMAGE_KHR; 2950 } 2951 2952 if (!_eglParseImageAttribList(&attrs, disp, attr_list)) 2953 return EGL_NO_IMAGE_KHR; 2954 2955 if (attrs.Width <= 0 || attrs.Height <= 0) { 2956 _eglError(EGL_BAD_PARAMETER, __func__); 2957 return EGL_NO_IMAGE_KHR; 2958 } 2959 2960 switch (attrs.DRMBufferFormatMESA) { 2961 case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: 2962 format = __DRI_IMAGE_FORMAT_ARGB8888; 2963 break; 2964 default: 2965 _eglError(EGL_BAD_PARAMETER, __func__); 2966 return EGL_NO_IMAGE_KHR; 2967 } 2968 2969 valid_mask = 2970 EGL_DRM_BUFFER_USE_SCANOUT_MESA | 2971 EGL_DRM_BUFFER_USE_SHARE_MESA | 2972 EGL_DRM_BUFFER_USE_CURSOR_MESA; 2973 if (attrs.DRMBufferUseMESA & ~valid_mask) { 2974 _eglError(EGL_BAD_PARAMETER, __func__); 2975 return EGL_NO_IMAGE_KHR; 2976 } 2977 2978 dri_use = 0; 2979 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SHARE_MESA) 2980 dri_use |= __DRI_IMAGE_USE_SHARE; 2981 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_SCANOUT_MESA) 2982 dri_use |= __DRI_IMAGE_USE_SCANOUT; 2983 if (attrs.DRMBufferUseMESA & EGL_DRM_BUFFER_USE_CURSOR_MESA) 2984 dri_use |= __DRI_IMAGE_USE_CURSOR; 2985 2986 dri2_img = malloc(sizeof *dri2_img); 2987 if (!dri2_img) { 2988 _eglError(EGL_BAD_ALLOC, "dri2_create_image_khr"); 2989 return EGL_NO_IMAGE_KHR; 2990 } 2991 2992 _eglInitImage(&dri2_img->base, disp); 2993 2994 dri2_img->dri_image = 2995 dri2_dpy->image->createImage(dri2_dpy->dri_screen, 2996 attrs.Width, attrs.Height, 2997 format, dri_use, dri2_img); 2998 if (dri2_img->dri_image == NULL) { 2999 free(dri2_img); 3000 _eglError(EGL_BAD_ALLOC, "dri2_create_drm_image_mesa"); 3001 return EGL_NO_IMAGE_KHR; 3002 } 3003 3004 return &dri2_img->base; 3005} 3006 3007static EGLBoolean 3008dri2_export_drm_image_mesa(_EGLDisplay *disp, _EGLImage *img, 3009 EGLint *name, EGLint *handle, EGLint *stride) 3010{ 3011 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3012 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 3013 3014 if (name && !dri2_dpy->image->queryImage(dri2_img->dri_image, 3015 __DRI_IMAGE_ATTRIB_NAME, name)) 3016 return _eglError(EGL_BAD_ALLOC, "dri2_export_drm_image_mesa"); 3017 3018 if (handle) 3019 dri2_dpy->image->queryImage(dri2_img->dri_image, 3020 __DRI_IMAGE_ATTRIB_HANDLE, handle); 3021 3022 if (stride) 3023 dri2_dpy->image->queryImage(dri2_img->dri_image, 3024 __DRI_IMAGE_ATTRIB_STRIDE, stride); 3025 3026 return EGL_TRUE; 3027} 3028 3029/** 3030 * Checks if we can support EGL_MESA_image_dma_buf_export on this image. 3031 3032 * The spec provides a boolean return for the driver to reject exporting for 3033 * basically any reason, but doesn't specify any particular error cases. For 3034 * now, we just fail if we don't have a DRM fourcc for the format. 3035 */ 3036static bool 3037dri2_can_export_dma_buf_image(_EGLDisplay *disp, _EGLImage *img) 3038{ 3039 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3040 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 3041 EGLint fourcc; 3042 3043 if (!dri2_dpy->image->queryImage(dri2_img->dri_image, 3044 __DRI_IMAGE_ATTRIB_FOURCC, &fourcc)) { 3045 return false; 3046 } 3047 3048 return true; 3049} 3050 3051static EGLBoolean 3052dri2_export_dma_buf_image_query_mesa(_EGLDisplay *disp, _EGLImage *img, 3053 EGLint *fourcc, EGLint *nplanes, 3054 EGLuint64KHR *modifiers) 3055{ 3056 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3057 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 3058 int num_planes; 3059 3060 if (!dri2_can_export_dma_buf_image(disp, img)) 3061 return EGL_FALSE; 3062 3063 dri2_dpy->image->queryImage(dri2_img->dri_image, 3064 __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes); 3065 if (nplanes) 3066 *nplanes = num_planes; 3067 3068 if (fourcc) 3069 dri2_dpy->image->queryImage(dri2_img->dri_image, 3070 __DRI_IMAGE_ATTRIB_FOURCC, fourcc); 3071 3072 if (modifiers) { 3073 int mod_hi, mod_lo; 3074 uint64_t modifier = DRM_FORMAT_MOD_INVALID; 3075 bool query; 3076 3077 query = dri2_dpy->image->queryImage(dri2_img->dri_image, 3078 __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, 3079 &mod_hi); 3080 query &= dri2_dpy->image->queryImage(dri2_img->dri_image, 3081 __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, 3082 &mod_lo); 3083 if (query) 3084 modifier = combine_u32_into_u64 (mod_hi, mod_lo); 3085 3086 for (int i = 0; i < num_planes; i++) 3087 modifiers[i] = modifier; 3088 } 3089 3090 return EGL_TRUE; 3091} 3092 3093static EGLBoolean 3094dri2_export_dma_buf_image_mesa(_EGLDisplay *disp, _EGLImage *img, 3095 int *fds, EGLint *strides, EGLint *offsets) 3096{ 3097 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3098 struct dri2_egl_image *dri2_img = dri2_egl_image(img); 3099 EGLint nplanes; 3100 3101 if (!dri2_can_export_dma_buf_image(disp, img)) 3102 return EGL_FALSE; 3103 3104 /* EGL_MESA_image_dma_buf_export spec says: 3105 * "If the number of fds is less than the number of planes, then 3106 * subsequent fd slots should contain -1." 3107 */ 3108 if (fds) { 3109 /* Query nplanes so that we know how big the given array is. */ 3110 dri2_dpy->image->queryImage(dri2_img->dri_image, 3111 __DRI_IMAGE_ATTRIB_NUM_PLANES, &nplanes); 3112 memset(fds, -1, nplanes * sizeof(int)); 3113 } 3114 3115 /* rework later to provide multiple fds/strides/offsets */ 3116 if (fds) 3117 dri2_dpy->image->queryImage(dri2_img->dri_image, 3118 __DRI_IMAGE_ATTRIB_FD, fds); 3119 3120 if (strides) 3121 dri2_dpy->image->queryImage(dri2_img->dri_image, 3122 __DRI_IMAGE_ATTRIB_STRIDE, strides); 3123 3124 if (offsets) { 3125 int img_offset; 3126 bool ret = dri2_dpy->image->queryImage(dri2_img->dri_image, 3127 __DRI_IMAGE_ATTRIB_OFFSET, &img_offset); 3128 if (ret) 3129 offsets[0] = img_offset; 3130 else 3131 offsets[0] = 0; 3132 } 3133 3134 return EGL_TRUE; 3135} 3136 3137#endif 3138 3139_EGLImage * 3140dri2_create_image_khr(_EGLDisplay *disp, _EGLContext *ctx, EGLenum target, 3141 EGLClientBuffer buffer, const EGLint *attr_list) 3142{ 3143 switch (target) { 3144 case EGL_GL_TEXTURE_2D_KHR: 3145 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: 3146 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: 3147 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: 3148 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: 3149 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: 3150 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: 3151 case EGL_GL_TEXTURE_3D_KHR: 3152 return dri2_create_image_khr_texture(disp, ctx, target, buffer, attr_list); 3153 case EGL_GL_RENDERBUFFER_KHR: 3154 return dri2_create_image_khr_renderbuffer(disp, ctx, buffer, attr_list); 3155#ifdef HAVE_LIBDRM 3156 case EGL_DRM_BUFFER_MESA: 3157 return dri2_create_image_mesa_drm_buffer(disp, ctx, buffer, attr_list); 3158 case EGL_LINUX_DMA_BUF_EXT: 3159 return dri2_create_image_dma_buf(disp, ctx, buffer, attr_list); 3160#endif 3161#ifdef HAVE_WAYLAND_PLATFORM 3162 case EGL_WAYLAND_BUFFER_WL: 3163 return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list); 3164#endif 3165 default: 3166 _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr"); 3167 return EGL_NO_IMAGE_KHR; 3168 } 3169} 3170 3171static EGLBoolean 3172dri2_destroy_image_khr(_EGLDisplay *disp, _EGLImage *image) 3173{ 3174 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3175 struct dri2_egl_image *dri2_img = dri2_egl_image(image); 3176 3177 dri2_dpy->image->destroyImage(dri2_img->dri_image); 3178 free(dri2_img); 3179 3180 return EGL_TRUE; 3181} 3182 3183#ifdef HAVE_WAYLAND_PLATFORM 3184 3185static void 3186dri2_wl_reference_buffer(void *user_data, uint32_t name, int fd, 3187 struct wl_drm_buffer *buffer) 3188{ 3189 _EGLDisplay *disp = user_data; 3190 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3191 __DRIimage *img; 3192 int dri_components = 0; 3193 3194 if (fd == -1) 3195 img = dri2_dpy->image->createImageFromNames(dri2_dpy->dri_screen, 3196 buffer->width, 3197 buffer->height, 3198 buffer->format, 3199 (int*)&name, 1, 3200 buffer->stride, 3201 buffer->offset, 3202 NULL); 3203 else 3204 img = dri2_dpy->image->createImageFromFds(dri2_dpy->dri_screen, 3205 buffer->width, 3206 buffer->height, 3207 buffer->format, 3208 &fd, 1, 3209 buffer->stride, 3210 buffer->offset, 3211 NULL); 3212 3213 if (img == NULL) 3214 return; 3215 3216 dri2_dpy->image->queryImage(img, __DRI_IMAGE_ATTRIB_COMPONENTS, &dri_components); 3217 3218 buffer->driver_format = NULL; 3219 for (int i = 0; i < ARRAY_SIZE(wl_drm_components); i++) 3220 if (wl_drm_components[i].dri_components == dri_components) 3221 buffer->driver_format = &wl_drm_components[i]; 3222 3223 if (buffer->driver_format == NULL) 3224 dri2_dpy->image->destroyImage(img); 3225 else 3226 buffer->driver_buffer = img; 3227} 3228 3229static void 3230dri2_wl_release_buffer(void *user_data, struct wl_drm_buffer *buffer) 3231{ 3232 _EGLDisplay *disp = user_data; 3233 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3234 3235 dri2_dpy->image->destroyImage(buffer->driver_buffer); 3236} 3237 3238static EGLBoolean 3239dri2_bind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy) 3240{ 3241 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3242 const struct wayland_drm_callbacks wl_drm_callbacks = { 3243 .authenticate = (int(*)(void *, uint32_t)) dri2_dpy->vtbl->authenticate, 3244 .reference_buffer = dri2_wl_reference_buffer, 3245 .release_buffer = dri2_wl_release_buffer, 3246 .is_format_supported = dri2_wl_is_format_supported 3247 }; 3248 int flags = 0; 3249 char *device_name; 3250 uint64_t cap; 3251 3252 if (dri2_dpy->wl_server_drm) 3253 return EGL_FALSE; 3254 3255 device_name = drmGetRenderDeviceNameFromFd(dri2_dpy->fd); 3256 if (!device_name) 3257 device_name = strdup(dri2_dpy->device_name); 3258 if (!device_name) 3259 return EGL_FALSE; 3260 3261 if (drmGetCap(dri2_dpy->fd, DRM_CAP_PRIME, &cap) == 0 && 3262 cap == (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT) && 3263 dri2_dpy->image->base.version >= 7 && 3264 dri2_dpy->image->createImageFromFds != NULL) 3265 flags |= WAYLAND_DRM_PRIME; 3266 3267 dri2_dpy->wl_server_drm = 3268 wayland_drm_init(wl_dpy, device_name, 3269 &wl_drm_callbacks, disp, flags); 3270 3271 free(device_name); 3272 3273 if (!dri2_dpy->wl_server_drm) 3274 return EGL_FALSE; 3275 3276#ifdef HAVE_DRM_PLATFORM 3277 /* We have to share the wl_drm instance with gbm, so gbm can convert 3278 * wl_buffers to gbm bos. */ 3279 if (dri2_dpy->gbm_dri) 3280 dri2_dpy->gbm_dri->wl_drm = dri2_dpy->wl_server_drm; 3281#endif 3282 3283 return EGL_TRUE; 3284} 3285 3286static EGLBoolean 3287dri2_unbind_wayland_display_wl(_EGLDisplay *disp, struct wl_display *wl_dpy) 3288{ 3289 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3290 3291 if (!dri2_dpy->wl_server_drm) 3292 return EGL_FALSE; 3293 3294 wayland_drm_uninit(dri2_dpy->wl_server_drm); 3295 dri2_dpy->wl_server_drm = NULL; 3296 3297 return EGL_TRUE; 3298} 3299 3300static EGLBoolean 3301dri2_query_wayland_buffer_wl(_EGLDisplay *disp, struct wl_resource *buffer_resource, 3302 EGLint attribute, EGLint *value) 3303{ 3304 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3305 struct wl_drm_buffer *buffer; 3306 const struct wl_drm_components_descriptor *format; 3307 3308 buffer = wayland_drm_buffer_get(dri2_dpy->wl_server_drm, buffer_resource); 3309 if (!buffer) 3310 return EGL_FALSE; 3311 3312 format = buffer->driver_format; 3313 switch (attribute) { 3314 case EGL_TEXTURE_FORMAT: 3315 *value = format->components; 3316 return EGL_TRUE; 3317 case EGL_WIDTH: 3318 *value = buffer->width; 3319 return EGL_TRUE; 3320 case EGL_HEIGHT: 3321 *value = buffer->height; 3322 return EGL_TRUE; 3323 } 3324 3325 return EGL_FALSE; 3326} 3327#endif 3328 3329static void 3330dri2_egl_ref_sync(struct dri2_egl_sync *sync) 3331{ 3332 p_atomic_inc(&sync->refcount); 3333} 3334 3335static void 3336dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy, 3337 struct dri2_egl_sync *dri2_sync) 3338{ 3339 if (p_atomic_dec_zero(&dri2_sync->refcount)) { 3340 switch (dri2_sync->base.Type) { 3341 case EGL_SYNC_REUSABLE_KHR: 3342 cnd_destroy(&dri2_sync->cond); 3343 break; 3344 case EGL_SYNC_NATIVE_FENCE_ANDROID: 3345 if (dri2_sync->base.SyncFd != EGL_NO_NATIVE_FENCE_FD_ANDROID) 3346 close(dri2_sync->base.SyncFd); 3347 break; 3348 default: 3349 break; 3350 } 3351 3352 if (dri2_sync->fence) 3353 dri2_dpy->fence->destroy_fence(dri2_dpy->dri_screen, dri2_sync->fence); 3354 3355 free(dri2_sync); 3356 } 3357} 3358 3359static _EGLSync * 3360dri2_create_sync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list) 3361{ 3362 _EGLContext *ctx = _eglGetCurrentContext(); 3363 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3364 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3365 struct dri2_egl_sync *dri2_sync; 3366 EGLint ret; 3367 pthread_condattr_t attr; 3368 3369 dri2_sync = calloc(1, sizeof(struct dri2_egl_sync)); 3370 if (!dri2_sync) { 3371 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 3372 return NULL; 3373 } 3374 3375 if (!_eglInitSync(&dri2_sync->base, disp, type, attrib_list)) { 3376 free(dri2_sync); 3377 return NULL; 3378 } 3379 3380 switch (type) { 3381 case EGL_SYNC_FENCE_KHR: 3382 dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context); 3383 if (!dri2_sync->fence) { 3384 /* Why did it fail? DRI doesn't return an error code, so we emit 3385 * a generic EGL error that doesn't communicate user error. 3386 */ 3387 _eglError(EGL_BAD_ALLOC, "eglCreateSyncKHR"); 3388 free(dri2_sync); 3389 return NULL; 3390 } 3391 break; 3392 3393 case EGL_SYNC_CL_EVENT_KHR: 3394 dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event( 3395 dri2_dpy->dri_screen, 3396 dri2_sync->base.CLEvent); 3397 /* this can only happen if the cl_event passed in is invalid. */ 3398 if (!dri2_sync->fence) { 3399 _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); 3400 free(dri2_sync); 3401 return NULL; 3402 } 3403 3404 /* the initial status must be "signaled" if the cl_event is signaled */ 3405 if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context, 3406 dri2_sync->fence, 0, 0)) 3407 dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 3408 break; 3409 3410 case EGL_SYNC_REUSABLE_KHR: 3411 /* intialize attr */ 3412 ret = pthread_condattr_init(&attr); 3413 3414 if (ret) { 3415 _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 3416 free(dri2_sync); 3417 return NULL; 3418 } 3419 3420 /* change clock attribute to CLOCK_MONOTONIC */ 3421 ret = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); 3422 3423 if (ret) { 3424 _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 3425 free(dri2_sync); 3426 return NULL; 3427 } 3428 3429 ret = pthread_cond_init(&dri2_sync->cond, &attr); 3430 3431 if (ret) { 3432 _eglError(EGL_BAD_ACCESS, "eglCreateSyncKHR"); 3433 free(dri2_sync); 3434 return NULL; 3435 } 3436 3437 /* initial status of reusable sync must be "unsignaled" */ 3438 dri2_sync->base.SyncStatus = EGL_UNSIGNALED_KHR; 3439 break; 3440 3441 case EGL_SYNC_NATIVE_FENCE_ANDROID: 3442 if (dri2_dpy->fence->create_fence_fd) { 3443 dri2_sync->fence = dri2_dpy->fence->create_fence_fd( 3444 dri2_ctx->dri_context, 3445 dri2_sync->base.SyncFd); 3446 } 3447 if (!dri2_sync->fence) { 3448 _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); 3449 free(dri2_sync); 3450 return NULL; 3451 } 3452 break; 3453 } 3454 3455 p_atomic_set(&dri2_sync->refcount, 1); 3456 return &dri2_sync->base; 3457} 3458 3459static EGLBoolean 3460dri2_destroy_sync(_EGLDisplay *disp, _EGLSync *sync) 3461{ 3462 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3463 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3464 EGLint ret = EGL_TRUE; 3465 EGLint err; 3466 3467 /* if type of sync is EGL_SYNC_REUSABLE_KHR and it is not signaled yet, 3468 * then unlock all threads possibly blocked by the reusable sync before 3469 * destroying it. 3470 */ 3471 if (dri2_sync->base.Type == EGL_SYNC_REUSABLE_KHR && 3472 dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) { 3473 dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 3474 /* unblock all threads currently blocked by sync */ 3475 err = cnd_broadcast(&dri2_sync->cond); 3476 3477 if (err) { 3478 _eglError(EGL_BAD_ACCESS, "eglDestroySyncKHR"); 3479 ret = EGL_FALSE; 3480 } 3481 } 3482 3483 dri2_egl_unref_sync(dri2_dpy, dri2_sync); 3484 3485 return ret; 3486} 3487 3488static EGLint 3489dri2_dup_native_fence_fd(_EGLDisplay *disp, _EGLSync *sync) 3490{ 3491 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3492 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3493 3494 assert(sync->Type == EGL_SYNC_NATIVE_FENCE_ANDROID); 3495 3496 if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 3497 /* try to retrieve the actual native fence fd.. if rendering is 3498 * not flushed this will just return -1, aka NO_NATIVE_FENCE_FD: 3499 */ 3500 sync->SyncFd = dri2_dpy->fence->get_fence_fd(dri2_dpy->dri_screen, 3501 dri2_sync->fence); 3502 } 3503 3504 if (sync->SyncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { 3505 /* if native fence fd still not created, return an error: */ 3506 _eglError(EGL_BAD_PARAMETER, "eglDupNativeFenceFDANDROID"); 3507 return EGL_NO_NATIVE_FENCE_FD_ANDROID; 3508 } 3509 3510 assert(sync_valid_fd(sync->SyncFd)); 3511 3512 return os_dupfd_cloexec(sync->SyncFd); 3513} 3514 3515static void 3516dri2_set_blob_cache_funcs(_EGLDisplay *disp, 3517 EGLSetBlobFuncANDROID set, 3518 EGLGetBlobFuncANDROID get) 3519{ 3520 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3521 dri2_dpy->blob->set_cache_funcs(dri2_dpy->dri_screen, 3522 disp->BlobCacheSet, 3523 disp->BlobCacheGet); 3524} 3525 3526static EGLint 3527dri2_client_wait_sync(_EGLDisplay *disp, _EGLSync *sync, 3528 EGLint flags, EGLTime timeout) 3529{ 3530 _EGLContext *ctx = _eglGetCurrentContext(); 3531 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3532 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3533 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3534 unsigned wait_flags = 0; 3535 3536 EGLint ret = EGL_CONDITION_SATISFIED_KHR; 3537 3538 /* The EGL_KHR_fence_sync spec states: 3539 * 3540 * "If no context is current for the bound API, 3541 * the EGL_SYNC_FLUSH_COMMANDS_BIT_KHR bit is ignored. 3542 */ 3543 if (dri2_ctx && flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) 3544 wait_flags |= __DRI2_FENCE_FLAG_FLUSH_COMMANDS; 3545 3546 /* the sync object should take a reference while waiting */ 3547 dri2_egl_ref_sync(dri2_sync); 3548 3549 switch (sync->Type) { 3550 case EGL_SYNC_FENCE_KHR: 3551 case EGL_SYNC_NATIVE_FENCE_ANDROID: 3552 case EGL_SYNC_CL_EVENT_KHR: 3553 if (dri2_dpy->fence->client_wait_sync(dri2_ctx ? dri2_ctx->dri_context : NULL, 3554 dri2_sync->fence, wait_flags, 3555 timeout)) 3556 dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR; 3557 else 3558 ret = EGL_TIMEOUT_EXPIRED_KHR; 3559 break; 3560 3561 case EGL_SYNC_REUSABLE_KHR: 3562 if (dri2_ctx && dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR && 3563 (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR)) { 3564 /* flush context if EGL_SYNC_FLUSH_COMMANDS_BIT_KHR is set */ 3565 dri2_gl_flush(); 3566 } 3567 3568 /* if timeout is EGL_FOREVER_KHR, it should wait without any timeout.*/ 3569 if (timeout == EGL_FOREVER_KHR) { 3570 mtx_lock(&dri2_sync->mutex); 3571 cnd_wait(&dri2_sync->cond, &dri2_sync->mutex); 3572 mtx_unlock(&dri2_sync->mutex); 3573 } else { 3574 /* if reusable sync has not been yet signaled */ 3575 if (dri2_sync->base.SyncStatus != EGL_SIGNALED_KHR) { 3576 /* timespecs for cnd_timedwait */ 3577 struct timespec current; 3578 struct timespec expire; 3579 3580 /* We override the clock to monotonic when creating the condition 3581 * variable. */ 3582 clock_gettime(CLOCK_MONOTONIC, ¤t); 3583 3584 /* calculating when to expire */ 3585 expire.tv_nsec = timeout % 1000000000L; 3586 expire.tv_sec = timeout / 1000000000L; 3587 3588 expire.tv_nsec += current.tv_nsec; 3589 expire.tv_sec += current.tv_sec; 3590 3591 /* expire.nsec now is a number between 0 and 1999999998 */ 3592 if (expire.tv_nsec > 999999999L) { 3593 expire.tv_sec++; 3594 expire.tv_nsec -= 1000000000L; 3595 } 3596 3597 mtx_lock(&dri2_sync->mutex); 3598 ret = cnd_timedwait(&dri2_sync->cond, &dri2_sync->mutex, &expire); 3599 mtx_unlock(&dri2_sync->mutex); 3600 3601 if (ret == thrd_busy) { 3602 if (dri2_sync->base.SyncStatus == EGL_UNSIGNALED_KHR) { 3603 ret = EGL_TIMEOUT_EXPIRED_KHR; 3604 } else { 3605 _eglError(EGL_BAD_ACCESS, "eglClientWaitSyncKHR"); 3606 ret = EGL_FALSE; 3607 } 3608 } 3609 } 3610 } 3611 break; 3612 } 3613 dri2_egl_unref_sync(dri2_dpy, dri2_sync); 3614 3615 return ret; 3616} 3617 3618static EGLBoolean 3619dri2_signal_sync(_EGLDisplay *disp, _EGLSync *sync, EGLenum mode) 3620{ 3621 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3622 EGLint ret; 3623 3624 if (sync->Type != EGL_SYNC_REUSABLE_KHR) 3625 return _eglError(EGL_BAD_MATCH, "eglSignalSyncKHR"); 3626 3627 if (mode != EGL_SIGNALED_KHR && mode != EGL_UNSIGNALED_KHR) 3628 return _eglError(EGL_BAD_ATTRIBUTE, "eglSignalSyncKHR"); 3629 3630 dri2_sync->base.SyncStatus = mode; 3631 3632 if (mode == EGL_SIGNALED_KHR) { 3633 ret = cnd_broadcast(&dri2_sync->cond); 3634 3635 /* fail to broadcast */ 3636 if (ret) 3637 return _eglError(EGL_BAD_ACCESS, "eglSignalSyncKHR"); 3638 } 3639 3640 return EGL_TRUE; 3641} 3642 3643static EGLint 3644dri2_server_wait_sync(_EGLDisplay *disp, _EGLSync *sync) 3645{ 3646 _EGLContext *ctx = _eglGetCurrentContext(); 3647 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3648 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3649 struct dri2_egl_sync *dri2_sync = dri2_egl_sync(sync); 3650 3651 dri2_dpy->fence->server_wait_sync(dri2_ctx->dri_context, 3652 dri2_sync->fence, 0); 3653 return EGL_TRUE; 3654} 3655 3656static int 3657dri2_interop_query_device_info(_EGLDisplay *disp, _EGLContext *ctx, 3658 struct mesa_glinterop_device_info *out) 3659{ 3660 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3661 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3662 3663 if (!dri2_dpy->interop) 3664 return MESA_GLINTEROP_UNSUPPORTED; 3665 3666 return dri2_dpy->interop->query_device_info(dri2_ctx->dri_context, out); 3667} 3668 3669static int 3670dri2_interop_export_object(_EGLDisplay *disp, _EGLContext *ctx, 3671 struct mesa_glinterop_export_in *in, 3672 struct mesa_glinterop_export_out *out) 3673{ 3674 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); 3675 struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx); 3676 3677 if (!dri2_dpy->interop) 3678 return MESA_GLINTEROP_UNSUPPORTED; 3679 3680 return dri2_dpy->interop->export_object(dri2_ctx->dri_context, in, out); 3681} 3682 3683const _EGLDriver _eglDriver = { 3684 .Initialize = dri2_initialize, 3685 .Terminate = dri2_terminate, 3686 .CreateContext = dri2_create_context, 3687 .DestroyContext = dri2_destroy_context, 3688 .MakeCurrent = dri2_make_current, 3689 .CreateWindowSurface = dri2_create_window_surface, 3690 .CreatePixmapSurface = dri2_create_pixmap_surface, 3691 .CreatePbufferSurface = dri2_create_pbuffer_surface, 3692 .DestroySurface = dri2_destroy_surface, 3693 .GetProcAddress = dri2_get_proc_address, 3694 .WaitClient = dri2_wait_client, 3695 .WaitNative = dri2_wait_native, 3696 .BindTexImage = dri2_bind_tex_image, 3697 .ReleaseTexImage = dri2_release_tex_image, 3698 .SwapInterval = dri2_swap_interval, 3699 .SwapBuffers = dri2_swap_buffers, 3700 .SwapBuffersWithDamageEXT = dri2_swap_buffers_with_damage, 3701 .SwapBuffersRegionNOK = dri2_swap_buffers_region, 3702 .SetDamageRegion = dri2_set_damage_region, 3703 .PostSubBufferNV = dri2_post_sub_buffer, 3704 .CopyBuffers = dri2_copy_buffers, 3705 .QueryBufferAge = dri2_query_buffer_age, 3706 .CreateImageKHR = dri2_create_image, 3707 .DestroyImageKHR = dri2_destroy_image_khr, 3708 .CreateWaylandBufferFromImageWL = dri2_create_wayland_buffer_from_image, 3709 .QuerySurface = dri2_query_surface, 3710 .QueryDriverName = dri2_query_driver_name, 3711 .QueryDriverConfig = dri2_query_driver_config, 3712#ifdef HAVE_LIBDRM 3713 .CreateDRMImageMESA = dri2_create_drm_image_mesa, 3714 .ExportDRMImageMESA = dri2_export_drm_image_mesa, 3715 .ExportDMABUFImageQueryMESA = dri2_export_dma_buf_image_query_mesa, 3716 .ExportDMABUFImageMESA = dri2_export_dma_buf_image_mesa, 3717 .QueryDmaBufFormatsEXT = dri2_query_dma_buf_formats, 3718 .QueryDmaBufModifiersEXT = dri2_query_dma_buf_modifiers, 3719#endif 3720#ifdef HAVE_WAYLAND_PLATFORM 3721 .BindWaylandDisplayWL = dri2_bind_wayland_display_wl, 3722 .UnbindWaylandDisplayWL = dri2_unbind_wayland_display_wl, 3723 .QueryWaylandBufferWL = dri2_query_wayland_buffer_wl, 3724#endif 3725 .GetSyncValuesCHROMIUM = dri2_get_sync_values_chromium, 3726 .CreateSyncKHR = dri2_create_sync, 3727 .ClientWaitSyncKHR = dri2_client_wait_sync, 3728 .SignalSyncKHR = dri2_signal_sync, 3729 .WaitSyncKHR = dri2_server_wait_sync, 3730 .DestroySyncKHR = dri2_destroy_sync, 3731 .GLInteropQueryDeviceInfo = dri2_interop_query_device_info, 3732 .GLInteropExportObject = dri2_interop_export_object, 3733 .DupNativeFenceFDANDROID = dri2_dup_native_fence_fd, 3734 .SetBlobCacheFuncsANDROID = dri2_set_blob_cache_funcs, 3735}; 3736