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